@hyve-sdk/js 1.5.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +244 -718
- package/dist/index.d.mts +141 -139
- package/dist/index.d.ts +141 -139
- package/dist/index.js +414 -526
- package/dist/index.mjs +409 -518
- package/dist/react.d.mts +453 -0
- package/dist/react.d.ts +453 -0
- package/dist/react.js +2173 -0
- package/dist/react.mjs +2151 -0
- package/package.json +30 -15
package/README.md
CHANGED
|
@@ -1,862 +1,388 @@
|
|
|
1
1
|
# @hyve-sdk/js
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for
|
|
3
|
+
TypeScript SDK for integrating games with the Hyve platform. Provides authentication, telemetry, persistent storage, ads, billing, and native bridge capabilities.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
bun add @hyve-sdk/js
|
|
9
|
-
# or
|
|
10
|
-
npm install @hyve-sdk/js
|
|
11
|
-
# or
|
|
12
8
|
pnpm add @hyve-sdk/js
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
##
|
|
11
|
+
## Quick Start
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
- **Modern & Legacy Token Support**: Dual authentication token formats
|
|
19
|
-
- **JWT Authentication**: Support for JWT tokens passed via URL parameters
|
|
20
|
-
- **API Integration**: Authenticated API calls with JWT token support
|
|
21
|
-
- **Inventory Management**: Built-in methods for user inventory operations
|
|
22
|
-
- **Telemetry Tracking**: Session-based analytics and event tracking
|
|
23
|
-
- **Billing Integration**: Unified billing for web (Stripe) and native (In-App Purchases) platforms
|
|
24
|
-
- **Ads Integration**: Google H5 Games Ads support (disabled by default)
|
|
25
|
-
- **Native Bridge**: Type-safe communication with React Native WebView apps
|
|
26
|
-
- **Logger**: Environment-aware logging system with configurable log levels
|
|
27
|
-
- **Security Utilities**: Domain validation and referrer checking
|
|
28
|
-
- **URL Parameter Parsing**: Easy extraction of authentication parameters
|
|
29
|
-
- **UUID Generation**: Built-in UUID v4 generation
|
|
30
|
-
|
|
31
|
-
## Core Components
|
|
32
|
-
|
|
33
|
-
### HyveClient
|
|
34
|
-
Main client class for SDK operations including authentication, telemetry, and API calls.
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
13
|
+
```ts
|
|
37
14
|
import { HyveClient } from "@hyve-sdk/js";
|
|
38
15
|
|
|
39
|
-
//
|
|
40
|
-
// Environment (dev/prod) is automatically detected from the parent page URL
|
|
16
|
+
// Authentication is automatic — the SDK reads hyve-access and game-id from the URL
|
|
41
17
|
const client = new HyveClient();
|
|
42
18
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (authenticated) {
|
|
47
|
-
console.log('User ID:', client.getUserId());
|
|
48
|
-
console.log('Session ID:', client.getSessionId());
|
|
49
|
-
console.log('Has JWT:', client.hasJwtToken());
|
|
50
|
-
console.log('Game ID:', client.getGameId());
|
|
51
|
-
}
|
|
19
|
+
console.log("User ID:", client.getUserId());
|
|
20
|
+
console.log("Game ID:", client.getGameId());
|
|
21
|
+
console.log("Authenticated:", client.isUserAuthenticated());
|
|
52
22
|
```
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
The SDK automatically detects whether to use dev or prod environment by checking the parent page URL:
|
|
56
|
-
- **Dev**: `marvin.dev.hyve.gg` or `dev.hyve.gg`
|
|
57
|
-
- **Prod**: `marvin.hyve.gg` or `hyve.gg`
|
|
24
|
+
The SDK reads authentication from URL parameters automatically during construction:
|
|
58
25
|
|
|
59
|
-
You can optionally override this for testing:
|
|
60
|
-
```typescript
|
|
61
|
-
// Only use for local testing - NOT for production code
|
|
62
|
-
const client = new HyveClient({
|
|
63
|
-
isDev: true, // Force dev mode for testing
|
|
64
|
-
apiBaseUrl: 'https://...' // Optional custom API URL
|
|
65
|
-
});
|
|
66
26
|
```
|
|
67
|
-
|
|
68
|
-
### Authentication Utilities
|
|
69
|
-
|
|
70
|
-
#### Parse URL Parameters
|
|
71
|
-
Extract authentication and game parameters from URL:
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
import { parseUrlParams } from "@hyve-sdk/js";
|
|
75
|
-
|
|
76
|
-
const params = parseUrlParams(window.location.search);
|
|
77
|
-
// Returns:
|
|
78
|
-
// {
|
|
79
|
-
// signature: string,
|
|
80
|
-
// message: string,
|
|
81
|
-
// gameStartTab: string,
|
|
82
|
-
// hyveToken: string,
|
|
83
|
-
// platform: string,
|
|
84
|
-
// hyveAccess: string, // JWT token
|
|
85
|
-
// gameId: string // Game identifier
|
|
86
|
-
// }
|
|
27
|
+
https://your-game.com?hyve-access=eyJhbGci...&game-id=my-game
|
|
87
28
|
```
|
|
88
29
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
import { verifyAuthentication } from "@hyve-sdk/js";
|
|
94
|
-
|
|
95
|
-
const result = verifyAuthentication({
|
|
96
|
-
hyveToken: params.hyveToken, // Modern token format
|
|
97
|
-
signature: params.signature, // Legacy format
|
|
98
|
-
message: params.message // Legacy format
|
|
99
|
-
});
|
|
30
|
+
**Environment detection** happens automatically from the parent page URL (games run in iframes):
|
|
31
|
+
- Dev: `marvin.dev.hyve.gg` or `dev.hyve.gg`
|
|
32
|
+
- Prod: `marvin.hyve.gg` or `hyve.gg`
|
|
33
|
+
- Override with `isDev` in config for local testing only
|
|
100
34
|
|
|
101
|
-
|
|
102
|
-
console.log('Authenticated address:', result.address);
|
|
103
|
-
console.log('Auth method used:', result.method); // 'modern' or 'legacy'
|
|
104
|
-
}
|
|
105
|
-
```
|
|
35
|
+
## React Integration
|
|
106
36
|
|
|
107
|
-
|
|
108
|
-
Verify modern authentication tokens with expiration:
|
|
37
|
+
Import from `@hyve-sdk/js/react` for the React provider and hook:
|
|
109
38
|
|
|
110
|
-
```
|
|
111
|
-
import {
|
|
39
|
+
```tsx
|
|
40
|
+
import { HyveSdkProvider, useHyveSdk } from "@hyve-sdk/js/react";
|
|
112
41
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<HyveSdkProvider config={{ isDev: true }}>
|
|
45
|
+
<Game />
|
|
46
|
+
</HyveSdkProvider>
|
|
47
|
+
);
|
|
117
48
|
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
#### Legacy Token Verification
|
|
121
|
-
Verify legacy signed messages with metadata:
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
import { handleVerifyMessage, validateSignature } from "@hyve-sdk/js";
|
|
125
|
-
|
|
126
|
-
// Method 1: Verify message with embedded metadata
|
|
127
|
-
const address = handleVerifyMessage(signature, message);
|
|
128
|
-
|
|
129
|
-
// Method 2: Simple signature validation
|
|
130
|
-
const isValid = validateSignature(signature, message, userId);
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Security Utilities
|
|
134
|
-
|
|
135
|
-
#### Domain Validation
|
|
136
|
-
Check if current domain is allowed:
|
|
137
49
|
|
|
138
|
-
|
|
139
|
-
|
|
50
|
+
function Game() {
|
|
51
|
+
const sdk = useHyveSdk();
|
|
140
52
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// Multiple domains with wildcard support
|
|
145
|
-
const allowed = isDomainAllowed(
|
|
146
|
-
['example.com', '*.subdomain.com'],
|
|
147
|
-
window.location.hostname
|
|
148
|
-
);
|
|
53
|
+
const handleScore = () => {
|
|
54
|
+
sdk.sendTelemetry("game", "player", "score_submitted", null, null, { score: 1000 });
|
|
55
|
+
};
|
|
149
56
|
|
|
150
|
-
|
|
57
|
+
return <button onClick={handleScore}>Submit Score</button>;
|
|
58
|
+
}
|
|
151
59
|
```
|
|
152
60
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
#### UUID Generation
|
|
156
|
-
Generate random UUID v4:
|
|
61
|
+
You can also pass a pre-created client:
|
|
157
62
|
|
|
158
|
-
```
|
|
159
|
-
|
|
63
|
+
```tsx
|
|
64
|
+
const client = new HyveClient({ isDev: true });
|
|
160
65
|
|
|
161
|
-
|
|
66
|
+
<HyveSdkProvider client={client}>
|
|
67
|
+
<App />
|
|
68
|
+
</HyveSdkProvider>
|
|
162
69
|
```
|
|
163
70
|
|
|
164
|
-
## Telemetry
|
|
165
|
-
|
|
166
|
-
### Send Telemetry Events
|
|
167
|
-
Track user actions and game events using JWT authentication:
|
|
71
|
+
## Telemetry
|
|
168
72
|
|
|
169
|
-
```
|
|
170
|
-
// Send a user-level telemetry event
|
|
171
|
-
// Game ID is automatically extracted from 'game-id' URL parameter
|
|
73
|
+
```ts
|
|
172
74
|
await client.sendTelemetry(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
{
|
|
179
|
-
button: 'attack-btn',
|
|
180
|
-
screenPosition: { x: 100, y: 200 },
|
|
75
|
+
"game", // location
|
|
76
|
+
"player", // category
|
|
77
|
+
"action", // action
|
|
78
|
+
"combat", // sub-category (optional)
|
|
79
|
+
"attack", // sub-action (optional)
|
|
80
|
+
{ // event details (optional)
|
|
181
81
|
damage: 100,
|
|
182
|
-
targetId:
|
|
183
|
-
|
|
184
|
-
level: 3
|
|
185
|
-
},
|
|
186
|
-
'web-chrome' // Platform ID (optional)
|
|
82
|
+
targetId: "enemy-123",
|
|
83
|
+
}
|
|
187
84
|
);
|
|
188
85
|
```
|
|
189
86
|
|
|
190
|
-
|
|
191
|
-
- Requires JWT token (from `hyve-access` URL parameter)
|
|
192
|
-
- Requires authenticated user
|
|
193
|
-
- Requires game ID (from `game-id` URL parameter)
|
|
194
|
-
- User ID is automatically extracted from JWT (cannot be spoofed)
|
|
87
|
+
Requires a valid `hyve-access` JWT and `game-id` in the URL.
|
|
195
88
|
|
|
196
|
-
|
|
197
|
-
- `hyve-access` - JWT authentication token
|
|
198
|
-
- `game-id` - Game identifier (associates all telemetry with this game)
|
|
199
|
-
- `hyve-token` or `signature`+`message` - For user authentication
|
|
89
|
+
## Persistent Game Data
|
|
200
90
|
|
|
201
|
-
|
|
202
|
-
- Automatically includes `session_id` and `game_id` from client
|
|
203
|
-
- Objects in `event_details` are auto-stringified to JSON
|
|
204
|
-
- Validates `event_details` is valid JSON before sending (returns false if invalid)
|
|
205
|
-
- All events tied to authenticated user identity
|
|
91
|
+
Save and retrieve game data with either cloud (default) or local storage:
|
|
206
92
|
|
|
207
|
-
|
|
93
|
+
```ts
|
|
94
|
+
// Save a value
|
|
95
|
+
await client.saveGameData("player_level", 5);
|
|
96
|
+
await client.saveGameData("settings", { volume: 0.8, fullscreen: true });
|
|
208
97
|
|
|
209
|
-
|
|
210
|
-
|
|
98
|
+
// Get a value
|
|
99
|
+
const item = await client.getGameData("player_level");
|
|
100
|
+
console.log(item?.value); // 5
|
|
211
101
|
|
|
212
|
-
|
|
213
|
-
|
|
102
|
+
// Batch save
|
|
103
|
+
await client.batchSaveGameData([
|
|
104
|
+
{ key: "coins", value: 1200 },
|
|
105
|
+
{ key: "lives", value: 3 },
|
|
106
|
+
]);
|
|
214
107
|
|
|
215
|
-
//
|
|
216
|
-
await client.
|
|
108
|
+
// Batch get
|
|
109
|
+
const items = await client.getMultipleGameData(["coins", "lives"]);
|
|
217
110
|
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
console.log('Game ID:', client.getGameId());
|
|
222
|
-
}
|
|
111
|
+
// Delete
|
|
112
|
+
await client.deleteGameData("temp_key");
|
|
113
|
+
await client.deleteMultipleGameData(["key1", "key2"]);
|
|
223
114
|
```
|
|
224
115
|
|
|
225
|
-
###
|
|
226
|
-
Make authenticated API requests:
|
|
227
|
-
|
|
228
|
-
```typescript
|
|
229
|
-
// GET request
|
|
230
|
-
const userData = await client.callApi('/api/v1/user');
|
|
231
|
-
|
|
232
|
-
// POST request with body
|
|
233
|
-
const result = await client.callApi('/api/v1/game/score', {
|
|
234
|
-
method: 'POST',
|
|
235
|
-
body: JSON.stringify({ score: 1000 })
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// With TypeScript typing
|
|
239
|
-
interface UserData {
|
|
240
|
-
id: string;
|
|
241
|
-
username: string;
|
|
242
|
-
}
|
|
243
|
-
const user = await client.callApi<UserData>('/api/v1/user');
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Inventory Management
|
|
247
|
-
|
|
248
|
-
#### Get User Inventory
|
|
249
|
-
Retrieve all inventory items:
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
const inventory = await client.getInventory();
|
|
253
|
-
|
|
254
|
-
console.log(`Total items: ${inventory.total_count}`);
|
|
255
|
-
inventory.items.forEach(item => {
|
|
256
|
-
console.log(`${item.item_type}: ${item.quantity}x`);
|
|
257
|
-
});
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
**Response Type:**
|
|
261
|
-
```typescript
|
|
262
|
-
interface Inventory {
|
|
263
|
-
items: InventoryItem[];
|
|
264
|
-
total_count: number;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
interface InventoryItem {
|
|
268
|
-
id: string;
|
|
269
|
-
user_id: string;
|
|
270
|
-
item_type: string;
|
|
271
|
-
item_id: string;
|
|
272
|
-
quantity: number;
|
|
273
|
-
metadata?: Record<string, any>;
|
|
274
|
-
created_at: string;
|
|
275
|
-
updated_at: string;
|
|
276
|
-
}
|
|
277
|
-
```
|
|
116
|
+
### Storage Modes
|
|
278
117
|
|
|
279
|
-
|
|
280
|
-
|
|
118
|
+
```ts
|
|
119
|
+
// Set mode at construction
|
|
120
|
+
const client = new HyveClient({ storageMode: "local" });
|
|
281
121
|
|
|
282
|
-
|
|
283
|
-
|
|
122
|
+
// Or override per-call
|
|
123
|
+
await client.saveGameData("key", "value", "local");
|
|
124
|
+
await client.getGameData("key", "cloud");
|
|
284
125
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
console.log('Metadata:', item.metadata);
|
|
289
|
-
}
|
|
126
|
+
// Change mode at runtime
|
|
127
|
+
client.configureStorage("cloud");
|
|
128
|
+
console.log(client.getStorageMode()); // "cloud"
|
|
290
129
|
```
|
|
291
130
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
## Ads Integration
|
|
297
|
-
|
|
298
|
-
The SDK includes support for Google H5 Games Ads. **Ads are disabled by default** and must be explicitly enabled in the configuration.
|
|
131
|
+
| Mode | Description |
|
|
132
|
+
|------|-------------|
|
|
133
|
+
| `cloud` | Synced to backend API (default) |
|
|
134
|
+
| `local` | Browser `localStorage`, device-only |
|
|
299
135
|
|
|
300
|
-
|
|
136
|
+
## Ads
|
|
301
137
|
|
|
302
|
-
|
|
303
|
-
import { HyveClient } from "@hyve-sdk/js";
|
|
138
|
+
Ads are disabled by default and must be explicitly configured.
|
|
304
139
|
|
|
305
|
-
|
|
140
|
+
```ts
|
|
306
141
|
const client = new HyveClient({
|
|
307
142
|
ads: {
|
|
308
|
-
enabled: true,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
game.pause();
|
|
314
|
-
},
|
|
315
|
-
onAfterAd: (type) => {
|
|
316
|
-
console.log('Resuming game after ad');
|
|
317
|
-
game.resume();
|
|
318
|
-
},
|
|
319
|
-
onRewardEarned: () => {
|
|
320
|
-
console.log('User earned reward!');
|
|
321
|
-
player.coins += 100;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
143
|
+
enabled: true,
|
|
144
|
+
onBeforeAd: (type) => game.pause(),
|
|
145
|
+
onAfterAd: (type) => game.resume(),
|
|
146
|
+
onRewardEarned: () => { player.coins += 100; },
|
|
147
|
+
},
|
|
324
148
|
});
|
|
325
149
|
|
|
326
|
-
|
|
327
|
-
const result = await client.showAd('rewarded');
|
|
150
|
+
const result = await client.showAd("rewarded");
|
|
328
151
|
if (result.success) {
|
|
329
|
-
console.log(
|
|
152
|
+
console.log("User watched the ad");
|
|
330
153
|
}
|
|
331
154
|
|
|
332
|
-
await client.showAd(
|
|
333
|
-
await client.showAd(
|
|
155
|
+
await client.showAd("interstitial"); // between levels
|
|
156
|
+
await client.showAd("preroll"); // game start
|
|
334
157
|
```
|
|
335
158
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
159
|
+
| Ad Type | Use Case |
|
|
160
|
+
|---------|----------|
|
|
161
|
+
| `rewarded` | User watches full ad for a reward |
|
|
162
|
+
| `interstitial` | Between levels or game screens |
|
|
163
|
+
| `preroll` | Before the game starts |
|
|
339
164
|
|
|
340
|
-
|
|
341
|
-
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
342
|
-
<script>
|
|
343
|
-
window.adBreak = window.adBreak || function(o) {
|
|
344
|
-
(window.adsbygoogle = window.adsbygoogle || []).push(o);
|
|
345
|
-
};
|
|
346
|
-
window.adConfig = window.adConfig || function(o) {
|
|
347
|
-
(window.adsbygoogle = window.adsbygoogle || []).push(o);
|
|
348
|
-
};
|
|
349
|
-
</script>
|
|
350
|
-
```
|
|
165
|
+
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.
|
|
351
166
|
|
|
352
|
-
|
|
167
|
+
## Platform Integrations
|
|
353
168
|
|
|
354
|
-
|
|
355
|
-
|------|----------|
|
|
356
|
-
| `rewarded` | User watches full ad for reward (coins, lives, etc.) |
|
|
357
|
-
| `interstitial` | Between levels or game screens |
|
|
358
|
-
| `preroll` | Before game starts |
|
|
359
|
-
|
|
360
|
-
### Configuration
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
interface AdConfig {
|
|
364
|
-
enabled?: boolean; // Enable/disable ads (default: false)
|
|
365
|
-
sound?: 'on' | 'off'; // Sound setting (default: 'on')
|
|
366
|
-
debug?: boolean; // Enable debug logging (default: false)
|
|
367
|
-
onBeforeAd?: (type) => void; // Called before ad shows
|
|
368
|
-
onAfterAd?: (type) => void; // Called after ad finishes
|
|
369
|
-
onRewardEarned?: () => void; // Called when user earns reward
|
|
370
|
-
}
|
|
371
|
-
```
|
|
169
|
+
### CrazyGames
|
|
372
170
|
|
|
373
|
-
|
|
171
|
+
When running on CrazyGames, the SDK auto-initializes the CrazyGames SDK and routes ads through it. Use these additional lifecycle methods:
|
|
374
172
|
|
|
375
|
-
```
|
|
376
|
-
//
|
|
377
|
-
client.
|
|
173
|
+
```ts
|
|
174
|
+
// Call when gameplay begins (required by CrazyGames policy)
|
|
175
|
+
await client.gameplayStart();
|
|
378
176
|
|
|
379
|
-
//
|
|
380
|
-
|
|
177
|
+
// Call when gameplay stops (paused, died, menu, etc.)
|
|
178
|
+
await client.gameplayStop();
|
|
381
179
|
|
|
382
|
-
//
|
|
383
|
-
client.
|
|
384
|
-
client.areAdsReady(); // Boolean
|
|
180
|
+
// Trigger a celebration effect on the CrazyGames website
|
|
181
|
+
await client.happytime();
|
|
385
182
|
```
|
|
386
183
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
**Requirements:**
|
|
390
|
-
- JWT token must be available (via `hyve-access` URL parameter)
|
|
391
|
-
- User must be authenticated
|
|
392
|
-
|
|
393
|
-
## Billing Integration
|
|
184
|
+
### Playgama
|
|
394
185
|
|
|
395
|
-
|
|
186
|
+
When running on Playgama, the SDK auto-initializes the Playgama Bridge and routes ads through it. No additional setup required.
|
|
396
187
|
|
|
397
|
-
|
|
188
|
+
## Billing
|
|
398
189
|
|
|
399
|
-
|
|
400
|
-
import { HyveClient } from "@hyve-sdk/js";
|
|
190
|
+
Billing supports web (Stripe) and native (In-App Purchases) — platform is detected automatically.
|
|
401
191
|
|
|
402
|
-
|
|
192
|
+
```ts
|
|
403
193
|
const client = new HyveClient({
|
|
404
194
|
billing: {
|
|
405
|
-
stripePublishableKey:
|
|
406
|
-
|
|
407
|
-
}
|
|
195
|
+
stripePublishableKey: "pk_live_...",
|
|
196
|
+
},
|
|
408
197
|
});
|
|
409
198
|
|
|
410
|
-
|
|
411
|
-
await client.authenticateFromUrl(window.location.search);
|
|
412
|
-
|
|
413
|
-
// Initialize billing (uses client's userId and gameId automatically)
|
|
414
|
-
const initialized = await client.initializeBilling();
|
|
415
|
-
|
|
416
|
-
if (initialized && client.isBillingAvailable()) {
|
|
417
|
-
// Set up purchase callbacks
|
|
199
|
+
if (client.isBillingAvailable()) {
|
|
418
200
|
client.onPurchaseComplete((result) => {
|
|
419
|
-
console.log(
|
|
420
|
-
// Refresh inventory
|
|
421
|
-
client.getInventory().then(inv => console.log('Updated inventory:', inv));
|
|
201
|
+
console.log("Purchase successful:", result.transactionId);
|
|
422
202
|
});
|
|
423
203
|
|
|
424
204
|
client.onPurchaseError((result) => {
|
|
425
|
-
console.error(
|
|
205
|
+
console.error("Purchase failed:", result.error?.message);
|
|
426
206
|
});
|
|
427
207
|
|
|
428
|
-
// Get available products
|
|
429
208
|
const products = await client.getBillingProducts();
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
// Purchase a product
|
|
433
|
-
await client.purchaseProduct('price_1234', {
|
|
434
|
-
elementId: 'stripe-checkout-element' // For web platform
|
|
435
|
-
});
|
|
209
|
+
await client.purchaseProduct("price_1234");
|
|
436
210
|
}
|
|
437
211
|
```
|
|
438
212
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
The SDK automatically detects the platform and uses the appropriate billing method:
|
|
442
|
-
|
|
443
|
-
| Platform | Payment Method | Requirements |
|
|
444
|
-
|----------|---------------|--------------|
|
|
445
|
-
| Web | Stripe Embedded Checkout | Stripe publishable key |
|
|
446
|
-
| Native (iOS/Android) | In-App Purchases | Native app integration |
|
|
447
|
-
|
|
448
|
-
### Prerequisites
|
|
449
|
-
|
|
450
|
-
For web platform, add a container element for Stripe checkout:
|
|
213
|
+
For web, add a container element for the Stripe checkout UI:
|
|
451
214
|
|
|
452
215
|
```html
|
|
453
216
|
<div id="stripe-checkout-element"></div>
|
|
454
217
|
```
|
|
455
218
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
### Configuration
|
|
461
|
-
|
|
462
|
-
```typescript
|
|
463
|
-
interface BillingConfig {
|
|
464
|
-
stripePublishableKey?: string; // Stripe key for web (required for web)
|
|
465
|
-
checkoutUrl?: string; // API endpoint for checkout
|
|
466
|
-
gameId?: number; // Game identifier
|
|
467
|
-
userId?: string; // User identifier
|
|
468
|
-
}
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
Note: When using billing through HyveClient, `userId` and `gameId` are automatically populated from the authenticated user.
|
|
472
|
-
|
|
473
|
-
### Methods
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
// Configure billing after initialization
|
|
477
|
-
client.configureBilling({
|
|
478
|
-
stripePublishableKey: 'pk_live_...',
|
|
479
|
-
checkoutUrl: 'https://api.example.com'
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
// Initialize billing
|
|
483
|
-
await client.initializeBilling();
|
|
484
|
-
|
|
485
|
-
// Check platform and availability
|
|
486
|
-
const platform = client.getBillingPlatform(); // 'web' | 'native' | 'unknown'
|
|
487
|
-
const available = client.isBillingAvailable(); // Boolean
|
|
488
|
-
|
|
489
|
-
// Get products
|
|
490
|
-
const products = await client.getBillingProducts();
|
|
491
|
-
|
|
492
|
-
// Purchase a product
|
|
493
|
-
const result = await client.purchaseProduct(productId, {
|
|
494
|
-
elementId: 'stripe-checkout-element' // Optional, defaults to 'stripe-checkout-element'
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
// Set up callbacks
|
|
498
|
-
client.onPurchaseComplete((result) => {
|
|
499
|
-
console.log('Success!', result);
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
client.onPurchaseError((result) => {
|
|
503
|
-
console.error('Failed:', result.error);
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
// Optional: Listen to billing logs
|
|
507
|
-
client.onBillingLog((level, message, data) => {
|
|
508
|
-
console.log(`[${level}] ${message}`, data);
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
// Clean up checkout UI
|
|
512
|
-
client.unmountBillingCheckout();
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
### Product Interface
|
|
516
|
-
|
|
517
|
-
```typescript
|
|
518
|
-
interface BillingProduct {
|
|
519
|
-
productId: string; // Product/price ID
|
|
520
|
-
title: string; // Product name
|
|
521
|
-
description: string; // Product description
|
|
522
|
-
price: number; // Price in dollars (e.g., 9.99)
|
|
523
|
-
localizedPrice: string; // Formatted price (e.g., "$9.99")
|
|
524
|
-
currency: string; // Currency code (e.g., "USD")
|
|
525
|
-
}
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
### Purchase Result
|
|
529
|
-
|
|
530
|
-
```typescript
|
|
531
|
-
interface PurchaseResult {
|
|
532
|
-
success: boolean;
|
|
533
|
-
productId: string;
|
|
534
|
-
transactionId?: string;
|
|
535
|
-
transactionDate?: string;
|
|
536
|
-
error?: {
|
|
537
|
-
code: string;
|
|
538
|
-
message: string;
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Complete Example with Telemetry
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
const client = new HyveClient({
|
|
547
|
-
billing: {
|
|
548
|
-
stripePublishableKey: process.env.VITE_STRIPE_KEY,
|
|
549
|
-
checkoutUrl: process.env.VITE_CHECKOUT_URL,
|
|
550
|
-
}
|
|
551
|
-
});
|
|
219
|
+
| Platform | Payment Method | Detection |
|
|
220
|
+
|----------|---------------|-----------|
|
|
221
|
+
| Web | Stripe Embedded Checkout | Default |
|
|
222
|
+
| Native iOS/Android | In-App Purchases | `ReactNativeWebView` in window |
|
|
552
223
|
|
|
553
|
-
|
|
554
|
-
await client.authenticateFromUrl();
|
|
555
|
-
|
|
556
|
-
// Initialize billing
|
|
557
|
-
await client.initializeBilling();
|
|
558
|
-
|
|
559
|
-
// Set up callbacks with telemetry
|
|
560
|
-
client.onPurchaseComplete((result) => {
|
|
561
|
-
// Send success telemetry
|
|
562
|
-
client.sendTelemetry(
|
|
563
|
-
'shop',
|
|
564
|
-
'purchase',
|
|
565
|
-
'complete',
|
|
566
|
-
'success',
|
|
567
|
-
null,
|
|
568
|
-
{ productId: result.productId, transactionId: result.transactionId }
|
|
569
|
-
);
|
|
224
|
+
## Native Bridge
|
|
570
225
|
|
|
571
|
-
|
|
572
|
-
client.getInventory();
|
|
573
|
-
});
|
|
226
|
+
Type-safe bidirectional communication between your web game and a React Native WebView host.
|
|
574
227
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
client.sendTelemetry(
|
|
578
|
-
'shop',
|
|
579
|
-
'purchase',
|
|
580
|
-
'error',
|
|
581
|
-
'failed',
|
|
582
|
-
null,
|
|
583
|
-
{
|
|
584
|
-
productId: result.productId,
|
|
585
|
-
errorCode: result.error?.code,
|
|
586
|
-
errorMessage: result.error?.message
|
|
587
|
-
}
|
|
588
|
-
);
|
|
589
|
-
});
|
|
228
|
+
```ts
|
|
229
|
+
import { NativeBridge } from "@hyve-sdk/js";
|
|
590
230
|
|
|
591
|
-
// Get and display products
|
|
592
|
-
const products = await client.getBillingProducts();
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
See [docs/examples/billing-with-client-example.ts](./docs/examples/billing-with-client-example.ts) for detailed examples including React components and Phaser integration.
|
|
596
|
-
|
|
597
|
-
**Requirements:**
|
|
598
|
-
- JWT token must be available (via `hyve-access` URL parameter)
|
|
599
|
-
- User must be authenticated
|
|
600
|
-
- Game ID must be available (via `game-id` URL parameter or JWT)
|
|
601
|
-
- For web: Stripe publishable key required
|
|
602
|
-
- For native: Mobile app must implement Native Bridge billing integration
|
|
603
|
-
|
|
604
|
-
## Native Bridge (React Native WebView)
|
|
605
|
-
|
|
606
|
-
Provides type-safe bidirectional communication between your web application and the React Native mobile app.
|
|
607
|
-
|
|
608
|
-
### Quick Start
|
|
609
|
-
|
|
610
|
-
```typescript
|
|
611
|
-
import { NativeBridge, NativeMessageType } from "@hyve-sdk/js";
|
|
612
|
-
|
|
613
|
-
// Initialize on app start
|
|
614
231
|
if (NativeBridge.isNativeContext()) {
|
|
615
232
|
NativeBridge.initialize();
|
|
616
|
-
}
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
### Check IAP Availability
|
|
620
|
-
|
|
621
|
-
Request information about In-App Purchase availability:
|
|
622
|
-
|
|
623
|
-
```typescript
|
|
624
|
-
// Register response handler
|
|
625
|
-
NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
|
|
626
|
-
if (payload.available) {
|
|
627
|
-
console.log("IAP is available on this device");
|
|
628
|
-
// Show purchase UI
|
|
629
|
-
} else {
|
|
630
|
-
console.log("IAP is not available");
|
|
631
|
-
// Hide purchase features
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
|
|
635
|
-
// Send request
|
|
636
|
-
NativeBridge.checkIAPAvailability();
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
### Request Push Notifications
|
|
640
|
-
|
|
641
|
-
Request notification permissions from the native app:
|
|
642
|
-
|
|
643
|
-
```typescript
|
|
644
|
-
// Register response handlers
|
|
645
|
-
NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
|
|
646
|
-
console.log("Push notifications enabled");
|
|
647
|
-
console.log("Token:", payload?.token);
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
|
|
651
|
-
console.log("Push notifications disabled");
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
// Send request
|
|
655
|
-
NativeBridge.requestNotificationPermission();
|
|
656
|
-
```
|
|
657
|
-
|
|
658
|
-
### Send Custom Messages
|
|
659
233
|
|
|
660
|
-
|
|
234
|
+
// Listen for IAP availability
|
|
235
|
+
NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
|
|
236
|
+
if (payload.available) {
|
|
237
|
+
console.log("IAP available on:", payload.platform);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
NativeBridge.checkIAPAvailability();
|
|
661
241
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
});
|
|
242
|
+
// Request push notification permission
|
|
243
|
+
NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
|
|
244
|
+
console.log("Token:", payload?.token);
|
|
245
|
+
});
|
|
246
|
+
NativeBridge.requestNotificationPermission();
|
|
668
247
|
|
|
669
|
-
//
|
|
670
|
-
NativeBridge.
|
|
671
|
-
|
|
672
|
-
|
|
248
|
+
// Send/receive custom messages
|
|
249
|
+
NativeBridge.send("GAME_EVENT", { action: "level_complete", level: 3 });
|
|
250
|
+
NativeBridge.on("CUSTOM_RESPONSE", (payload) => {
|
|
251
|
+
console.log("Received:", payload);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
673
254
|
```
|
|
674
255
|
|
|
675
|
-
###
|
|
676
|
-
|
|
677
|
-
**Web → Native:**
|
|
678
|
-
- `CHECK_IAP_AVAILABILITY` - Check if IAP is available
|
|
679
|
-
- `REQUEST_NOTIFICATION_PERMISSION` - Request push notification permission
|
|
680
|
-
|
|
681
|
-
**Native → Web:**
|
|
682
|
-
- `IAP_AVAILABILITY_RESULT` - Response with IAP availability
|
|
683
|
-
- `PUSH_PERMISSION_GRANTED` - Push permission granted
|
|
684
|
-
- `PUSH_PERMISSION_DENIED` - Push permission denied
|
|
685
|
-
|
|
686
|
-
### API Reference
|
|
256
|
+
### NativeBridge API
|
|
687
257
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
258
|
+
| Method | Description |
|
|
259
|
+
|--------|-------------|
|
|
260
|
+
| `isNativeContext()` | Check if running in React Native WebView |
|
|
261
|
+
| `initialize()` | Start the message listener |
|
|
262
|
+
| `send(type, payload?)` | Send a message to the native app |
|
|
263
|
+
| `on(type, handler)` | Register a message handler |
|
|
264
|
+
| `off(type)` | Remove a message handler |
|
|
265
|
+
| `clearHandlers()` | Remove all handlers |
|
|
266
|
+
| `checkIAPAvailability()` | Request IAP availability from native |
|
|
267
|
+
| `requestNotificationPermission()` | Request push notification permission |
|
|
698
268
|
|
|
699
269
|
## Logger
|
|
700
270
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
### Quick Start
|
|
704
|
-
|
|
705
|
-
```typescript
|
|
271
|
+
```ts
|
|
706
272
|
import { logger } from "@hyve-sdk/js";
|
|
707
273
|
|
|
708
|
-
logger.debug("Debug
|
|
274
|
+
logger.debug("Debug info", { data: "value" });
|
|
709
275
|
logger.info("Informational message");
|
|
710
276
|
logger.warn("Warning message");
|
|
711
277
|
logger.error("Error message", error);
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
### Configuration
|
|
715
|
-
|
|
716
|
-
**Automatic Behavior:**
|
|
717
|
-
- **Development** (`NODE_ENV !== 'production'`): Logging enabled by default
|
|
718
|
-
- **Production** (`NODE_ENV === 'production'`): Logging disabled by default
|
|
719
278
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
**Node.js Override:**
|
|
727
|
-
```bash
|
|
728
|
-
HYVE_SDK_LOG_LEVEL=error,warn node app.js
|
|
279
|
+
// Namespaced child logger
|
|
280
|
+
const gameLogger = logger.child("Game");
|
|
281
|
+
gameLogger.info("Game started");
|
|
282
|
+
// Output: [Hyve SDK] [Game] [INFO] [timestamp] Game started
|
|
729
283
|
```
|
|
730
284
|
|
|
731
|
-
|
|
732
|
-
```typescript
|
|
733
|
-
import { Logger } from "@hyve-sdk/js";
|
|
285
|
+
Override log level in the browser:
|
|
734
286
|
|
|
735
|
-
|
|
736
|
-
|
|
287
|
+
```js
|
|
288
|
+
localStorage.setItem("HYVE_SDK_LOG_LEVEL", "error,warn");
|
|
737
289
|
```
|
|
738
290
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
Create namespaced loggers for different parts of your application:
|
|
291
|
+
## API Reference
|
|
742
292
|
|
|
743
|
-
|
|
744
|
-
import { logger } from "@hyve-sdk/js";
|
|
293
|
+
### HyveClient Config
|
|
745
294
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
//
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
295
|
+
```ts
|
|
296
|
+
new HyveClient(config?: {
|
|
297
|
+
isDev?: boolean; // Override env detection (local testing only)
|
|
298
|
+
apiBaseUrl?: string; // Override API base URL
|
|
299
|
+
storageMode?: "cloud" | "local";
|
|
300
|
+
ads?: AdConfig;
|
|
301
|
+
billing?: BillingConfig;
|
|
302
|
+
})
|
|
753
303
|
```
|
|
754
304
|
|
|
755
|
-
### Features
|
|
756
|
-
|
|
757
|
-
- **Automatic environment detection**: Enables/disables based on NODE_ENV
|
|
758
|
-
- **Configurable log levels**: debug, info, warn, error
|
|
759
|
-
- **Timestamps**: All logs include ISO 8601 timestamps
|
|
760
|
-
- **Prefixed output**: All logs prefixed with `[Hyve SDK]`
|
|
761
|
-
- **Child loggers**: Create namespaced loggers for different modules
|
|
762
|
-
- **Browser storage**: Log level persists in localStorage
|
|
763
|
-
|
|
764
|
-
## Client Methods Reference
|
|
765
|
-
|
|
766
305
|
### Authentication
|
|
767
|
-
- `authenticateFromUrl(urlParams?)` - Authenticate from URL parameters (extracts JWT, game ID, user auth)
|
|
768
|
-
- `getUserId()` - Get authenticated user ID (address)
|
|
769
|
-
- `getSessionId()` - Get unique session ID
|
|
770
|
-
- `getGameId()` - Get game ID from URL parameters
|
|
771
|
-
- `isUserAuthenticated()` - Check if user is authenticated
|
|
772
|
-
- `hasJwtToken()` - Check if JWT token is available
|
|
773
|
-
- `getJwtToken()` - Get JWT token string
|
|
774
|
-
- `logout()` - Clear user authentication
|
|
775
|
-
- `reset()` - Reset client state with new session
|
|
776
|
-
|
|
777
|
-
### API Calls
|
|
778
|
-
- `callApi<T>(endpoint, options?)` - Generic authenticated API call
|
|
779
|
-
- `getInventory()` - Get user's inventory
|
|
780
|
-
- `getInventoryItem(itemId)` - Get specific inventory item
|
|
781
|
-
|
|
782
|
-
### Telemetry
|
|
783
|
-
- `sendTelemetry(location, category, action, subCategory?, subAction?, details?, platformId?)` - Send JWT-authenticated analytics event (uses game ID from URL)
|
|
784
|
-
- `updateTelemetryConfig(config)` - Update telemetry settings
|
|
785
|
-
|
|
786
|
-
### Ads
|
|
787
|
-
- `configureAds(config)` - Configure ads service
|
|
788
|
-
- `showAd(type)` - Show an ad ('rewarded', 'interstitial', or 'preroll')
|
|
789
|
-
- `areAdsEnabled()` - Check if ads are enabled
|
|
790
|
-
- `areAdsReady()` - Check if ads are ready to show
|
|
791
|
-
|
|
792
|
-
### Configuration
|
|
793
|
-
- `getApiBaseUrl()` - Get current API base URL
|
|
794
|
-
- `updateTelemetryConfig(config)` - Update client configuration
|
|
795
|
-
|
|
796
|
-
## Authentication Flow
|
|
797
|
-
|
|
798
|
-
### Modern Token Flow (Recommended)
|
|
799
|
-
1. User authenticates on platform
|
|
800
|
-
2. Platform generates hyve-token: `signature.address.random.timestamp`
|
|
801
|
-
3. Token passed via URL parameter `hyve-token`
|
|
802
|
-
4. SDK verifies token with `verifyHyveToken()` or `verifyAuthentication()`
|
|
803
306
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
307
|
+
| Method | Returns | Description |
|
|
308
|
+
|--------|---------|-------------|
|
|
309
|
+
| `getUserId()` | `string \| null` | Authenticated user ID |
|
|
310
|
+
| `getGameId()` | `string \| null` | Game ID from URL or JWT |
|
|
311
|
+
| `getSessionId()` | `string` | Unique session ID |
|
|
312
|
+
| `getJwtToken()` | `string \| null` | Raw JWT string |
|
|
313
|
+
| `isUserAuthenticated()` | `boolean` | Whether a user ID was extracted |
|
|
314
|
+
| `hasJwtToken()` | `boolean` | Whether a JWT is present |
|
|
315
|
+
| `logout()` | `void` | Clear auth state |
|
|
316
|
+
| `reset()` | `void` | Clear auth and generate new session ID |
|
|
317
|
+
|
|
318
|
+
### API
|
|
319
|
+
|
|
320
|
+
| Method | Returns | Description |
|
|
321
|
+
|--------|---------|-------------|
|
|
322
|
+
| `callApi<T>(endpoint, options?)` | `Promise<T>` | Authenticated fetch to the Hyve API |
|
|
323
|
+
| `getInventory()` | `Promise<Inventory>` | Get user inventory |
|
|
324
|
+
| `getInventoryItem(itemId)` | `Promise<InventoryItem>` | Get a specific inventory item |
|
|
808
325
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
- **Token Expiration**: Modern tokens expire after 10 minutes by default
|
|
812
|
-
- **Domain Validation**: Always validate origin domains in production
|
|
813
|
-
- **Signature Verification**: All signatures verified using ethers.js
|
|
814
|
-
- **Localhost Exception**: localhost always allowed for development
|
|
815
|
-
|
|
816
|
-
## TypeScript Support
|
|
326
|
+
### Telemetry
|
|
817
327
|
|
|
818
|
-
|
|
328
|
+
| Method | Returns | Description |
|
|
329
|
+
|--------|---------|-------------|
|
|
330
|
+
| `sendTelemetry(location, category, action, subCategory?, subAction?, details?)` | `Promise<boolean>` | Send an analytics event |
|
|
331
|
+
| `updateTelemetryConfig(config)` | `void` | Update telemetry settings at runtime |
|
|
819
332
|
|
|
820
|
-
|
|
333
|
+
### Storage
|
|
821
334
|
|
|
822
|
-
|
|
823
|
-
|
|
335
|
+
| Method | Returns | Description |
|
|
336
|
+
|--------|---------|-------------|
|
|
337
|
+
| `saveGameData(key, value, storage?)` | `Promise<SaveGameDataResponse>` | Save a single value |
|
|
338
|
+
| `batchSaveGameData(items, storage?)` | `Promise<SaveGameDataResponse>` | Save multiple values |
|
|
339
|
+
| `getGameData(key, storage?)` | `Promise<GameDataItem \| null>` | Get a single value |
|
|
340
|
+
| `getMultipleGameData(keys, storage?)` | `Promise<GameDataItem[]>` | Get multiple values |
|
|
341
|
+
| `deleteGameData(key, storage?)` | `Promise<boolean>` | Delete a single value |
|
|
342
|
+
| `deleteMultipleGameData(keys, storage?)` | `Promise<number>` | Delete multiple values |
|
|
343
|
+
| `configureStorage(mode)` | `void` | Set default storage mode |
|
|
344
|
+
| `getStorageMode()` | `"cloud" \| "local"` | Get current storage mode |
|
|
824
345
|
|
|
825
|
-
|
|
346
|
+
### Ads
|
|
826
347
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
348
|
+
| Method | Returns | Description |
|
|
349
|
+
|--------|---------|-------------|
|
|
350
|
+
| `configureAds(config)` | `void` | Configure the ads service |
|
|
351
|
+
| `showAd(type)` | `Promise<AdResult>` | Show an ad |
|
|
352
|
+
| `areAdsReady()` | `boolean` | Check if ads have initialized |
|
|
353
|
+
| `gameplayStart()` | `Promise<void>` | Notify gameplay started (CrazyGames) |
|
|
354
|
+
| `gameplayStop()` | `Promise<void>` | Notify gameplay stopped (CrazyGames) |
|
|
355
|
+
| `happytime()` | `Promise<void>` | Trigger celebration effect (CrazyGames) |
|
|
356
|
+
|
|
357
|
+
### Billing
|
|
358
|
+
|
|
359
|
+
| Method | Returns | Description |
|
|
360
|
+
|--------|---------|-------------|
|
|
361
|
+
| `getBillingPlatform()` | `BillingPlatform` | `"web"` \| `"native"` \| `"unknown"` |
|
|
362
|
+
| `isBillingAvailable()` | `boolean` | Check if billing is ready |
|
|
363
|
+
| `getBillingProducts()` | `Promise<BillingProduct[]>` | Fetch available products |
|
|
364
|
+
| `purchaseProduct(productId, options?)` | `Promise<PurchaseResult>` | Initiate a purchase |
|
|
365
|
+
| `onPurchaseComplete(callback)` | `void` | Register purchase success handler |
|
|
366
|
+
| `onPurchaseError(callback)` | `void` | Register purchase error handler |
|
|
367
|
+
| `unmountBillingCheckout()` | `void` | Clean up Stripe checkout UI |
|
|
368
|
+
|
|
369
|
+
## Build Output
|
|
370
|
+
|
|
371
|
+
| Format | File | Use |
|
|
372
|
+
|--------|------|-----|
|
|
373
|
+
| CJS | `dist/index.js` | Node.js / bundler |
|
|
374
|
+
| ESM | `dist/index.mjs` | Bundler (tree-shakeable) |
|
|
375
|
+
| CJS (React) | `dist/react.js` | React integration |
|
|
376
|
+
| ESM (React) | `dist/react.mjs` | React integration (tree-shakeable) |
|
|
831
377
|
|
|
832
378
|
## Development
|
|
833
379
|
|
|
834
380
|
```bash
|
|
835
|
-
#
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
# Type checking
|
|
839
|
-
bun run check-types
|
|
840
|
-
|
|
841
|
-
# Linting
|
|
842
|
-
bun run lint
|
|
843
|
-
|
|
844
|
-
# Build
|
|
845
|
-
bun run build
|
|
381
|
+
pnpm run check-types # Type check
|
|
382
|
+
pnpm run lint # Lint
|
|
383
|
+
pnpm run build # Build
|
|
846
384
|
```
|
|
847
385
|
|
|
848
|
-
## Documentation
|
|
849
|
-
|
|
850
|
-
For complete documentation and examples, visit [https://docs.hyve.gg](https://docs.hyve.gg)
|
|
851
|
-
|
|
852
|
-
### Additional Guides
|
|
853
|
-
|
|
854
|
-
- [Telemetry Guide](./docs/TELEMETRY.md) - Best practices, validation rules, and examples for event tracking
|
|
855
|
-
- [Billing Integration](./docs/BILLING_INTEGRATION.md) - Platform-aware billing with Stripe and In-App Purchases
|
|
856
|
-
- [Billing Migration Guide](./docs/BILLING_MIGRATION_GUIDE.md) - Upgrading from older billing implementations
|
|
857
|
-
- [Ads Integration](./docs/ads.md) - Google H5 Games Ads integration
|
|
858
|
-
- [Native Bridge](./docs/NATIVE_BRIDGE.md) - React Native WebView communication
|
|
859
|
-
|
|
860
386
|
## License
|
|
861
387
|
|
|
862
|
-
MIT
|
|
388
|
+
MIT
|