@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 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
- | `useCreateGame()` | Mutation | Full create lifecycle (build sign send → confirm) |
185
- | `useJoinGame()` | Mutation | Full join lifecycle |
186
- | `useClaim()` | Mutation | Full claim lifecycle |
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 || !isEligible) {
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,