@dubsdotapp/expo 0.2.41 → 0.2.43
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 +160 -3
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/ui/game/ClaimButton.tsx +8 -2
package/README.md
CHANGED
|
@@ -117,6 +117,8 @@ function CreateBet({ eventId }: { eventId: string }) {
|
|
|
117
117
|
| `renderError` | `fn` | *default UI* | Custom error screen |
|
|
118
118
|
| `renderRegistration` | `fn` | *default UI* | Custom registration screen |
|
|
119
119
|
| `managed` | `boolean` | `true` | Set `false` for headless mode (no connect screen or auth gate) |
|
|
120
|
+
| `redirectUri` | `string` | — | Deeplink redirect URI for Phantom wallet (required for iOS) |
|
|
121
|
+
| `appUrl` | `string` | — | App URL shown in Phantom's connect screen |
|
|
120
122
|
|
|
121
123
|
### Disconnect
|
|
122
124
|
|
|
@@ -178,12 +180,16 @@ const myStorage: TokenStorage = {
|
|
|
178
180
|
|
|
179
181
|
| Hook | Type | Description |
|
|
180
182
|
|------|------|-------------|
|
|
183
|
+
| `useAuth()` | Auth | Full auth state — `user`, `isAuthenticated`, `authenticate()`, `register()`, `logout()` |
|
|
181
184
|
| `useEvents(params?)` | Query | Fetch upcoming events (sports + esports) |
|
|
182
185
|
| `useGame(gameId)` | Query | Single game detail |
|
|
183
186
|
| `useGames(params?)` | Query | List games with filters |
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
+
| `useNetworkGames(params?)` | Query | List games across the entire Dubs network |
|
|
188
|
+
| `useCreateGame()` | Mutation | Create game on a sports/esports event (build → sign → confirm) |
|
|
189
|
+
| `useCreateCustomGame()` | Mutation | Create a custom 1v1 game with arbitrary buy-in |
|
|
190
|
+
| `useJoinGame()` | Mutation | Join an existing game |
|
|
191
|
+
| `useClaim()` | Mutation | Claim prize or refund after game resolves |
|
|
192
|
+
| `useHasClaimed(gameId)` | Query | Check if current wallet already claimed — returns `hasClaimed`, `amountClaimed`, `claimSignature` |
|
|
187
193
|
|
|
188
194
|
### Mutation Status
|
|
189
195
|
|
|
@@ -208,6 +214,157 @@ const game = await client.getGame('sport-123...');
|
|
|
208
214
|
const codes = client.getErrorCodesLocal();
|
|
209
215
|
```
|
|
210
216
|
|
|
217
|
+
## UI Components
|
|
218
|
+
|
|
219
|
+
### Game Sheets
|
|
220
|
+
|
|
221
|
+
Drop-in bottom sheets that handle the full transaction lifecycle (build → sign → confirm) internally.
|
|
222
|
+
|
|
223
|
+
#### CreateCustomGameSheet
|
|
224
|
+
|
|
225
|
+
Bottom sheet for creating a custom 1v1 game with configurable buy-in.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { CreateCustomGameSheet } from '@dubsdotapp/expo';
|
|
229
|
+
|
|
230
|
+
<CreateCustomGameSheet
|
|
231
|
+
visible={showSheet}
|
|
232
|
+
onDismiss={() => setShowSheet(false)}
|
|
233
|
+
presetAmounts={[0.01, 0.1, 0.5]}
|
|
234
|
+
defaultAmount={0.01}
|
|
235
|
+
metadata={{ matchType: 'battleship' }}
|
|
236
|
+
onSuccess={(result) => console.log('Created!', result.gameId)}
|
|
237
|
+
onError={(err) => console.error(err)}
|
|
238
|
+
/>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
| Prop | Type | Default | Description |
|
|
242
|
+
|------|------|---------|-------------|
|
|
243
|
+
| `visible` | `boolean` | *required* | Show/hide the sheet |
|
|
244
|
+
| `onDismiss` | `() => void` | *required* | Called when user closes the sheet |
|
|
245
|
+
| `title` | `string` | `'New Game'` | Sheet header title |
|
|
246
|
+
| `maxPlayers` | `number` | `2` | Max players (currently 1v1) |
|
|
247
|
+
| `fee` | `number` | `0.05` | Platform fee percentage (0–1) |
|
|
248
|
+
| `presetAmounts` | `number[]` | `[0.01, 0.1, 0.5]` | Quick-select buy-in chips |
|
|
249
|
+
| `defaultAmount` | `number` | — | Pre-selected buy-in |
|
|
250
|
+
| `metadata` | `Record<string, unknown>` | — | Arbitrary metadata attached to the game |
|
|
251
|
+
| `onSuccess` | `(result) => void` | — | Called with `{ gameId, gameAddress, signature, explorerUrl, buyIn }` |
|
|
252
|
+
| `onError` | `(error) => void` | — | Called on failure |
|
|
253
|
+
|
|
254
|
+
#### JoinGameSheet
|
|
255
|
+
|
|
256
|
+
Bottom sheet for joining an existing game. Shows buy-in, team selection, pool summary, and potential winnings.
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
import { JoinGameSheet } from '@dubsdotapp/expo';
|
|
260
|
+
|
|
261
|
+
<JoinGameSheet
|
|
262
|
+
visible={showSheet}
|
|
263
|
+
onDismiss={() => setShowSheet(false)}
|
|
264
|
+
game={gameData}
|
|
265
|
+
onSuccess={(result) => console.log('Joined!', result.signature)}
|
|
266
|
+
onError={(err) => console.error(err)}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Prop | Type | Default | Description |
|
|
271
|
+
|------|------|---------|-------------|
|
|
272
|
+
| `visible` | `boolean` | *required* | Show/hide the sheet |
|
|
273
|
+
| `onDismiss` | `() => void` | *required* | Called when user closes the sheet |
|
|
274
|
+
| `game` | `GameDetail` | *required* | Game data from `useGame()` |
|
|
275
|
+
| `ImageComponent` | `ComponentType` | — | Custom image component (e.g. expo-image) for team logos |
|
|
276
|
+
| `shortName` | `(name) => string` | — | Custom team label formatter |
|
|
277
|
+
| `homeColor` | `string` | `'#3B82F6'` | Home team accent color |
|
|
278
|
+
| `awayColor` | `string` | `'#EF4444'` | Away team accent color |
|
|
279
|
+
| `onSuccess` | `(result) => void` | — | Called with `{ signature, explorerUrl }` |
|
|
280
|
+
| `onError` | `(error) => void` | — | Called on failure |
|
|
281
|
+
|
|
282
|
+
#### ClaimPrizeSheet
|
|
283
|
+
|
|
284
|
+
Bottom sheet for claiming a prize or refund after a game resolves. Includes a celebration animation on success.
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
import { ClaimPrizeSheet } from '@dubsdotapp/expo';
|
|
288
|
+
|
|
289
|
+
<ClaimPrizeSheet
|
|
290
|
+
visible={showSheet}
|
|
291
|
+
onDismiss={() => setShowSheet(false)}
|
|
292
|
+
gameId="abc123..."
|
|
293
|
+
prizeAmount={0.019}
|
|
294
|
+
isRefund={false}
|
|
295
|
+
onSuccess={(result) => console.log('Claimed!', result.explorerUrl)}
|
|
296
|
+
/>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
| Prop | Type | Default | Description |
|
|
300
|
+
|------|------|---------|-------------|
|
|
301
|
+
| `visible` | `boolean` | *required* | Show/hide the sheet |
|
|
302
|
+
| `onDismiss` | `() => void` | *required* | Called when user closes the sheet |
|
|
303
|
+
| `gameId` | `string` | *required* | Game ID to claim |
|
|
304
|
+
| `prizeAmount` | `number` | *required* | Prize amount in SOL |
|
|
305
|
+
| `isRefund` | `boolean` | `false` | Show refund language instead of prize language |
|
|
306
|
+
| `onSuccess` | `(result) => void` | — | Called with `{ signature, explorerUrl }` |
|
|
307
|
+
| `onError` | `(error) => void` | — | Called on failure |
|
|
308
|
+
|
|
309
|
+
### ClaimButton
|
|
310
|
+
|
|
311
|
+
Drop-in button that handles the entire claim flow internally — eligibility checks, prize/refund display, sheet lifecycle, and claimed badge. Renders nothing when the user is ineligible.
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { ClaimButton } from '@dubsdotapp/expo';
|
|
315
|
+
|
|
316
|
+
<ClaimButton
|
|
317
|
+
gameId="abc123..."
|
|
318
|
+
onSuccess={(result) => console.log('Claimed!', result.explorerUrl)}
|
|
319
|
+
onError={(err) => console.error(err)}
|
|
320
|
+
/>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
| Prop | Type | Default | Description |
|
|
324
|
+
|------|------|---------|-------------|
|
|
325
|
+
| `gameId` | `string` | *required* | Game ID to check and claim |
|
|
326
|
+
| `style` | `ViewStyle` | — | Custom button style |
|
|
327
|
+
| `onSuccess` | `(result) => void` | — | Called after successful claim |
|
|
328
|
+
| `onError` | `(error) => void` | — | Called on failure |
|
|
329
|
+
|
|
330
|
+
**Render states:**
|
|
331
|
+
- Loading / no wallet / no data → renders nothing
|
|
332
|
+
- Not eligible (lost, not resolved, not a bettor) → renders nothing
|
|
333
|
+
- Eligible + unclaimed → solid accent button: "Claim Prize — X SOL" or "Claim Refund — X SOL"
|
|
334
|
+
- Already claimed → outlined badge: "Prize Claimed!" or "Refund Claimed!"
|
|
335
|
+
|
|
336
|
+
### Game Display Cards
|
|
337
|
+
|
|
338
|
+
| Component | Description |
|
|
339
|
+
|-----------|-------------|
|
|
340
|
+
| `GamePoster` | Hero card with team logos, names, countdown, and live/locked badges |
|
|
341
|
+
| `LivePoolsCard` | Pool breakdown — each side's SOL amount, bar chart, and implied odds |
|
|
342
|
+
| `PickWinnerCard` | Team selection card for choosing which side to bet on |
|
|
343
|
+
| `PlayersCard` | List of all bettors with avatar, username, team, and wager amount |
|
|
344
|
+
| `JoinGameButton` | Fixed bottom bar with buy-in info and join CTA (hides when already joined / locked / resolved) |
|
|
345
|
+
|
|
346
|
+
### Profile & Settings
|
|
347
|
+
|
|
348
|
+
| Component | Description |
|
|
349
|
+
|-----------|-------------|
|
|
350
|
+
| `UserProfileCard` | Displays avatar, username, wallet address, and member-since date |
|
|
351
|
+
| `SettingsSheet` | Full settings screen with profile card, copy address, support link, and logout |
|
|
352
|
+
|
|
353
|
+
### Theming
|
|
354
|
+
|
|
355
|
+
All UI components respect the developer-configured accent color from the Dubs dashboard. You can also override the theme programmatically:
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
import { useDubsTheme, mergeTheme } from '@dubsdotapp/expo';
|
|
359
|
+
import type { DubsTheme } from '@dubsdotapp/expo';
|
|
360
|
+
|
|
361
|
+
// Inside a component — automatically respects light/dark mode + accent override
|
|
362
|
+
const theme = useDubsTheme();
|
|
363
|
+
|
|
364
|
+
// Or merge custom overrides manually
|
|
365
|
+
const custom = mergeTheme(baseTheme, { accent: '#EF4444' });
|
|
366
|
+
```
|
|
367
|
+
|
|
211
368
|
## Event ID Format
|
|
212
369
|
|
|
213
370
|
- Sports: `sports:{LEAGUE}:{EVENT_ID}` (e.g. `sports:NBA:espn-nba-401...`)
|
package/dist/index.js
CHANGED
|
@@ -4663,7 +4663,7 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
4663
4663
|
[claimStatus.refetch, onSuccess]
|
|
4664
4664
|
// eslint-disable-line react-hooks/exhaustive-deps
|
|
4665
4665
|
);
|
|
4666
|
-
if (game.loading || claimStatus.loading || !game.data || !walletAddress
|
|
4666
|
+
if (game.loading || claimStatus.loading || !game.data || !walletAddress) {
|
|
4667
4667
|
return null;
|
|
4668
4668
|
}
|
|
4669
4669
|
const label = isRefund ? "Refund" : "Prize";
|
|
@@ -4681,6 +4681,9 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
4681
4681
|
}
|
|
4682
4682
|
);
|
|
4683
4683
|
}
|
|
4684
|
+
if (!isEligible) {
|
|
4685
|
+
return null;
|
|
4686
|
+
}
|
|
4684
4687
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
4685
4688
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4686
4689
|
import_react_native17.TouchableOpacity,
|