@thestatic-tv/dcl-sdk 2.2.10 → 2.3.0-beta.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 +216 -66
- package/dist/index.d.mts +450 -38
- package/dist/index.d.ts +450 -38
- package/dist/index.js +1671 -142
- package/dist/index.mjs +1667 -141
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -14,10 +14,11 @@ This SDK allows DCL scene builders to:
|
|
|
14
14
|
|
|
15
15
|
## Pricing
|
|
16
16
|
|
|
17
|
-
|
|
|
17
|
+
| Tier | Price | Features |
|
|
18
18
|
|------|-------|----------|
|
|
19
|
-
| **
|
|
20
|
-
| **
|
|
19
|
+
| **Free** | $5/mo | Session/visitor tracking only |
|
|
20
|
+
| **Standard** | $10/mo | Free + Guide UI, Chat UI, Heartbeat, Interactions |
|
|
21
|
+
| **Pro** | $15/mo | Standard + Admin Panel (Video tab, Mod tab, Custom scene tabs) |
|
|
21
22
|
|
|
22
23
|
> **All keys use `dcls_` prefix** - the server determines your subscription level.
|
|
23
24
|
>
|
|
@@ -37,16 +38,16 @@ If you need to rotate your API key (e.g., if compromised), you can do so from th
|
|
|
37
38
|
|
|
38
39
|
## Example Scene
|
|
39
40
|
|
|
40
|
-
Clone our
|
|
41
|
+
Clone our example scene to get started quickly:
|
|
41
42
|
|
|
42
43
|
```bash
|
|
43
|
-
git clone https://github.com/thestatic-tv/thestatic-dcl-
|
|
44
|
-
cd thestatic-dcl-
|
|
44
|
+
git clone https://github.com/thestatic-tv/thestatic-dcl-example.git
|
|
45
|
+
cd thestatic-dcl-example
|
|
45
46
|
npm install
|
|
46
47
|
npm start
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
See the [
|
|
50
|
+
See the [example repo](https://github.com/thestatic-tv/thestatic-dcl-example) for a complete working scene with video player integration.
|
|
50
51
|
|
|
51
52
|
## Installation
|
|
52
53
|
|
|
@@ -58,18 +59,24 @@ npm install @thestatic-tv/dcl-sdk
|
|
|
58
59
|
|
|
59
60
|
1. Get your API key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
|
|
60
61
|
|
|
61
|
-
2. Initialize the client in your scene:
|
|
62
|
+
2. Initialize the client in your scene's `main()` function:
|
|
62
63
|
|
|
63
64
|
```typescript
|
|
65
|
+
import {} from '@dcl/sdk/math'
|
|
66
|
+
import { engine } from '@dcl/sdk/ecs'
|
|
64
67
|
import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
let staticTV: StaticTVClient
|
|
70
|
+
|
|
71
|
+
export function main() {
|
|
72
|
+
staticTV = new StaticTVClient({
|
|
73
|
+
apiKey: 'dcls_your_api_key_here'
|
|
74
|
+
})
|
|
75
|
+
// Session tracking starts automatically!
|
|
76
|
+
}
|
|
70
77
|
```
|
|
71
78
|
|
|
72
|
-
3. Fetch channels and display them:
|
|
79
|
+
3. Fetch channels and display them (Full mode only):
|
|
73
80
|
|
|
74
81
|
```typescript
|
|
75
82
|
// Get all channels
|
|
@@ -108,33 +115,40 @@ await staticTV.interactions.follow('channel-slug')
|
|
|
108
115
|
await staticTV.destroy()
|
|
109
116
|
```
|
|
110
117
|
|
|
111
|
-
##
|
|
118
|
+
## Free Tier (Visitor Tracking Only)
|
|
112
119
|
|
|
113
120
|
If you don't have a channel but want to track visitors to your scene:
|
|
114
121
|
|
|
115
122
|
1. Get a scene key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
|
|
116
123
|
|
|
117
|
-
2. Initialize with your scene key
|
|
124
|
+
2. Initialize with your scene key in `main()`:
|
|
118
125
|
|
|
119
126
|
```typescript
|
|
127
|
+
import {} from '@dcl/sdk/math'
|
|
128
|
+
import { engine } from '@dcl/sdk/ecs'
|
|
120
129
|
import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
|
|
121
130
|
|
|
122
|
-
|
|
123
|
-
apiKey: 'dcls_your_scene_key_here'
|
|
124
|
-
})
|
|
131
|
+
let staticTV: StaticTVClient
|
|
125
132
|
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
export function main() {
|
|
134
|
+
staticTV = new StaticTVClient({
|
|
135
|
+
apiKey: 'dcls_your_scene_key_here'
|
|
136
|
+
})
|
|
137
|
+
// Session tracking starts automatically!
|
|
138
|
+
}
|
|
128
139
|
```
|
|
129
140
|
|
|
130
|
-
3. Check
|
|
141
|
+
3. Check the current tier:
|
|
131
142
|
|
|
132
143
|
```typescript
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
// Check tier (free, standard, or pro)
|
|
145
|
+
console.log('Current tier:', staticTV.tier)
|
|
146
|
+
|
|
147
|
+
if (staticTV.isFree) {
|
|
148
|
+
console.log('Running in free tier - session tracking only')
|
|
135
149
|
}
|
|
136
150
|
|
|
137
|
-
// guide, heartbeat, and interactions are null in
|
|
151
|
+
// guide, heartbeat, and interactions are null in free tier
|
|
138
152
|
if (staticTV.guide) {
|
|
139
153
|
const channels = await staticTV.guide.getChannels()
|
|
140
154
|
}
|
|
@@ -161,15 +175,28 @@ Main client class for interacting with thestatic.tv.
|
|
|
161
175
|
| Property | Type | Description |
|
|
162
176
|
|----------|------|-------------|
|
|
163
177
|
| `keyType` | `'channel' \| 'scene'` | The detected key type |
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
178
|
+
| `tier` | `'free' \| 'standard' \| 'pro'` | Current subscription tier |
|
|
179
|
+
| `isFree` | `boolean` | `true` if free tier (session tracking only) |
|
|
180
|
+
| `hasStandardFeatures` | `boolean` | `true` if standard features enabled |
|
|
181
|
+
| `hasProFeatures` | `boolean` | `true` if pro features enabled |
|
|
182
|
+
| `guide` | `GuideModule \| null` | Guide module (null in free tier) |
|
|
166
183
|
| `session` | `SessionModule` | Session module (always available) |
|
|
167
|
-
| `heartbeat` | `HeartbeatModule \| null` | Heartbeat module (null in
|
|
168
|
-
| `interactions` | `InteractionsModule \| null` | Interactions module (null in
|
|
169
|
-
| `guideUI` | `GuideUIModule \| null` | Guide UI module (null in
|
|
170
|
-
| `chatUI` | `ChatUIModule \| null` | Chat UI module (null in
|
|
184
|
+
| `heartbeat` | `HeartbeatModule \| null` | Heartbeat module (null in free tier) |
|
|
185
|
+
| `interactions` | `InteractionsModule \| null` | Interactions module (null in free tier) |
|
|
186
|
+
| `guideUI` | `GuideUIModule \| null` | Guide UI module (null in free tier) |
|
|
187
|
+
| `chatUI` | `ChatUIModule \| null` | Chat UI module (null in free tier) |
|
|
188
|
+
| `adminPanel` | `AdminPanelUIModule \| null` | Admin panel (null until enableProFeatures() called) |
|
|
189
|
+
| `isLite` | `boolean` | **Deprecated**: Use `isFree` instead |
|
|
190
|
+
|
|
191
|
+
#### Methods
|
|
171
192
|
|
|
172
|
-
|
|
193
|
+
| Method | Description |
|
|
194
|
+
|--------|-------------|
|
|
195
|
+
| `enableProFeatures(config)` | Enable Pro tier admin panel |
|
|
196
|
+
| `registerSceneTab(tab)` | Add custom scene tab (Pro tier) |
|
|
197
|
+
| `destroy()` | Cleanup before scene unload |
|
|
198
|
+
|
|
199
|
+
### Guide Module (Standard/Pro Tier)
|
|
173
200
|
|
|
174
201
|
```typescript
|
|
175
202
|
staticTV.guide.getChannels() // Get all channels (cached 30s)
|
|
@@ -188,9 +215,18 @@ staticTV.session.startSession() // Manually start session
|
|
|
188
215
|
staticTV.session.endSession() // End session
|
|
189
216
|
staticTV.session.getSessionId() // Get current session ID
|
|
190
217
|
staticTV.session.isSessionActive() // Check if session is active
|
|
218
|
+
|
|
219
|
+
// Get scene stats (visitors, sessions, etc.)
|
|
220
|
+
const stats = await staticTV.session.getStats()
|
|
221
|
+
if (stats) {
|
|
222
|
+
console.log('Total sessions today:', stats.totalSessions)
|
|
223
|
+
console.log('Unique visitors:', stats.uniqueVisitors)
|
|
224
|
+
console.log('Total minutes watched:', stats.totalMinutes)
|
|
225
|
+
console.log('You are visitor #', stats.visitorNumber)
|
|
226
|
+
}
|
|
191
227
|
```
|
|
192
228
|
|
|
193
|
-
### Heartbeat Module (
|
|
229
|
+
### Heartbeat Module (Standard/Pro Tier)
|
|
194
230
|
|
|
195
231
|
Track video watching. Each heartbeat represents 1 minute watched.
|
|
196
232
|
|
|
@@ -201,7 +237,7 @@ staticTV.heartbeat.getCurrentChannel() // Get currently watched channel
|
|
|
201
237
|
staticTV.heartbeat.isCurrentlyWatching() // Check if watching
|
|
202
238
|
```
|
|
203
239
|
|
|
204
|
-
### Interactions Module (
|
|
240
|
+
### Interactions Module (Standard/Pro Tier)
|
|
205
241
|
|
|
206
242
|
Like and follow channels. Requires wallet connection.
|
|
207
243
|
|
|
@@ -210,24 +246,27 @@ staticTV.interactions.like(channelSlug) // Like a channel
|
|
|
210
246
|
staticTV.interactions.follow(channelSlug) // Follow a channel
|
|
211
247
|
```
|
|
212
248
|
|
|
213
|
-
### Guide UI Module (
|
|
249
|
+
### Guide UI Module (Standard/Pro Tier)
|
|
214
250
|
|
|
215
251
|
Built-in channel browser UI. You provide a callback to handle video selection.
|
|
216
252
|
|
|
217
253
|
```typescript
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
254
|
+
let staticTV: StaticTVClient
|
|
255
|
+
|
|
256
|
+
export function main() {
|
|
257
|
+
staticTV = new StaticTVClient({
|
|
258
|
+
apiKey: 'dcls_your_api_key',
|
|
259
|
+
guideUI: {
|
|
260
|
+
onVideoSelect: (video) => {
|
|
261
|
+
// Handle video playback in your scene
|
|
262
|
+
console.log('Playing:', video.name, video.src)
|
|
263
|
+
}
|
|
225
264
|
}
|
|
226
|
-
}
|
|
227
|
-
})
|
|
265
|
+
})
|
|
228
266
|
|
|
229
|
-
// Initialize the UI (call once after client is created)
|
|
230
|
-
|
|
267
|
+
// Initialize the UI (call once after client is created)
|
|
268
|
+
staticTV.guideUI.init()
|
|
269
|
+
}
|
|
231
270
|
|
|
232
271
|
// Show/hide the guide
|
|
233
272
|
staticTV.guideUI.show()
|
|
@@ -244,22 +283,25 @@ staticTV.guideUI.currentVideoId = 'video-id'
|
|
|
244
283
|
await staticTV.guideUI.refresh()
|
|
245
284
|
```
|
|
246
285
|
|
|
247
|
-
### Chat UI Module (
|
|
286
|
+
### Chat UI Module (Standard/Pro Tier)
|
|
248
287
|
|
|
249
288
|
Real-time chat with Firebase authentication.
|
|
250
289
|
|
|
251
290
|
```typescript
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
291
|
+
let staticTV: StaticTVClient
|
|
292
|
+
|
|
293
|
+
export function main() {
|
|
294
|
+
staticTV = new StaticTVClient({
|
|
295
|
+
apiKey: 'dcls_your_api_key',
|
|
296
|
+
chatUI: {
|
|
297
|
+
position: 'right', // 'left', 'center', or 'right'
|
|
298
|
+
fontScale: 1.0
|
|
299
|
+
}
|
|
300
|
+
})
|
|
260
301
|
|
|
261
|
-
// Initialize the chat (call once after client is created)
|
|
262
|
-
|
|
302
|
+
// Initialize the chat (call once after client is created)
|
|
303
|
+
staticTV.chatUI.init()
|
|
304
|
+
}
|
|
263
305
|
|
|
264
306
|
// Show/hide the chat
|
|
265
307
|
staticTV.chatUI.show()
|
|
@@ -276,23 +318,131 @@ const unread = staticTV.chatUI.unreadCount
|
|
|
276
318
|
staticTV.chatUI.setChannel('channel-slug')
|
|
277
319
|
```
|
|
278
320
|
|
|
279
|
-
###
|
|
321
|
+
### Admin Panel Module (Pro Tier)
|
|
280
322
|
|
|
281
|
-
|
|
323
|
+
In-scene admin panel with Video and Mod tabs. Allows scene owners/admins to:
|
|
324
|
+
- Control live streaming (start/stop, rotate keys)
|
|
325
|
+
- Play videos from URL or predefined slots
|
|
326
|
+
- Manage scene admins and banned wallets
|
|
327
|
+
- Send broadcast messages to all players
|
|
282
328
|
|
|
283
329
|
```typescript
|
|
284
|
-
import {
|
|
330
|
+
import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
|
|
331
|
+
import ReactEcs, { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
|
|
332
|
+
|
|
333
|
+
let staticTV: StaticTVClient
|
|
285
334
|
|
|
286
|
-
|
|
335
|
+
export function main() {
|
|
336
|
+
staticTV = new StaticTVClient({
|
|
337
|
+
apiKey: 'dcls_your_api_key'
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
// Enable admin panel (Pro tier)
|
|
341
|
+
staticTV.enableProFeatures({
|
|
342
|
+
// sceneId is optional - defaults to your API key ID
|
|
343
|
+
title: 'MY SCENE ADMIN', // Panel header title
|
|
344
|
+
onVideoPlay: (url) => {
|
|
345
|
+
// Handle video playback in your scene
|
|
346
|
+
videoPlayer.play(url)
|
|
347
|
+
},
|
|
348
|
+
onVideoStop: () => {
|
|
349
|
+
videoPlayer.stop()
|
|
350
|
+
},
|
|
351
|
+
onVideoSlotPlay: (slot) => {
|
|
352
|
+
// Play a predefined video slot (slot1-slot5)
|
|
353
|
+
fetchAndPlaySlot(slot)
|
|
354
|
+
},
|
|
355
|
+
onBroadcast: (text) => {
|
|
356
|
+
// Show notification to all players
|
|
357
|
+
showNotification(text)
|
|
358
|
+
},
|
|
359
|
+
onCommand: (type, payload) => {
|
|
360
|
+
// Handle custom commands (kickAll, kickBanned, etc.)
|
|
361
|
+
handleCommand(type, payload)
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Render the admin panel
|
|
287
367
|
ReactEcsRenderer.setUiRenderer(() => {
|
|
288
|
-
return (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
368
|
+
return staticTV.adminPanel?.getComponent()
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
// Toggle panel visibility
|
|
372
|
+
staticTV.adminPanel.toggle()
|
|
373
|
+
|
|
374
|
+
// Check if user has admin access
|
|
375
|
+
if (staticTV.adminPanel.hasAccess) { ... }
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### Admin Panel Configuration Options
|
|
379
|
+
|
|
380
|
+
| Option | Type | Default | Description |
|
|
381
|
+
|--------|------|---------|-------------|
|
|
382
|
+
| `sceneId` | `string` | API key ID | Scene ID for API calls (optional - defaults to your API key ID) |
|
|
383
|
+
| `title` | `string` | `'ADMIN PANEL'` | Header title |
|
|
384
|
+
| `headerColor` | `{r,g,b,a}` | red | Header background color |
|
|
385
|
+
| `showVideoTab` | `boolean` | `true` | Show Video tab |
|
|
386
|
+
| `showModTab` | `boolean` | `true` | Show Mod tab (owners only) |
|
|
387
|
+
| `onVideoPlay` | `(url) => void` | - | Called when video should play |
|
|
388
|
+
| `onVideoStop` | `() => void` | - | Called when video should stop |
|
|
389
|
+
| `onVideoSlotPlay` | `(slot) => void` | - | Called when slot is selected |
|
|
390
|
+
| `onBroadcast` | `(text) => void` | - | Called for broadcast messages |
|
|
391
|
+
| `onCommand` | `(type, payload) => void` | - | Called for custom commands |
|
|
392
|
+
| `footerLink` | `string` | scene page | Link shown in footer |
|
|
393
|
+
| `debug` | `boolean` | `false` | Enable debug logging |
|
|
394
|
+
|
|
395
|
+
### Custom Scene Tabs (Pro Tier)
|
|
396
|
+
|
|
397
|
+
Add your own scene-specific control tabs to the admin panel:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
import ReactEcs, { UiEntity, Button, Label } from '@dcl/sdk/react-ecs'
|
|
401
|
+
|
|
402
|
+
// Enable pro features first
|
|
403
|
+
staticTV.enableProFeatures({ sceneId: 'my-scene', ... })
|
|
404
|
+
|
|
405
|
+
// Register custom tabs
|
|
406
|
+
staticTV.registerSceneTab({
|
|
407
|
+
label: 'LIGHTS',
|
|
408
|
+
id: 'lights',
|
|
409
|
+
render: () => (
|
|
410
|
+
<UiEntity uiTransform={{ flexDirection: 'column', padding: 8 }}>
|
|
411
|
+
<Label value="Light Controls" fontSize={14} />
|
|
412
|
+
<Button value="Disco Mode" onMouseDown={() => setDiscoLights()} />
|
|
413
|
+
<Button value="Ambient" onMouseDown={() => setAmbientLights()} />
|
|
414
|
+
<Button value="Off" onMouseDown={() => turnOffLights()} />
|
|
415
|
+
</UiEntity>
|
|
294
416
|
)
|
|
295
417
|
})
|
|
418
|
+
|
|
419
|
+
staticTV.registerSceneTab({
|
|
420
|
+
label: 'DOORS',
|
|
421
|
+
id: 'doors',
|
|
422
|
+
render: () => <MyDoorsControls />
|
|
423
|
+
})
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Custom tabs appear before the Video and Mod tabs in the tab bar.
|
|
427
|
+
|
|
428
|
+
### Rendering UI Components
|
|
429
|
+
|
|
430
|
+
The UI modules provide `getComponent()` methods that return React-ECS elements. Add the renderer **outside** your `main()` function:
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
|
|
434
|
+
|
|
435
|
+
// Outside main() - required by DCL
|
|
436
|
+
ReactEcsRenderer.setUiRenderer(() => {
|
|
437
|
+
if (!staticTV) return null
|
|
438
|
+
return ReactEcs.createElement(UiEntity, {
|
|
439
|
+
uiTransform: { width: '100%', height: '100%', positionType: 'absolute' },
|
|
440
|
+
children: [
|
|
441
|
+
staticTV.guideUI?.getComponent(),
|
|
442
|
+
staticTV.chatUI?.getComponent()
|
|
443
|
+
].filter(Boolean)
|
|
444
|
+
})
|
|
445
|
+
})
|
|
296
446
|
```
|
|
297
447
|
|
|
298
448
|
## Metrics Attribution
|