@series-inc/venus-sdk 3.0.4 → 3.0.6

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 CHANGED
@@ -1,23 +1,21 @@
1
1
  # Venus SDK API
2
2
 
3
- The core API package for the Venus SDK, providing comprehensive, type-safe interfaces for building H5 games and applications on the Venus platform.
3
+ Build connected HTML5 games that integrate deeply with the Venus platform. This package provides the client SDK used by hosted games as well as the local mock environment for development.
4
4
 
5
- ## Installation
5
+ ## Highlights
6
6
 
7
- ```bash
8
- npm install venus-sdk
9
- ```
7
+ - Typed APIs for Venus platform services (simulation, rooms, analytics, ads, and more)
8
+ - Host-aware tooling including lifecycle hooks, safe-area utilities, and asset loading helpers
10
9
 
11
- ## Architecture
10
+ ## Quick Start
12
11
 
13
- The Venus SDK is built on a client-server RPC architecture:
12
+ ### Installation
14
13
 
15
- - **Host Interface** - Main entry point grouping all APIs
16
- - **RPC Transport** - Message-based communication with Venus platform
17
- - **Mock Implementations** - Complete mock APIs for local development
18
- - **Venus API** - Low-level platform interface
14
+ ```bash
15
+ npm install @series-inc/venus-sdk@latest
16
+ ```
19
17
 
20
- ### Usage
18
+ ### Initialize
21
19
 
22
20
  ```typescript
23
21
  import { default as VenusAPI } from '@series-inc/venus-sdk/api'
@@ -26,973 +24,10 @@ import { default as VenusAPI } from '@series-inc/venus-sdk/api'
26
24
  await VenusAPI.initializeAsync()
27
25
  ```
28
26
 
29
- ## API Overview
30
-
31
- ### Profile API
32
-
33
- ```typescript
34
- // Get current user profile (synchronous)
35
- const profile = VenusAPI.profile.getCurrentProfile()
36
- console.log(profile.name, profile.username)
37
- ```
38
- ---
39
-
40
- ### Safe Area & HUD Insets
41
-
42
- ```typescript
43
- // Static safe area from initialization (baseline padding)
44
- const safeArea = VenusAPI.config.ui.safeArea
45
- layout.style.paddingTop = `${safeArea.top}px`
46
- layout.style.paddingBottom = `${safeArea.bottom}px`
47
-
48
- // Dynamic HUD insets arrive with lifecycle events
49
- VenusAPI.lifecycle.onShow(({ hudInsets }) => {
50
- applyInsets(hudInsets, 'preview')
51
- })
52
-
53
- VenusAPI.lifecycle.onPlay(({ hudInsets }) => {
54
- applyInsets(hudInsets, 'fullscreen')
55
- })
56
-
57
- function applyInsets(insets, mode) {
58
- // Use whichever inset is larger to avoid overlap with host UI
59
- const top = Math.max(VenusAPI.config.ui.safeArea.top, insets.top)
60
- canvas.style.paddingTop = `${top}px`
61
- canvas.dataset.mode = mode
62
- }
63
- ```
64
-
65
- `safeArea` provides a static baseline defined at initialization. `hudInsets` reflect the live host UI chrome and differ between preview (`onShow`) and fullscreen (`onPlay`) contexts.
66
-
67
- ---
68
-
69
- ### Ads API
70
-
71
- ```typescript
72
- // Check if rewarded ad is ready
73
- const rewardedReady = await VenusAPI.ads.isRewardedAdReadyAsync()
74
-
75
- // Show interstitial ad
76
- const interstitialShown = await VenusAPI.ads.showInterstitialAd()
77
- if (interstitialShown) {
78
- // Interstitial ad was displayed
79
- }
80
-
81
- // Show rewarded video ad
82
- const rewardEarned = await VenusAPI.ads.showRewardedAdAsync()
83
- if (rewardEarned) {
84
- // User watched the full video and earned reward
85
- }
86
- ```
87
- ---
88
-
89
- ### Haptics API
90
-
91
- ```typescript
92
- // Trigger haptic feedback
93
- await VenusAPI.haptics.triggerHapticAsync('success')
94
- await VenusAPI.haptics.triggerHapticAsync('warning')
95
- await VenusAPI.haptics.triggerHapticAsync('error')
96
- await VenusAPI.haptics.triggerHapticAsync('light')
97
- await VenusAPI.haptics.triggerHapticAsync('medium')
98
- await VenusAPI.haptics.triggerHapticAsync('heavy')
99
- ```
100
- ---
101
-
102
- ### Local Notifications API
103
-
104
- ```typescript
105
- // Schedule a delayed notification (minimal - required params only)
106
- const id = await VenusApi.notifications.scheduleAsync(
107
- 'Notification Title',
108
- 'Notification Body',
109
- 60 // Delay in seconds
110
- )
111
-
112
- // Schedule with optional notification ID
113
- const id = await VenusApi.notifications.scheduleAsync(
114
- 'Notification Title',
115
- 'Notification Body',
116
- 60,
117
- 'custom-notification-id'
118
- )
119
-
120
- // Schedule with all optional settings
121
- const id = await VenusApi.notifications.scheduleAsync(
122
- 'Notification Title',
123
- 'Notification Body',
124
- 60,
125
- 'custom-notification-id',
126
- {
127
- priority: 100, // 0-100, default 50
128
- groupId: 'reminders', // Group related notifications
129
- payload: { key: 'value' } // Custom data
130
- }
131
- )
132
-
133
- // Cancel a notification
134
- await VenusApi.notifications.cancelNotification(notificationId)
135
-
136
- // Get all scheduled notifications
137
- await VenusApi.notifications.getAllScheduledLocalNotifications()
138
- ```
139
- ---
140
-
141
- ### Loader API
142
-
143
- The preloader is opt-in by default. In order to opt in, you must add
144
- ```typescript
145
- await VenusAPI.initializeAsync({ usePreloader: true })
146
- ```
147
-
148
- ```typescript
149
- // Activating and dismissing the preloader
150
- await VenusApi.preloader.showLoadScreen()
151
- await VenusApi.preloader.hideLoadScreen()
152
- ```
153
- ---
154
-
155
- ### Custom Funnel Events API
156
-
157
- ```typescript
158
- // Record a custom analytics event
159
- await VenusApi.analytics.recordCustomEvent('level_completed', {
160
- level: 5,
161
- score: 1250,
162
- time: 45.2
163
- })
164
-
165
- // Track funnel step with optional funnel name
166
- await VenusApi.analytics.trackFunnelStep(1, 'tutorial_started', 'onboarding')
167
- await VenusApi.analytics.trackFunnelStep(2, 'tutorial_completed', 'onboarding')
168
- ```
169
- ---
170
-
171
- ### IAP API
172
-
173
- ```typescript
174
- // get VBucks/Hard Currency balance
175
- await VenusApi.iap.getHardCurrencyBalance()
176
- // Spend VBucks/Hard Currency
177
- await VenusApi.iap.spendCurrency('yourProductID', 3)
178
- // Open Venus Store
179
- await VenusApi.iap.openStore()
180
- // Get Currency Icon
181
- await VenusApi.iap.getCurrencyIcon()
182
- ```
183
- ---
184
-
185
- ### Saves API
186
-
187
- ```typescript
188
- // Get an item from storage
189
- await VenusApi.storage.getItem('playerData')
190
- // Set an item in storage
191
- await VenusApi.storage.setItem('playerData', JSON.stringify({ level: 10 }))
192
- // Remove an item from storage
193
- await VenusApi.storage.removeItem('playerData')
194
- // Get storage length
195
- await VenusApi.storage.length()
196
- // Get key at specific index
197
- await VenusApi.storage.key(0)
198
- // Clear all items from storage
199
- await VenusApi.storage.clear()
200
- // Set multiple items at once
201
- await VenusApi.storage.setMultipleItems([
202
- { key: 'playerData', value: JSON.stringify({ level: 10 }) },
203
- { key: 'settings', value: JSON.stringify({ sound: true }) }
204
- ])
205
- // Remove multiple items at once
206
- await VenusApi.storage.removeMultipleItems(['playerData', 'settings'])
207
- // Get all items from storage
208
- await VenusApi.storage.getAllItems()
209
- ```
210
- ---
211
-
212
- ### LLM API
213
-
214
- ```typescript
215
- // Request chat completion from AI model
216
- const response = await VenusApi.ai.requestChatCompletionAsync({
217
- model: 'chatGPT',
218
- messages: [
219
- {
220
- role: 'user',
221
- content: 'What is the best strategy for this level?'
222
- }
223
- ]
224
- })
225
-
226
- // Get available completion models
227
- const models = await VenusApi.ai.getAvailableCompletionModels()
228
- ```
229
-
230
- ### Simulation API
231
-
232
- The Simulation API manages game state, recipe execution, and slot systems.
233
-
234
- #### State Management
235
-
236
- ```typescript
237
- // Get current simulation state
238
- const state = await VenusAPI.simulation.getStateAsync(roomId?)
239
- // Returns: { entities, inventory, currencies, timers, etc. }
240
-
241
- // Get simulation configuration
242
- const config = await VenusAPI.simulation.getConfigAsync(roomId?)
243
- ```
244
-
245
- #### Recipe Execution
246
-
247
- Recipes are server-authoritative game actions (crafting, battles, upgrades, etc.):
248
-
249
- ```typescript
250
- // Execute a recipe
251
- const result = await VenusAPI.simulation.executeRecipeAsync(
252
- 'craft_sword',
253
- { materials: ['iron', 'wood'] },
254
- { skipNotification: false }
255
- )
256
-
257
- // Execute a scoped recipe (entity-specific)
258
- const result = await VenusAPI.simulation.executeScopedRecipeAsync(
259
- 'upgrade_weapon',
260
- 'sword_123',
261
- { level: 5 }
262
- )
263
-
264
- // Get active recipe runs (for time-based recipes)
265
- const runs = await VenusAPI.simulation.getActiveRunsAsync()
266
-
267
- // Collect completed recipe
268
- const result = await VenusAPI.simulation.collectRecipeAsync(runId)
269
-
270
- // Trigger recipe chain
271
- await VenusAPI.simulation.triggerRecipeChainAsync('battle_complete')
272
- ```
273
-
274
- #### Recipe Requirements
275
-
276
- ```typescript
277
- // Check requirements for a single recipe
278
- const requirements = await VenusAPI.simulation.getRecipeRequirementsAsync(
279
- 'craft_sword',
280
- 'player',
281
- 1
282
- )
283
- // Returns: { recipeId, entity, amount?, inputs, canAfford, disabled }
284
-
285
- // Batch check multiple recipes
286
- const results = await VenusAPI.simulation.getBatchRecipeRequirementsAsync([
287
- { recipeId: 'craft_sword', batchAmount: 1 },
288
- { recipeId: 'craft_shield', batchAmount: 2 }
289
- ])
290
- // Returns: { success, results, errors? }
291
-
292
- // Get available recipes
293
- const recipes = await VenusAPI.simulation.getAvailableRecipesAsync({
294
- roomId: 'room_123',
295
- includeActorRecipes: true
296
- })
297
- // Returns: { success, recipes }
298
- ```
299
-
300
- #### Slot Management
301
-
302
- Slots represent equipment, loadouts, teams, or any item container system:
303
-
304
- ```typescript
305
- // Get all slot containers
306
- const containers = await VenusAPI.simulation.getSlotContainersAsync()
307
- // Returns: [{ id: 'equipment', slots: [...] }, { id: 'team', slots: [...] }]
308
-
309
- // Get slot assignments for a container
310
- const assignments = await VenusAPI.simulation.getSlotAssignmentsAsync('equipment')
311
- // Returns: [{ slotId: 'weapon', itemId: 'sword_123' }, ...]
312
-
313
- // Assign item to slot
314
- await VenusAPI.simulation.assignItemToSlotAsync('equipment', 'weapon', 'sword_123')
315
-
316
- // Remove item from slot
317
- await VenusAPI.simulation.removeItemFromSlotAsync('equipment', 'weapon')
318
-
319
- // Get available items for a slot
320
- const items = await VenusAPI.simulation.getAvailableItemsAsync('equipment', 'weapon')
321
-
322
- // Preview power calculation before assignment
323
- const preview = await VenusAPI.simulation.calculatePowerPreviewAsync(
324
- 'equipment',
325
- 'weapon',
326
- 'sword_456'
327
- )
328
- // Returns: { currentPower: 100, newPower: 150, delta: +50 }
329
-
330
- // Validate slot assignment
331
- const valid = await VenusAPI.simulation.validateSlotAssignmentAsync(
332
- 'equipment',
333
- 'weapon',
334
- 'shield_123' // Wrong type
335
- )
336
- // Returns: { valid: false, reason: 'Type mismatch' }
337
-
338
- // Batch operations (atomic)
339
- await VenusAPI.simulation.executeBatchOperationsAsync([
340
- { type: 'assign', containerId: 'equipment', slotId: 'weapon', itemId: 'sword' },
341
- { type: 'assign', containerId: 'equipment', slotId: 'armor', itemId: 'plate' },
342
- { type: 'remove', containerId: 'equipment', slotId: 'boots' }
343
- ], false) // false = execute, true = validate only
344
- ```
345
-
346
- #### Field Resolution & Metadata
347
-
348
- ```typescript
349
- // Resolve dynamic field values
350
- const value = await VenusAPI.simulation.resolveFieldValueAsync(
351
- 'player_123',
352
- 'stats.power',
353
- 'player'
354
- )
355
-
356
- // Get entity metadata
357
- const metadata = await VenusAPI.simulation.getEntityMetadataAsync('sword_123')
358
- ```
359
- ---
360
-
361
- #### Utility Methods
362
-
363
- ```typescript
364
- // Sum stat contributions
365
- const totalPower = VenusAPI.simulation.sumContributions(
366
- [{ power: 10 }, { power: 20 }, { power: 15 }],
367
- 'power'
368
- )
369
- // Returns: 45
370
- ```
371
-
372
- ---
373
-
374
- ### Storage API
375
-
376
- Three-tier storage system with different data scopes:
377
-
378
- ```typescript
379
- // Device Cache - persists across all apps for the device
380
- await VenusAPI.deviceCache.setItem('lastUserId', '12345')
381
- const userId = await VenusAPI.deviceCache.getItem('lastUserId')
382
-
383
- // App Storage - app-specific persistent storage
384
- await VenusAPI.appStorage.setItem('highScore', JSON.stringify(1000))
385
- await VenusAPI.appStorage.setItem('playerData', JSON.stringify({ level: 5, gold: 1000 }))
386
-
387
- // Global Storage - shared across all apps for the user
388
- await VenusAPI.globalStorage.setItem('preferences', JSON.stringify({ theme: 'dark' }))
389
-
390
- // All storage APIs support:
391
- const value = await storage.getItem(key)
392
- await storage.setItem(key, value)
393
- await storage.removeItem(key)
394
- await storage.clear()
395
- const count = await storage.length()
396
- const keyName = await storage.key(index)
397
- ```
398
-
399
- ---
400
-
401
-
402
- ### Popups API
403
-
404
- Display native-style UI popups:
405
-
406
- ```typescript
407
- // Toast messages
408
- await VenusAPI.popups.showToast('Game saved!', {
409
- duration: 3000,
410
- variant: 'success',
411
- action: { label: 'Undo' }
412
- })
413
-
414
- // Alert dialog
415
- await VenusAPI.popups.showAlert(
416
- 'Warning',
417
- 'This action cannot be undone',
418
- { buttonText: 'OK' }
419
- )
420
-
421
- // Confirm dialog
422
- const confirmed = await VenusAPI.popups.showConfirm(
423
- 'Delete Item',
424
- 'Are you sure you want to delete this item?',
425
- { confirmText: 'Delete', cancelText: 'Cancel' }
426
- )
427
-
428
- if (confirmed) {
429
- // User confirmed
430
- }
431
-
432
- // Action sheet
433
- const selected = await VenusAPI.popups.showActionSheet(
434
- [
435
- { id: 'edit', label: 'Edit' },
436
- { id: 'share', label: 'Share' },
437
- { id: 'delete', label: 'Delete' }
438
- ],
439
- {
440
- title: 'Choose Action',
441
- cancelButtonText: 'Cancel'
442
- }
443
- )
444
-
445
- if (selected === 'delete') {
446
- // User selected delete
447
- }
448
- ```
449
-
450
- ---
451
-
452
- ### Navigation API
453
-
454
- Stack-based navigation system:
455
-
456
- ```typescript
457
- // Get current stack information (synchronous)
458
- const stack = VenusAPI.navigation.getStackInfo()
459
- // Returns: { isInStack, stackPosition, isTopOfStack, stackDepth, parentInstanceId }
460
-
461
- // Push new app to stack
462
- await VenusAPI.navigation.pushApp('bird-flap', {
463
- contextData: { level: 5, difficulty: 'hard' }
464
- })
465
-
466
- // Pop from stack (returns to previous app)
467
- await VenusAPI.navigation.popApp()
468
- ```
469
-
470
- ---
471
-
472
- ### Post API
473
-
474
- Social interaction APIs for posts:
475
-
476
- ```typescript
477
- // Get post interaction data
478
- const postInfo = await VenusAPI.post.getPostInfo()
479
- // Returns: { isLiked, isFollowing, likesCount, commentsCount }
480
-
481
- // Toggle like
482
- const likeResult = await VenusAPI.post.toggleLikeAsync()
483
- // Returns: { isLiked, likesCount, action: 'liked' | 'unliked' }
484
-
485
- // Toggle follow
486
- const followResult = await VenusAPI.post.toggleFollowAsync()
487
- // Returns: { isFollowing, action: 'followed' | 'unfollowed' }
488
-
489
- // Open comments UI
490
- const commentsResult = await VenusAPI.post.openCommentsAsync()
491
- // Returns: { opened, commentsCount }
492
-
493
- // Share post
494
- const shareResult = await VenusAPI.post.sharePostAsync({
495
- message: 'Check this out!',
496
- title: 'My Post'
497
- })
498
- // Returns: { shared, platform, customMessage? }
499
- ```
500
-
501
- ---
502
-
503
- ### Analytics API
504
-
505
- ```typescript
506
- // Log custom event
507
- await VenusAPI.analytics.logEvent('level_complete', {
508
- level: 5,
509
- score: 1000,
510
- timeElapsed: 120
511
- })
512
-
513
- // Set user properties
514
- await VenusAPI.analytics.setUserProperty('vip_status', 'gold')
515
- ```
516
-
517
- ---
518
-
519
- ### Avatar 3D API
520
-
521
- ```typescript
522
- // Load current avatar configuration
523
- const avatar = await VenusAPI.avatar3d.loadAvatar()
524
- // Or load a specific avatar
525
- const avatarConfig = await VenusAPI.avatar3d.loadAvatar('avatar_123')
526
-
527
- // Show avatar editor
528
- const result = await VenusAPI.avatar3d.showEditor({
529
- currentAvatar: avatarConfig,
530
- contextData: { source: 'settings' }
531
- })
532
-
533
- if (result.wasChanged && result.savedAvatarId) {
534
- console.log('Avatar updated:', result.savedAvatarId)
535
- }
536
-
537
- // Save avatar
538
- const avatarId = await VenusAPI.avatar3d.saveAvatar(avatarConfig)
539
-
540
- // Delete avatar
541
- await VenusAPI.avatar3d.deleteAvatar()
542
-
543
- // Download avatar manifest
544
- const manifest = await VenusAPI.avatar3d.downloadManifest()
545
-
546
- // Download asset paths
547
- const assetPaths = await VenusAPI.avatar3d.downloadAssetPaths()
548
- ```
549
-
550
- ---
551
-
552
- ### Rooms API
553
-
554
- Multi-user room management:
555
-
556
- ```typescript
557
- // Get current room
558
- const room = await VenusAPI.rooms.getCurrentRoom()
559
- // Returns: { id, name, participants, metadata }
560
-
561
- // Join room
562
- await VenusAPI.rooms.join('room_123')
563
-
564
- // Leave room
565
- await VenusAPI.rooms.leave()
566
-
567
- // Send room message
568
- await VenusAPI.rooms.sendMessage({
569
- type: 'game_action',
570
- data: { action: 'move', x: 10, y: 20 }
571
- })
572
- ```
573
-
574
- ---
575
-
576
- ### Time API
577
-
578
- Server time synchronization and formatting:
579
-
580
- ```typescript
581
- // Get server time
582
- const serverTimeData = await VenusAPI.time.requestTimeAsync()
583
- // Returns: { serverTime, localTime, timezoneOffset, formattedTime, locale }
584
-
585
- // Format time with locale
586
- const formatted = VenusAPI.time.formatTime(Date.now(), {
587
- locale: 'en-US',
588
- format: 'full' // 'full', 'long', 'medium', 'short'
589
- })
590
-
591
- // Format number with locale
592
- const formattedNumber = VenusAPI.time.formatNumber(1234567.89, {
593
- locale: 'en-US',
594
- style: 'currency',
595
- currency: 'USD'
596
- })
597
-
598
- // Get future time
599
- const futureTime = await VenusAPI.time.getFutureTimeAsync({
600
- days: 1,
601
- hours: 2,
602
- minutes: 30
603
- })
604
- ```
605
-
606
- ---
607
-
608
- ### CDN API
609
-
610
- ```typescript
611
- // Resolve asset URLs (synchronous)
612
- const assetUrl = VenusAPI.cdn.resolveAssetUrl('images/logo.png')
613
- const avatarUrl = VenusAPI.cdn.resolveAvatarAssetUrl('avatars/model.glb')
614
- const libUrl = VenusAPI.cdn.resolveSharedLibUrl('libs/helper.js')
615
-
616
- // Get CDN base URL
617
- const baseUrl = VenusAPI.cdn.getAssetCdnBaseUrl()
618
-
619
- // Fetch from CDN
620
- const response = await VenusAPI.cdn.fetchFromCdn('https://cdn.example.com/file.json')
621
- const blob = await VenusAPI.cdn.fetchBlob('path/to/asset.png')
622
- ```
623
-
624
- ---
625
-
626
- ### Features API
627
-
628
- Feature flags, experiments, and A/B testing:
629
-
630
- ```typescript
631
- // Get feature flag value (returns boolean)
632
- const enabled = await VenusAPI.features.getFeatureFlag('new_ui_enabled')
633
-
634
- // Get feature gate (returns boolean)
635
- const canAccess = await VenusAPI.features.getFeatureGate('beta_features')
636
-
637
- // Get experiment variant
638
- const experiment = await VenusAPI.features.getExperiment('checkout_flow')
639
- // Returns: { name, ruleID, value, groupName } | null
640
- ```
641
-
642
- ### Lifecycle API
643
-
644
- App lifecycle event handlers:
645
-
646
- ```typescript
647
- // Register lifecycle callbacks
648
- VenusAPI.lifecycle.onReady(() => {
649
- console.log('App ready')
650
- })
651
-
652
- VenusAPI.lifecycle.onShow((context) => {
653
- console.log('App shown', context.hudInsets)
654
- })
655
-
656
- VenusAPI.lifecycle.onPlay((context) => {
657
- console.log('App playing', context.hudInsets)
658
- })
659
-
660
- VenusAPI.lifecycle.onPause(() => {
661
- console.log('App paused')
662
- })
663
-
664
- VenusAPI.lifecycle.onResume(() => {
665
- console.log('App resumed')
666
- })
667
-
668
- VenusAPI.lifecycle.onHidden(() => {
669
- console.log('App hidden')
670
- })
671
-
672
- VenusAPI.lifecycle.onQuit(() => {
673
- console.log('App quitting')
674
- })
675
-
676
- // Quit the app
677
- await VenusAPI.lifecycle.quit()
678
- ```
679
-
680
- ---
681
-
682
- ### Logging API
683
-
684
- ```typescript
685
- // Log messages
686
- VenusAPI.logging.log('Info message', { data: 'value' })
687
- VenusAPI.logging.error('Error message', error)
688
- VenusAPI.logging.debug('Debug info')
689
- ```
690
-
691
- ---
692
-
693
- ### Leaderboard API (BETA)
694
-
695
- Competitive leaderboards with anti-cheat, multiple modes, and time periods.
696
-
697
- #### API Methods
698
-
699
- ```typescript
700
- // Start a leaderboard session
701
- const session = await VenusAPI.leaderboard.startRunAsync({
702
- mode: 'classic' // Optional: 'classic', 'hard', etc. Defaults to 'default'
703
- })
704
- // Returns: { sessionId, startTime, expiresAt, hashNonce?, mode }
705
-
706
- // Submit a score (within 1 hour of starting session)
707
- const result = await VenusAPI.leaderboard.submitScoreAsync({
708
- sessionId: session.sessionId,
709
- score: 1500,
710
- durationSec: 120,
711
- mode: 'classic', // Optional: must match session mode
712
- metadata: { // Optional: game-specific data (max 20KB)
713
- levelCompleted: 10,
714
- powerUpsUsed: 3
715
- },
716
- telemetry: { // Optional: anti-cheat data (max 2KB, primitives only)
717
- clickCount: 245,
718
- avgReactionTime: 0.32
719
- },
720
- hash: computedHash // Required if leaderboard uses hash verification
721
- })
722
- // Returns: { accepted, rank, zScore, isAnomaly }
723
-
724
- // Get leaderboard (paginated)
725
- const leaderboard = await VenusAPI.leaderboard.getLeaderboardAsync({
726
- mode: 'classic', // Optional: game mode
727
- period: 'daily', // Optional: 'daily', 'weekly', 'monthly', 'alltime'
728
- periodDate: Date.now(), // Optional: specific period to view
729
- limit: 50, // Optional: entries per page (max 50)
730
- cursor: nextCursor // Optional: for pagination
731
- })
732
- // Returns: {
733
- // variant: 'standard',
734
- // entries: [{ profileId, username, avatarUrl, score, rank, ... }],
735
- // totalEntries: 1234,
736
- // nextCursor: 'abc123...',
737
- // playerRank: 42,
738
- // periodInstance: 'daily_2025-11-04'
739
- // }
740
-
741
- // Get leaderboard highlight (top players + context around you)
742
- const highlight = await VenusAPI.leaderboard.getLeaderboardHighlightAsync({
743
- mode: 'classic',
744
- period: 'daily',
745
- topCount: 3, // Top N players (podium)
746
- contextAhead: 4, // Players ahead of you
747
- contextBehind: 2 // Players behind you
748
- })
749
- // Returns: {
750
- // variant: 'highlight',
751
- // entries: [...],
752
- // context: {
753
- // topEntries: [...], // Top 3
754
- // beforePlayer: [...], // 4 players ahead
755
- // playerEntry: {...}, // Your entry
756
- // afterPlayer: [...], // 2 players behind
757
- // omittedBefore: 35, // Gap between top 3 and you
758
- // omittedAfter: 100 // Players below you
759
- // },
760
- // playerRank: 42,
761
- // totalEntries: 150
762
- // }
763
-
764
- // Get player stats
765
- const stats = await VenusAPI.leaderboard.getPlayerStatsAsync({
766
- mode: 'classic',
767
- period: 'daily'
768
- })
769
- // Returns: {
770
- // rank: 42,
771
- // score: 1500,
772
- // totalPlayers: 150,
773
- // percentile: 0.72, // 72nd percentile
774
- // trustScore: 85,
775
- // periodInstance: 'daily_2025-11-04'
776
- // }
777
- ```
778
-
779
- #### Configuration
780
-
781
- Add a `leaderboard` object to your game's `config.json` file:
782
-
783
- ```json
784
- {
785
- "leaderboard": {
786
- "isDisabled": false,
787
- "disabledMessage": "Leaderboards are temporarily unavailable.",
788
- "requiresHash": true,
789
- "hashSecret": "your-secret-key-change-in-production",
790
- "scoringFields": ["score", "durationSec", "sessionId"],
791
- "minDurationSec": 10,
792
- "maxDurationSec": 600,
793
- "minScore": 0,
794
- "maxScore": 999999999,
795
- "modes": {
796
- "default": {
797
- "displayName": "Classic Mode"
798
- },
799
- "hard": {
800
- "displayName": "Hard Mode",
801
- "minDurationSec": 5,
802
- "maxDurationSec": 300
803
- }
804
- },
805
- "periods": {
806
- "daily": {
807
- "displayName": "Daily",
808
- "type": "daily"
809
- },
810
- "alltime": {
811
- "displayName": "All Time",
812
- "type": "alltime"
813
- }
814
- },
815
- "antiCheat": {
816
- "enableZScoreDetection": false,
817
- "zScoreThreshold": 3,
818
- "enableRateLimit": true,
819
- "minTimeBetweenSubmissionsSec": 60,
820
- "trustScoreDecayPerFlag": 10,
821
- "shadowBanThreshold": 20
822
- },
823
- "displaySettings": {
824
- "maxEntriesPerPage": 50
825
- },
826
- "seedEntries": {
827
- "default": {
828
- "daily": [
829
- {
830
- "score": 18500,
831
- "username": "ProPlayer",
832
- "avatarUrl": null,
833
- "durationSec": 180
834
- },
835
- {
836
- "score": 15200,
837
- "username": "Challenger",
838
- "avatarUrl": null,
839
- "durationSec": 210
840
- }
841
- ]
842
- }
843
- }
844
- }
845
- }
846
- ```
847
-
848
- **Configuration Options:**
849
-
850
- - `isDisabled`: Globally disable leaderboards
851
- - `requiresHash`: Enable HMAC-based score verification (recommended for production)
852
- - `hashSecret`: Secret key for HMAC verification (keep this secure!)
853
- - `scoringFields`: Fields included in hash verification (can include nested fields like `metadata.level`)
854
- - `minDurationSec` / `maxDurationSec`: Valid gameplay duration range
855
- - `minScore` / `maxScore`: Valid score bounds
856
- - `modes`: Game modes (can override min/max values per mode)
857
- - `periods`: Time periods for leaderboards (`daily`, `weekly`, `monthly`, `alltime`)
858
- - `antiCheat`: Anti-cheat settings
859
- - `seedEntries`: Pre-populate leaderboards with NPC scores (nested by mode → period)
860
-
861
- **Features:**
862
- - **Multiple Modes**: Support different game modes (classic, hard, etc.)
863
- - **Time Periods**: Daily, weekly, monthly, and all-time leaderboards
864
- - **Anti-Cheat**: Session validation, rate limiting, hash verification, z-score anomaly detection
865
- - **Shadow Banning**: Cheaters see their own scores but are hidden from others
866
- - **Trust Scores**: Per-player reputation that decays with suspicious behavior
867
- - **Seed Entries**: Pre-populate leaderboards with NPC scores
868
- - **Pagination**: Cursor-based pagination for large leaderboards
869
- - **UTC-Based Periods**: All players globally compete in same daily/weekly/monthly periods
870
-
871
- **Security Notes:**
872
- - Session tokens expire after 1 hour and can only be used once to prevent replay attacks
873
- - Use `requiresHash: true` in production with a strong `hashSecret`
874
- - Keep `hashSecret` out of version control (use environment variables or local config)
875
- - Store `hashSecret` in `config.local.json` (gitignored) for local development
876
-
877
- ---
878
-
879
- ## Mock Mode
880
-
881
- All APIs have complete mock implementations for local development:
882
-
883
- ```typescript
884
- import { default as VenusAPI } from '@series-inc/venus-sdk/api'
885
-
886
- await VenusAPI.initializeAsync({ mock: true })
887
-
888
- // All APIs work the same, but with simulated responses
889
- const state = await VenusAPI.simulation.getStateAsync()
890
- ```
891
-
892
- ### Custom Mock Data
893
-
894
- ```typescript
895
- await VenusAPI.initializeAsync({
896
- mock: {
897
- simulation: {
898
- state: { customData: 'value' }
899
- },
900
- profile: {
901
- name: 'Test User',
902
- username: 'test_user'
903
- }
904
- }
905
- })
906
- ```
907
-
908
- ---
909
-
910
- ## RPC Transport
911
-
912
- The SDK uses an RPC (Remote Procedure Call) architecture for communication:
913
-
914
- ```typescript
915
- import { RpcClient, VenusTransport } from 'venus-sdk'
916
-
917
- // Low-level RPC client
918
- const transport = new VenusTransport()
919
- const rpcClient = new RpcClient(transport)
920
-
921
- // Send request
922
- const response = await rpcClient.request({
923
- method: 'simulation.getState',
924
- params: { roomId: 'room_123' }
925
- })
926
- ```
927
-
928
- ---
929
-
930
- ## Build Configuration
931
-
932
- The package is built with `tsup` and provides multiple module formats:
933
-
934
- ```json
935
- {
936
- "main": "./dist/index.cjs",
937
- "module": "./dist/index.mjs",
938
- "types": "./dist/index.d.ts",
939
- "exports": {
940
- ".": {
941
- "types": "./dist/index.d.ts",
942
- "import": "./dist/index.mjs",
943
- "require": "./dist/index.cjs"
944
- },
945
- "./api": {
946
- "types": "./dist/venus-api/index.d.ts",
947
- "import": "./dist/venus-api/index.mjs",
948
- "require": "./dist/venus-api/index.cjs"
949
- }
950
- }
951
- }
952
- ```
953
-
954
- ---
955
-
956
- ## TypeScript Configuration
957
-
958
- The package uses TypeScript 5.9+ with strict type checking:
959
-
960
- ```json
961
- {
962
- "compilerOptions": {
963
- "strict": true,
964
- "target": "ES2020",
965
- "module": "ESNext",
966
- "moduleResolution": "bundler"
967
- }
968
- }
969
- ```
970
-
971
- ---
972
-
973
- ## Testing
974
-
975
- ```bash
976
- # Run unit tests
977
- npm test
978
-
979
- # Run tests in watch mode
980
- npm test -- --watch
981
- ```
982
-
983
- Tests are written using Jest with JSDOM environment for browser API simulation.
984
-
985
- ---
986
-
987
- ## License
988
-
989
- MIT
990
-
991
- ---
27
+ ## Documentation
992
28
 
993
- ## Related
29
+ The complete Venus SDK manuals live on [Venus Docs](https://series-1.gitbook.io/getreel-docs). Start there for setup guides, API references, tutorials, and best practices.
994
30
 
995
- - [Main Repository](https://github.com/SeriesAI/venus-sdk)
996
- - [npm Package](https://www.npmjs.com/package/venus-sdk)
997
- - [Issue Tracker](https://github.com/SeriesAI/venus-sdk/issues)
31
+ ## Support & Links
998
32
 
33
+ - [Join our Discord!](https://discord.gg/NcjhKQHx)