@dubsdotapp/expo 0.2.29 → 0.2.30

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/dist/index.d.mts CHANGED
@@ -118,12 +118,14 @@ interface CreateCustomGameParams {
118
118
  title?: string;
119
119
  maxPlayers?: number;
120
120
  metadata?: Record<string, unknown>;
121
+ externalGameId?: string;
121
122
  }
122
123
  interface CreateCustomGameResult {
123
124
  gameId: string;
124
125
  gameAddress: string;
125
126
  transaction: string;
126
127
  lockTimestamp: number;
128
+ externalGameId?: string | null;
127
129
  }
128
130
  interface JoinGameParams {
129
131
  playerWallet: string;
@@ -189,6 +191,7 @@ interface GameDetail {
189
191
  drawPool: number;
190
192
  totalPool: number;
191
193
  media: GameMedia;
194
+ externalGameId?: string | null;
192
195
  createdAt: string;
193
196
  updatedAt: string;
194
197
  }
@@ -208,12 +211,14 @@ interface GameListItem {
208
211
  league: string | null;
209
212
  lockTimestamp: number | null;
210
213
  createdAt: string;
214
+ externalGameId?: string | null;
211
215
  opponents: GameListOpponent[];
212
216
  media: GameMedia;
213
217
  }
214
218
  interface GetGamesParams {
215
219
  wallet?: string;
216
220
  status?: 'open' | 'locked' | 'resolved';
221
+ externalGameId?: string;
217
222
  limit?: number;
218
223
  offset?: number;
219
224
  }
@@ -733,6 +738,7 @@ interface CreateCustomGameMutationResult {
733
738
  signature: string;
734
739
  explorerUrl: string;
735
740
  buyIn: number;
741
+ externalGameId?: string | null;
736
742
  }
737
743
  declare function useCreateCustomGame(): {
738
744
  execute: (params: CreateCustomGameParams) => Promise<CreateCustomGameMutationResult>;
@@ -896,11 +902,29 @@ interface CreateCustomGameSheetProps {
896
902
  presetAmounts?: number[];
897
903
  defaultAmount?: number;
898
904
  metadata?: Record<string, unknown>;
905
+ externalGameId?: string;
899
906
  onAmountChange?: (amount: number | null) => void;
900
907
  onSuccess?: (result: CreateCustomGameMutationResult) => void;
901
908
  onError?: (error: Error) => void;
902
909
  }
903
- declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers, fee, presetAmounts, defaultAmount, metadata, onAmountChange, onSuccess, onError, }: CreateCustomGameSheetProps): react_jsx_runtime.JSX.Element;
910
+ declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers, fee, presetAmounts, defaultAmount, metadata, externalGameId, onAmountChange, onSuccess, onError, }: CreateCustomGameSheetProps): react_jsx_runtime.JSX.Element;
911
+
912
+ interface JoinGameSheetProps {
913
+ visible: boolean;
914
+ onDismiss: () => void;
915
+ game: GameDetail;
916
+ /** Optional Image component (expo-image, etc.) for team logos */
917
+ ImageComponent?: React$1.ComponentType<any>;
918
+ /** Custom short-name function for team labels */
919
+ shortName?: (name: string | null) => string;
920
+ /** Override team colors (default blue/red) */
921
+ homeColor?: string;
922
+ awayColor?: string;
923
+ /** Callbacks */
924
+ onSuccess?: (result: JoinGameMutationResult) => void;
925
+ onError?: (error: Error) => void;
926
+ }
927
+ declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
904
928
 
905
929
  /**
906
930
  * Deserialize a base64-encoded transaction, sign via wallet adapter, send to Solana.
@@ -910,4 +934,4 @@ declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers,
910
934
  */
911
935
  declare function signAndSendBase64Transaction(base64Tx: string, wallet: WalletAdapter, connection: Connection): Promise<string>;
912
936
 
913
- export { AuthGate, type AuthGateProps, type AuthStatus, type AuthenticateParams, type AuthenticateResult, type Bettor, type BuildClaimParams, type BuildClaimResult, type CheckUsernameResult, type ClaimMutationResult, type ConfirmGameParams, type ConfirmGameResult, ConnectWalletScreen, type ConnectWalletScreenProps, type CreateCustomGameMutationResult, type CreateCustomGameParams, type CreateCustomGameResult, CreateCustomGameSheet, type CreateCustomGameSheetProps, type CreateGameMutationResult, type CreateGameParams, type CreateGameResult, DEFAULT_BASE_URL, DEFAULT_RPC_URL, type DeviceInfo, DubsApiError, type DubsAppUser, DubsClient, type DubsClientConfig, type DubsContextValue, type DubsNetwork, DubsProvider, type DubsProviderProps, type DubsPublicUser, type DubsTheme, type DubsUser, type EsportsMatchDetail, type EsportsMatchOpponent, type EsportsMatchResult, type EventMedia, type EventMeta, type EventStream, type GameDetail, type GameListItem, type GameListOpponent, type GameMedia, GamePoster, type GamePosterProps, type GetGamesParams, type GetNetworkGamesParams, type GetUpcomingEventsParams, JoinGameButton, type JoinGameButtonProps, type JoinGameMutationResult, type JoinGameParams, type JoinGameResult, LivePoolsCard, type LivePoolsCardProps, type LiveScore, type LiveScoreCompetitor, type MutationResult, type MutationStatus, type MwaAdapterConfig, type MwaTransactFn, MwaWalletAdapter, NETWORK_CONFIG, type NonceResult, type Opponent, type Pagination, type ParsedError, PhantomDeeplinkAdapter, type PhantomDeeplinkAdapterConfig, type PhantomSession, PickWinnerCard, type PickWinnerCardProps, PlayersCard, type PlayersCardProps, type QueryResult, type RegisterParams, type RegisterResult, type RegistrationScreenProps, SOLANA_PROGRAM_ERRORS, STORAGE_KEYS, SettingsSheet, type SettingsSheetProps, type SolanaErrorCode, type TokenStorage, type UiConfig, type UnifiedEvent, type UseAuthResult, UserProfileCard, type UserProfileCardProps, type ValidateEventResult, type WalletAdapter, createSecureStoreStorage, getDeviceInfo, isSolanaSeeker, mergeTheme, parseSolanaError, signAndSendBase64Transaction, useAppConfig, useAuth, useClaim, useCreateCustomGame, useCreateGame, useDubs, useDubsTheme, useEvents, useGame, useGames, useJoinGame, useNetworkGames };
937
+ export { AuthGate, type AuthGateProps, type AuthStatus, type AuthenticateParams, type AuthenticateResult, type Bettor, type BuildClaimParams, type BuildClaimResult, type CheckUsernameResult, type ClaimMutationResult, type ConfirmGameParams, type ConfirmGameResult, ConnectWalletScreen, type ConnectWalletScreenProps, type CreateCustomGameMutationResult, type CreateCustomGameParams, type CreateCustomGameResult, CreateCustomGameSheet, type CreateCustomGameSheetProps, type CreateGameMutationResult, type CreateGameParams, type CreateGameResult, DEFAULT_BASE_URL, DEFAULT_RPC_URL, type DeviceInfo, DubsApiError, type DubsAppUser, DubsClient, type DubsClientConfig, type DubsContextValue, type DubsNetwork, DubsProvider, type DubsProviderProps, type DubsPublicUser, type DubsTheme, type DubsUser, type EsportsMatchDetail, type EsportsMatchOpponent, type EsportsMatchResult, type EventMedia, type EventMeta, type EventStream, type GameDetail, type GameListItem, type GameListOpponent, type GameMedia, GamePoster, type GamePosterProps, type GetGamesParams, type GetNetworkGamesParams, type GetUpcomingEventsParams, JoinGameButton, type JoinGameButtonProps, type JoinGameMutationResult, type JoinGameParams, type JoinGameResult, JoinGameSheet, type JoinGameSheetProps, LivePoolsCard, type LivePoolsCardProps, type LiveScore, type LiveScoreCompetitor, type MutationResult, type MutationStatus, type MwaAdapterConfig, type MwaTransactFn, MwaWalletAdapter, NETWORK_CONFIG, type NonceResult, type Opponent, type Pagination, type ParsedError, PhantomDeeplinkAdapter, type PhantomDeeplinkAdapterConfig, type PhantomSession, PickWinnerCard, type PickWinnerCardProps, PlayersCard, type PlayersCardProps, type QueryResult, type RegisterParams, type RegisterResult, type RegistrationScreenProps, SOLANA_PROGRAM_ERRORS, STORAGE_KEYS, SettingsSheet, type SettingsSheetProps, type SolanaErrorCode, type TokenStorage, type UiConfig, type UnifiedEvent, type UseAuthResult, UserProfileCard, type UserProfileCardProps, type ValidateEventResult, type WalletAdapter, createSecureStoreStorage, getDeviceInfo, isSolanaSeeker, mergeTheme, parseSolanaError, signAndSendBase64Transaction, useAppConfig, useAuth, useClaim, useCreateCustomGame, useCreateGame, useDubs, useDubsTheme, useEvents, useGame, useGames, useJoinGame, useNetworkGames };
package/dist/index.d.ts CHANGED
@@ -118,12 +118,14 @@ interface CreateCustomGameParams {
118
118
  title?: string;
119
119
  maxPlayers?: number;
120
120
  metadata?: Record<string, unknown>;
121
+ externalGameId?: string;
121
122
  }
122
123
  interface CreateCustomGameResult {
123
124
  gameId: string;
124
125
  gameAddress: string;
125
126
  transaction: string;
126
127
  lockTimestamp: number;
128
+ externalGameId?: string | null;
127
129
  }
128
130
  interface JoinGameParams {
129
131
  playerWallet: string;
@@ -189,6 +191,7 @@ interface GameDetail {
189
191
  drawPool: number;
190
192
  totalPool: number;
191
193
  media: GameMedia;
194
+ externalGameId?: string | null;
192
195
  createdAt: string;
193
196
  updatedAt: string;
194
197
  }
@@ -208,12 +211,14 @@ interface GameListItem {
208
211
  league: string | null;
209
212
  lockTimestamp: number | null;
210
213
  createdAt: string;
214
+ externalGameId?: string | null;
211
215
  opponents: GameListOpponent[];
212
216
  media: GameMedia;
213
217
  }
214
218
  interface GetGamesParams {
215
219
  wallet?: string;
216
220
  status?: 'open' | 'locked' | 'resolved';
221
+ externalGameId?: string;
217
222
  limit?: number;
218
223
  offset?: number;
219
224
  }
@@ -733,6 +738,7 @@ interface CreateCustomGameMutationResult {
733
738
  signature: string;
734
739
  explorerUrl: string;
735
740
  buyIn: number;
741
+ externalGameId?: string | null;
736
742
  }
737
743
  declare function useCreateCustomGame(): {
738
744
  execute: (params: CreateCustomGameParams) => Promise<CreateCustomGameMutationResult>;
@@ -896,11 +902,29 @@ interface CreateCustomGameSheetProps {
896
902
  presetAmounts?: number[];
897
903
  defaultAmount?: number;
898
904
  metadata?: Record<string, unknown>;
905
+ externalGameId?: string;
899
906
  onAmountChange?: (amount: number | null) => void;
900
907
  onSuccess?: (result: CreateCustomGameMutationResult) => void;
901
908
  onError?: (error: Error) => void;
902
909
  }
903
- declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers, fee, presetAmounts, defaultAmount, metadata, onAmountChange, onSuccess, onError, }: CreateCustomGameSheetProps): react_jsx_runtime.JSX.Element;
910
+ declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers, fee, presetAmounts, defaultAmount, metadata, externalGameId, onAmountChange, onSuccess, onError, }: CreateCustomGameSheetProps): react_jsx_runtime.JSX.Element;
911
+
912
+ interface JoinGameSheetProps {
913
+ visible: boolean;
914
+ onDismiss: () => void;
915
+ game: GameDetail;
916
+ /** Optional Image component (expo-image, etc.) for team logos */
917
+ ImageComponent?: React$1.ComponentType<any>;
918
+ /** Custom short-name function for team labels */
919
+ shortName?: (name: string | null) => string;
920
+ /** Override team colors (default blue/red) */
921
+ homeColor?: string;
922
+ awayColor?: string;
923
+ /** Callbacks */
924
+ onSuccess?: (result: JoinGameMutationResult) => void;
925
+ onError?: (error: Error) => void;
926
+ }
927
+ declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
904
928
 
905
929
  /**
906
930
  * Deserialize a base64-encoded transaction, sign via wallet adapter, send to Solana.
@@ -910,4 +934,4 @@ declare function CreateCustomGameSheet({ visible, onDismiss, title, maxPlayers,
910
934
  */
911
935
  declare function signAndSendBase64Transaction(base64Tx: string, wallet: WalletAdapter, connection: Connection): Promise<string>;
912
936
 
913
- export { AuthGate, type AuthGateProps, type AuthStatus, type AuthenticateParams, type AuthenticateResult, type Bettor, type BuildClaimParams, type BuildClaimResult, type CheckUsernameResult, type ClaimMutationResult, type ConfirmGameParams, type ConfirmGameResult, ConnectWalletScreen, type ConnectWalletScreenProps, type CreateCustomGameMutationResult, type CreateCustomGameParams, type CreateCustomGameResult, CreateCustomGameSheet, type CreateCustomGameSheetProps, type CreateGameMutationResult, type CreateGameParams, type CreateGameResult, DEFAULT_BASE_URL, DEFAULT_RPC_URL, type DeviceInfo, DubsApiError, type DubsAppUser, DubsClient, type DubsClientConfig, type DubsContextValue, type DubsNetwork, DubsProvider, type DubsProviderProps, type DubsPublicUser, type DubsTheme, type DubsUser, type EsportsMatchDetail, type EsportsMatchOpponent, type EsportsMatchResult, type EventMedia, type EventMeta, type EventStream, type GameDetail, type GameListItem, type GameListOpponent, type GameMedia, GamePoster, type GamePosterProps, type GetGamesParams, type GetNetworkGamesParams, type GetUpcomingEventsParams, JoinGameButton, type JoinGameButtonProps, type JoinGameMutationResult, type JoinGameParams, type JoinGameResult, LivePoolsCard, type LivePoolsCardProps, type LiveScore, type LiveScoreCompetitor, type MutationResult, type MutationStatus, type MwaAdapterConfig, type MwaTransactFn, MwaWalletAdapter, NETWORK_CONFIG, type NonceResult, type Opponent, type Pagination, type ParsedError, PhantomDeeplinkAdapter, type PhantomDeeplinkAdapterConfig, type PhantomSession, PickWinnerCard, type PickWinnerCardProps, PlayersCard, type PlayersCardProps, type QueryResult, type RegisterParams, type RegisterResult, type RegistrationScreenProps, SOLANA_PROGRAM_ERRORS, STORAGE_KEYS, SettingsSheet, type SettingsSheetProps, type SolanaErrorCode, type TokenStorage, type UiConfig, type UnifiedEvent, type UseAuthResult, UserProfileCard, type UserProfileCardProps, type ValidateEventResult, type WalletAdapter, createSecureStoreStorage, getDeviceInfo, isSolanaSeeker, mergeTheme, parseSolanaError, signAndSendBase64Transaction, useAppConfig, useAuth, useClaim, useCreateCustomGame, useCreateGame, useDubs, useDubsTheme, useEvents, useGame, useGames, useJoinGame, useNetworkGames };
937
+ export { AuthGate, type AuthGateProps, type AuthStatus, type AuthenticateParams, type AuthenticateResult, type Bettor, type BuildClaimParams, type BuildClaimResult, type CheckUsernameResult, type ClaimMutationResult, type ConfirmGameParams, type ConfirmGameResult, ConnectWalletScreen, type ConnectWalletScreenProps, type CreateCustomGameMutationResult, type CreateCustomGameParams, type CreateCustomGameResult, CreateCustomGameSheet, type CreateCustomGameSheetProps, type CreateGameMutationResult, type CreateGameParams, type CreateGameResult, DEFAULT_BASE_URL, DEFAULT_RPC_URL, type DeviceInfo, DubsApiError, type DubsAppUser, DubsClient, type DubsClientConfig, type DubsContextValue, type DubsNetwork, DubsProvider, type DubsProviderProps, type DubsPublicUser, type DubsTheme, type DubsUser, type EsportsMatchDetail, type EsportsMatchOpponent, type EsportsMatchResult, type EventMedia, type EventMeta, type EventStream, type GameDetail, type GameListItem, type GameListOpponent, type GameMedia, GamePoster, type GamePosterProps, type GetGamesParams, type GetNetworkGamesParams, type GetUpcomingEventsParams, JoinGameButton, type JoinGameButtonProps, type JoinGameMutationResult, type JoinGameParams, type JoinGameResult, JoinGameSheet, type JoinGameSheetProps, LivePoolsCard, type LivePoolsCardProps, type LiveScore, type LiveScoreCompetitor, type MutationResult, type MutationStatus, type MwaAdapterConfig, type MwaTransactFn, MwaWalletAdapter, NETWORK_CONFIG, type NonceResult, type Opponent, type Pagination, type ParsedError, PhantomDeeplinkAdapter, type PhantomDeeplinkAdapterConfig, type PhantomSession, PickWinnerCard, type PickWinnerCardProps, PlayersCard, type PlayersCardProps, type QueryResult, type RegisterParams, type RegisterResult, type RegistrationScreenProps, SOLANA_PROGRAM_ERRORS, STORAGE_KEYS, SettingsSheet, type SettingsSheetProps, type SolanaErrorCode, type TokenStorage, type UiConfig, type UnifiedEvent, type UseAuthResult, UserProfileCard, type UserProfileCardProps, type ValidateEventResult, type WalletAdapter, createSecureStoreStorage, getDeviceInfo, isSolanaSeeker, mergeTheme, parseSolanaError, signAndSendBase64Transaction, useAppConfig, useAuth, useClaim, useCreateCustomGame, useCreateGame, useDubs, useDubsTheme, useEvents, useGame, useGames, useJoinGame, useNetworkGames };
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  DubsProvider: () => DubsProvider,
41
41
  GamePoster: () => GamePoster,
42
42
  JoinGameButton: () => JoinGameButton,
43
+ JoinGameSheet: () => JoinGameSheet,
43
44
  LivePoolsCard: () => LivePoolsCard,
44
45
  MwaWalletAdapter: () => MwaWalletAdapter,
45
46
  NETWORK_CONFIG: () => NETWORK_CONFIG,
@@ -343,7 +344,8 @@ var DubsClient = class {
343
344
  gameId: res.gameId,
344
345
  gameAddress: res.gameAddress,
345
346
  transaction: res.transaction,
346
- lockTimestamp: res.lockTimestamp
347
+ lockTimestamp: res.lockTimestamp,
348
+ externalGameId: res.externalGameId ?? null
347
349
  };
348
350
  }
349
351
  async confirmCustomGame(params) {
@@ -390,6 +392,7 @@ var DubsClient = class {
390
392
  const qs = new URLSearchParams();
391
393
  if (params?.wallet) qs.set("wallet", params.wallet);
392
394
  if (params?.status) qs.set("status", params.status);
395
+ if (params?.externalGameId) qs.set("externalGameId", params.externalGameId);
393
396
  if (params?.limit != null) qs.set("limit", String(params.limit));
394
397
  if (params?.offset != null) qs.set("offset", String(params.offset));
395
398
  const query = qs.toString();
@@ -1911,7 +1914,8 @@ function useCreateCustomGame() {
1911
1914
  gameAddress: createResult.gameAddress,
1912
1915
  signature,
1913
1916
  explorerUrl,
1914
- buyIn: params.wagerAmount
1917
+ buyIn: params.wagerAmount,
1918
+ externalGameId: createResult.externalGameId ?? null
1915
1919
  };
1916
1920
  setData(result);
1917
1921
  setStatus("success");
@@ -3493,6 +3497,7 @@ function CreateCustomGameSheet({
3493
3497
  presetAmounts = [0.01, 0.1, 0.5, 1],
3494
3498
  defaultAmount = 0.01,
3495
3499
  metadata,
3500
+ externalGameId,
3496
3501
  onAmountChange,
3497
3502
  onSuccess,
3498
3503
  onError
@@ -3567,11 +3572,12 @@ function CreateCustomGameSheet({
3567
3572
  wagerAmount: effectiveAmount,
3568
3573
  title,
3569
3574
  maxPlayers,
3570
- metadata
3575
+ metadata,
3576
+ externalGameId
3571
3577
  });
3572
3578
  } catch {
3573
3579
  }
3574
- }, [effectiveAmount, wallet.publicKey, mutation.execute, title, maxPlayers, metadata]);
3580
+ }, [effectiveAmount, wallet.publicKey, mutation.execute, title, maxPlayers, metadata, externalGameId]);
3575
3581
  const statusLabel = STATUS_LABELS2[mutation.status] || "";
3576
3582
  const playersLabel = playerCount === 2 ? "2 (1v1)" : `${playerCount} players`;
3577
3583
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
@@ -3825,6 +3831,391 @@ var styles9 = import_react_native14.StyleSheet.create({
3825
3831
  gap: 10
3826
3832
  }
3827
3833
  });
3834
+
3835
+ // src/ui/game/JoinGameSheet.tsx
3836
+ var import_react21 = require("react");
3837
+ var import_react_native15 = require("react-native");
3838
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3839
+ var STATUS_LABELS3 = {
3840
+ building: "Building transaction...",
3841
+ signing: "Approve in wallet...",
3842
+ confirming: "Confirming...",
3843
+ success: "Joined!"
3844
+ };
3845
+ var CUSTOM_GAME_MODE = 6;
3846
+ function JoinGameSheet({
3847
+ visible,
3848
+ onDismiss,
3849
+ game,
3850
+ ImageComponent,
3851
+ shortName,
3852
+ homeColor = "#3B82F6",
3853
+ awayColor = "#EF4444",
3854
+ onSuccess,
3855
+ onError
3856
+ }) {
3857
+ const t = useDubsTheme();
3858
+ const { wallet } = useDubs();
3859
+ const mutation = useJoinGame();
3860
+ const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
3861
+ const [selectedTeam, setSelectedTeam] = (0, import_react21.useState)(null);
3862
+ const overlayOpacity = (0, import_react21.useRef)(new import_react_native15.Animated.Value(0)).current;
3863
+ (0, import_react21.useEffect)(() => {
3864
+ import_react_native15.Animated.timing(overlayOpacity, {
3865
+ toValue: visible ? 1 : 0,
3866
+ duration: 250,
3867
+ useNativeDriver: true
3868
+ }).start();
3869
+ }, [visible, overlayOpacity]);
3870
+ (0, import_react21.useEffect)(() => {
3871
+ if (visible) {
3872
+ setSelectedTeam(isCustomGame ? "away" : null);
3873
+ mutation.reset();
3874
+ }
3875
+ }, [visible]);
3876
+ (0, import_react21.useEffect)(() => {
3877
+ if (mutation.status === "success" && mutation.data) {
3878
+ onSuccess?.(mutation.data);
3879
+ const timer = setTimeout(() => {
3880
+ onDismiss();
3881
+ }, 1500);
3882
+ return () => clearTimeout(timer);
3883
+ }
3884
+ }, [mutation.status, mutation.data]);
3885
+ (0, import_react21.useEffect)(() => {
3886
+ if (mutation.status === "error" && mutation.error) {
3887
+ onError?.(mutation.error);
3888
+ }
3889
+ }, [mutation.status, mutation.error]);
3890
+ const opponents = game.opponents || [];
3891
+ const bettors = game.bettors || [];
3892
+ const totalPool = game.totalPool || 0;
3893
+ const homePool = game.homePool || 0;
3894
+ const awayPool = game.awayPool || 0;
3895
+ const buyIn = game.buyIn;
3896
+ const { homeOdds, awayOdds, homeBets, awayBets } = (0, import_react21.useMemo)(() => ({
3897
+ homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
3898
+ awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
3899
+ homeBets: bettors.filter((b) => b.team === "home").length,
3900
+ awayBets: bettors.filter((b) => b.team === "away").length
3901
+ }), [totalPool, homePool, awayPool, bettors]);
3902
+ const poolAfterJoin = totalPool + buyIn;
3903
+ const selectedOdds = selectedTeam === "home" ? homeOdds : selectedTeam === "away" ? awayOdds : "\u2014";
3904
+ const potentialWinnings = selectedOdds !== "\u2014" ? (parseFloat(selectedOdds) * buyIn).toFixed(4) : "\u2014";
3905
+ const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
3906
+ const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
3907
+ const selectedName = selectedTeam === "home" ? homeName : selectedTeam === "away" ? awayName : "\u2014";
3908
+ const alreadyJoined = (0, import_react21.useMemo)(() => {
3909
+ if (!wallet.publicKey) return false;
3910
+ const addr = wallet.publicKey.toBase58();
3911
+ return bettors.some((b) => b.wallet === addr);
3912
+ }, [bettors, wallet.publicKey]);
3913
+ const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
3914
+ const canJoin = selectedTeam !== null && !isMutating && mutation.status !== "success" && !alreadyJoined;
3915
+ const handleJoin = (0, import_react21.useCallback)(async () => {
3916
+ if (!selectedTeam || !wallet.publicKey) return;
3917
+ try {
3918
+ await mutation.execute({
3919
+ playerWallet: wallet.publicKey.toBase58(),
3920
+ gameId: game.gameId,
3921
+ teamChoice: selectedTeam,
3922
+ amount: buyIn
3923
+ });
3924
+ } catch {
3925
+ }
3926
+ }, [selectedTeam, wallet.publicKey, mutation.execute, game.gameId, buyIn]);
3927
+ const statusLabel = STATUS_LABELS3[mutation.status] || "";
3928
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3929
+ import_react_native15.Modal,
3930
+ {
3931
+ visible,
3932
+ animationType: "slide",
3933
+ transparent: true,
3934
+ onRequestClose: onDismiss,
3935
+ children: [
3936
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Animated.View, { style: [styles10.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.TouchableOpacity, { style: styles10.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
3937
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3938
+ import_react_native15.KeyboardAvoidingView,
3939
+ {
3940
+ style: styles10.keyboardView,
3941
+ behavior: import_react_native15.Platform.OS === "ios" ? "padding" : void 0,
3942
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: styles10.sheetPositioner, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: [styles10.sheet, { backgroundColor: t.background }], children: [
3943
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: styles10.handleRow, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.handle, { backgroundColor: t.textMuted }] }) }),
3944
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.header, children: [
3945
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.headerTitle, { color: t.text }], children: "Join Game" }),
3946
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.TouchableOpacity, { onPress: onDismiss, activeOpacity: 0.8, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.closeButton, { color: t.textMuted }], children: "\u2715" }) })
3947
+ ] }),
3948
+ !isCustomGame && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.section, children: [
3949
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
3950
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.teamsRow, children: [
3951
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3952
+ TeamButton,
3953
+ {
3954
+ name: homeName,
3955
+ imageUrl: opponents[0]?.imageUrl,
3956
+ odds: homeOdds,
3957
+ bets: homeBets,
3958
+ color: homeColor,
3959
+ selected: selectedTeam === "home",
3960
+ onPress: () => setSelectedTeam("home"),
3961
+ ImageComponent,
3962
+ t
3963
+ }
3964
+ ),
3965
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3966
+ TeamButton,
3967
+ {
3968
+ name: awayName,
3969
+ imageUrl: opponents[1]?.imageUrl,
3970
+ odds: awayOdds,
3971
+ bets: awayBets,
3972
+ color: awayColor,
3973
+ selected: selectedTeam === "away",
3974
+ onPress: () => setSelectedTeam("away"),
3975
+ ImageComponent,
3976
+ t
3977
+ }
3978
+ )
3979
+ ] })
3980
+ ] }),
3981
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: [styles10.summaryCard, { backgroundColor: t.surface, borderColor: t.border }], children: [
3982
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.summaryRow, children: [
3983
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Buy-in" }),
3984
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.Text, { style: [styles10.summaryValue, { color: t.text }], children: [
3985
+ buyIn,
3986
+ " SOL"
3987
+ ] })
3988
+ ] }),
3989
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
3990
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.summaryRow, children: [
3991
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Your side" }),
3992
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryValue, { color: t.text }], children: selectedName })
3993
+ ] }),
3994
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
3995
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.summaryRow, children: [
3996
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Total pool" }),
3997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.Text, { style: [styles10.summaryValue, { color: t.text }], children: [
3998
+ poolAfterJoin,
3999
+ " SOL"
4000
+ ] })
4001
+ ] }),
4002
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
4003
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.summaryRow, children: [
4004
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Potential winnings" }),
4005
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.summaryValue, { color: t.success }], children: potentialWinnings !== "\u2014" ? `${potentialWinnings} SOL` : "\u2014" })
4006
+ ] })
4007
+ ] }),
4008
+ alreadyJoined && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.errorBox, { backgroundColor: t.surface, borderColor: t.border }], children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.errorText, { color: t.textMuted }], children: "You've already joined this game." }) }),
4009
+ mutation.error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.errorText, { color: t.errorText }], children: mutation.error.message }) }),
4010
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4011
+ import_react_native15.TouchableOpacity,
4012
+ {
4013
+ style: [
4014
+ styles10.ctaButton,
4015
+ { backgroundColor: canJoin ? t.accent : t.border }
4016
+ ],
4017
+ disabled: !canJoin,
4018
+ onPress: handleJoin,
4019
+ activeOpacity: 0.8,
4020
+ children: isMutating ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: styles10.ctaLoading, children: [
4021
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
4022
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: styles10.ctaText, children: statusLabel })
4023
+ ] }) : mutation.status === "success" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: styles10.ctaText, children: STATUS_LABELS3.success }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.ctaText, !canJoin && { opacity: 0.5 }], children: alreadyJoined ? "Already Joined" : selectedTeam ? `Join Game \u2014 ${buyIn} SOL` : "Pick a side to join" })
4024
+ }
4025
+ )
4026
+ ] }) })
4027
+ }
4028
+ )
4029
+ ]
4030
+ }
4031
+ );
4032
+ }
4033
+ function TeamButton({
4034
+ name,
4035
+ imageUrl,
4036
+ odds,
4037
+ bets,
4038
+ color,
4039
+ selected,
4040
+ onPress,
4041
+ ImageComponent,
4042
+ t
4043
+ }) {
4044
+ const [imgFailed, setImgFailed] = (0, import_react21.useState)(false);
4045
+ const Img = ImageComponent || require("react-native").Image;
4046
+ const showImage = imageUrl && !imgFailed;
4047
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4048
+ import_react_native15.TouchableOpacity,
4049
+ {
4050
+ style: [styles10.teamOption, { borderColor: selected ? color : t.border, backgroundColor: selected ? color + "15" : t.background }],
4051
+ onPress,
4052
+ activeOpacity: 0.7,
4053
+ children: [
4054
+ showImage ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Img, { source: { uri: imageUrl }, style: styles10.teamLogo, resizeMode: "contain", onError: () => setImgFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.teamLogo, styles10.teamLogoPlaceholder] }),
4055
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: [styles10.teamName, { color: t.text }], numberOfLines: 1, children: name }),
4056
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.Text, { style: [styles10.teamOdds, { color }], children: [
4057
+ odds,
4058
+ "x"
4059
+ ] }),
4060
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.Text, { style: [styles10.teamBets, { color: t.textMuted }], children: [
4061
+ bets,
4062
+ " ",
4063
+ bets === 1 ? "bet" : "bets"
4064
+ ] }),
4065
+ selected && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: [styles10.teamBadge, { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.Text, { style: styles10.teamBadgeText, children: "Selected" }) })
4066
+ ]
4067
+ }
4068
+ );
4069
+ }
4070
+ var styles10 = import_react_native15.StyleSheet.create({
4071
+ overlay: {
4072
+ ...import_react_native15.StyleSheet.absoluteFillObject,
4073
+ backgroundColor: "rgba(0,0,0,0.5)"
4074
+ },
4075
+ overlayTap: {
4076
+ flex: 1
4077
+ },
4078
+ keyboardView: {
4079
+ flex: 1,
4080
+ justifyContent: "flex-end"
4081
+ },
4082
+ sheetPositioner: {
4083
+ justifyContent: "flex-end"
4084
+ },
4085
+ sheet: {
4086
+ borderTopLeftRadius: 24,
4087
+ borderTopRightRadius: 24,
4088
+ paddingHorizontal: 20,
4089
+ paddingBottom: 40
4090
+ },
4091
+ handleRow: {
4092
+ alignItems: "center",
4093
+ paddingTop: 10,
4094
+ paddingBottom: 8
4095
+ },
4096
+ handle: {
4097
+ width: 36,
4098
+ height: 4,
4099
+ borderRadius: 2,
4100
+ opacity: 0.4
4101
+ },
4102
+ header: {
4103
+ flexDirection: "row",
4104
+ alignItems: "center",
4105
+ justifyContent: "space-between",
4106
+ paddingVertical: 12
4107
+ },
4108
+ headerTitle: {
4109
+ fontSize: 20,
4110
+ fontWeight: "700"
4111
+ },
4112
+ closeButton: {
4113
+ fontSize: 20,
4114
+ padding: 4
4115
+ },
4116
+ section: {
4117
+ gap: 12,
4118
+ paddingTop: 8
4119
+ },
4120
+ sectionLabel: {
4121
+ fontSize: 15,
4122
+ fontWeight: "600"
4123
+ },
4124
+ teamsRow: {
4125
+ flexDirection: "row",
4126
+ gap: 12
4127
+ },
4128
+ summaryCard: {
4129
+ marginTop: 20,
4130
+ borderRadius: 16,
4131
+ borderWidth: 1,
4132
+ overflow: "hidden"
4133
+ },
4134
+ summaryRow: {
4135
+ flexDirection: "row",
4136
+ alignItems: "center",
4137
+ justifyContent: "space-between",
4138
+ paddingHorizontal: 16,
4139
+ paddingVertical: 14
4140
+ },
4141
+ summaryLabel: {
4142
+ fontSize: 14
4143
+ },
4144
+ summaryValue: {
4145
+ fontSize: 15,
4146
+ fontWeight: "700"
4147
+ },
4148
+ summarySep: {
4149
+ height: 1,
4150
+ marginHorizontal: 16
4151
+ },
4152
+ errorBox: {
4153
+ marginTop: 16,
4154
+ borderRadius: 12,
4155
+ borderWidth: 1,
4156
+ padding: 12
4157
+ },
4158
+ errorText: {
4159
+ fontSize: 13,
4160
+ fontWeight: "500"
4161
+ },
4162
+ ctaButton: {
4163
+ marginTop: 20,
4164
+ height: 56,
4165
+ borderRadius: 14,
4166
+ justifyContent: "center",
4167
+ alignItems: "center"
4168
+ },
4169
+ ctaText: {
4170
+ color: "#FFFFFF",
4171
+ fontSize: 16,
4172
+ fontWeight: "700"
4173
+ },
4174
+ ctaLoading: {
4175
+ flexDirection: "row",
4176
+ alignItems: "center",
4177
+ gap: 10
4178
+ },
4179
+ // Team button styles
4180
+ teamOption: {
4181
+ flex: 1,
4182
+ borderWidth: 2,
4183
+ borderRadius: 16,
4184
+ padding: 16,
4185
+ alignItems: "center",
4186
+ gap: 8
4187
+ },
4188
+ teamLogo: {
4189
+ width: 48,
4190
+ height: 48,
4191
+ borderRadius: 24
4192
+ },
4193
+ teamLogoPlaceholder: {
4194
+ backgroundColor: "rgba(128,128,128,0.2)"
4195
+ },
4196
+ teamName: {
4197
+ fontSize: 15,
4198
+ fontWeight: "700"
4199
+ },
4200
+ teamOdds: {
4201
+ fontSize: 20,
4202
+ fontWeight: "800"
4203
+ },
4204
+ teamBets: {
4205
+ fontSize: 12
4206
+ },
4207
+ teamBadge: {
4208
+ borderRadius: 8,
4209
+ paddingHorizontal: 12,
4210
+ paddingVertical: 4,
4211
+ marginTop: 4
4212
+ },
4213
+ teamBadgeText: {
4214
+ color: "#FFF",
4215
+ fontSize: 12,
4216
+ fontWeight: "700"
4217
+ }
4218
+ });
3828
4219
  // Annotate the CommonJS export names for ESM import in node:
3829
4220
  0 && (module.exports = {
3830
4221
  AuthGate,
@@ -3837,6 +4228,7 @@ var styles9 = import_react_native14.StyleSheet.create({
3837
4228
  DubsProvider,
3838
4229
  GamePoster,
3839
4230
  JoinGameButton,
4231
+ JoinGameSheet,
3840
4232
  LivePoolsCard,
3841
4233
  MwaWalletAdapter,
3842
4234
  NETWORK_CONFIG,