@dubsdotapp/expo 0.2.5 → 0.2.7

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.mjs CHANGED
@@ -266,6 +266,33 @@ var DubsClient = class {
266
266
  message: res.message
267
267
  };
268
268
  }
269
+ // ── Custom Game Lifecycle (game_mode=6) ──
270
+ async createCustomGame(params) {
271
+ const res = await this.request(
272
+ "POST",
273
+ "/games/custom/create",
274
+ params
275
+ );
276
+ return {
277
+ gameId: res.gameId,
278
+ gameAddress: res.gameAddress,
279
+ transaction: res.transaction,
280
+ lockTimestamp: res.lockTimestamp
281
+ };
282
+ }
283
+ async confirmCustomGame(params) {
284
+ const res = await this.request(
285
+ "POST",
286
+ "/games/custom/confirm",
287
+ params
288
+ );
289
+ return {
290
+ gameId: res.gameId,
291
+ signature: res.signature,
292
+ explorerUrl: res.explorerUrl,
293
+ message: res.message
294
+ };
295
+ }
269
296
  async buildClaimTransaction(params) {
270
297
  const res = await this.request(
271
298
  "POST",
@@ -461,7 +488,7 @@ function createSecureStoreStorage() {
461
488
  }
462
489
 
463
490
  // src/provider.tsx
464
- import { createContext as createContext3, useContext as useContext3, useMemo, useCallback as useCallback11, useState as useState11, useEffect as useEffect7 } from "react";
491
+ import { createContext as createContext3, useContext as useContext3, useMemo, useCallback as useCallback12, useState as useState12, useEffect as useEffect7 } from "react";
465
492
  import { Connection } from "@solana/web3.js";
466
493
 
467
494
  // src/managed-wallet.tsx
@@ -856,7 +883,7 @@ function ManagedWalletProvider({
856
883
  }
857
884
 
858
885
  // src/ui/AuthGate.tsx
859
- import React2, { useState as useState10, useEffect as useEffect6, useRef as useRef3, useCallback as useCallback10 } from "react";
886
+ import React2, { useState as useState11, useEffect as useEffect6, useRef as useRef3, useCallback as useCallback11 } from "react";
860
887
  import {
861
888
  View as View2,
862
889
  Text as Text2,
@@ -1165,8 +1192,69 @@ function useClaim() {
1165
1192
  return { execute, status, error, data, reset };
1166
1193
  }
1167
1194
 
1195
+ // src/hooks/useCreateCustomGame.ts
1196
+ import { useState as useState9, useCallback as useCallback9 } from "react";
1197
+ function useCreateCustomGame() {
1198
+ const { client, wallet } = useDubs();
1199
+ const [status, setStatus] = useState9("idle");
1200
+ const [error, setError] = useState9(null);
1201
+ const [data, setData] = useState9(null);
1202
+ const reset = useCallback9(() => {
1203
+ setStatus("idle");
1204
+ setError(null);
1205
+ setData(null);
1206
+ }, []);
1207
+ const execute = useCallback9(async (params) => {
1208
+ setStatus("building");
1209
+ setError(null);
1210
+ setData(null);
1211
+ try {
1212
+ console.log("[useCreateCustomGame] Step 1: Building transaction...");
1213
+ const createResult = await client.createCustomGame(params);
1214
+ console.log("[useCreateCustomGame] Step 1 done:", { gameId: createResult.gameId, gameAddress: createResult.gameAddress });
1215
+ setStatus("signing");
1216
+ console.log("[useCreateCustomGame] Step 2: Signing and sending...");
1217
+ const signature = await signAndSendBase64Transaction(
1218
+ createResult.transaction,
1219
+ wallet
1220
+ );
1221
+ console.log("[useCreateCustomGame] Step 2 done. Signature:", signature);
1222
+ setStatus("confirming");
1223
+ console.log("[useCreateCustomGame] Step 3: Confirming with backend...");
1224
+ await client.confirmCustomGame({
1225
+ gameId: createResult.gameId,
1226
+ playerWallet: params.playerWallet,
1227
+ signature,
1228
+ teamChoice: params.teamChoice,
1229
+ wagerAmount: params.wagerAmount,
1230
+ role: "creator",
1231
+ gameAddress: createResult.gameAddress
1232
+ });
1233
+ console.log("[useCreateCustomGame] Step 3 done.");
1234
+ const explorerUrl = `https://solscan.io/tx/${signature}`;
1235
+ const result = {
1236
+ gameId: createResult.gameId,
1237
+ gameAddress: createResult.gameAddress,
1238
+ signature,
1239
+ explorerUrl
1240
+ };
1241
+ setData(result);
1242
+ setStatus("success");
1243
+ console.log("[useCreateCustomGame] Complete!");
1244
+ return result;
1245
+ } catch (err) {
1246
+ console.error("[useCreateCustomGame] FAILED:", err);
1247
+ const error2 = err instanceof Error ? err : new Error(String(err));
1248
+ setError(error2);
1249
+ setStatus("error");
1250
+ throw error2;
1251
+ }
1252
+ }, [client, wallet]);
1253
+ return { execute, status, error, data, reset };
1254
+ }
1255
+
1168
1256
  // src/hooks/useAuth.ts
1169
- import { useState as useState9, useCallback as useCallback9, useRef as useRef2, useContext as useContext2 } from "react";
1257
+ import { useState as useState10, useCallback as useCallback10, useRef as useRef2, useContext as useContext2 } from "react";
1170
1258
  import bs58 from "bs58";
1171
1259
 
1172
1260
  // src/auth-context.ts
@@ -1177,12 +1265,12 @@ var AuthContext = createContext2(null);
1177
1265
  function useAuth() {
1178
1266
  const sharedAuth = useContext2(AuthContext);
1179
1267
  const { client, wallet } = useDubs();
1180
- const [status, setStatus] = useState9("idle");
1181
- const [user, setUser] = useState9(null);
1182
- const [token, setToken] = useState9(null);
1183
- const [error, setError] = useState9(null);
1268
+ const [status, setStatus] = useState10("idle");
1269
+ const [user, setUser] = useState10(null);
1270
+ const [token, setToken] = useState10(null);
1271
+ const [error, setError] = useState10(null);
1184
1272
  const pendingAuth = useRef2(null);
1185
- const reset = useCallback9(() => {
1273
+ const reset = useCallback10(() => {
1186
1274
  setStatus("idle");
1187
1275
  setUser(null);
1188
1276
  setToken(null);
@@ -1190,7 +1278,7 @@ function useAuth() {
1190
1278
  pendingAuth.current = null;
1191
1279
  client.setToken(null);
1192
1280
  }, [client]);
1193
- const authenticate = useCallback9(async () => {
1281
+ const authenticate = useCallback10(async () => {
1194
1282
  try {
1195
1283
  if (!wallet.publicKey) {
1196
1284
  throw new Error("Wallet not connected");
@@ -1221,7 +1309,7 @@ function useAuth() {
1221
1309
  setStatus("error");
1222
1310
  }
1223
1311
  }, [client, wallet]);
1224
- const register = useCallback9(async (username, referralCode, avatarUrl) => {
1312
+ const register = useCallback10(async (username, referralCode, avatarUrl) => {
1225
1313
  try {
1226
1314
  const pending = pendingAuth.current;
1227
1315
  if (!pending) {
@@ -1247,7 +1335,7 @@ function useAuth() {
1247
1335
  setStatus("error");
1248
1336
  }
1249
1337
  }, [client]);
1250
- const logout = useCallback9(async () => {
1338
+ const logout = useCallback10(async () => {
1251
1339
  try {
1252
1340
  await client.logout();
1253
1341
  } catch {
@@ -1258,7 +1346,7 @@ function useAuth() {
1258
1346
  setError(null);
1259
1347
  pendingAuth.current = null;
1260
1348
  }, [client]);
1261
- const restoreSession = useCallback9(async (savedToken) => {
1349
+ const restoreSession = useCallback10(async (savedToken) => {
1262
1350
  try {
1263
1351
  client.setToken(savedToken);
1264
1352
  const me = await client.getMe();
@@ -1317,8 +1405,8 @@ function AuthGate({
1317
1405
  }) {
1318
1406
  const { client } = useDubs();
1319
1407
  const auth = useAuth();
1320
- const [phase, setPhase] = useState10("init");
1321
- const [registrationPhase, setRegistrationPhase] = useState10(false);
1408
+ const [phase, setPhase] = useState11("init");
1409
+ const [registrationPhase, setRegistrationPhase] = useState11(false);
1322
1410
  useEffect6(() => {
1323
1411
  let cancelled = false;
1324
1412
  (async () => {
@@ -1351,12 +1439,12 @@ function AuthGate({
1351
1439
  useEffect6(() => {
1352
1440
  if (auth.token) onSaveToken(auth.token);
1353
1441
  }, [auth.token]);
1354
- const retry = useCallback10(() => {
1442
+ const retry = useCallback11(() => {
1355
1443
  setRegistrationPhase(false);
1356
1444
  auth.reset();
1357
1445
  auth.authenticate();
1358
1446
  }, [auth]);
1359
- const handleRegister = useCallback10(
1447
+ const handleRegister = useCallback11(
1360
1448
  (username, referralCode, avatarUrl) => {
1361
1449
  auth.register(username, referralCode, avatarUrl);
1362
1450
  },
@@ -1459,14 +1547,14 @@ function DefaultRegistrationScreen({
1459
1547
  }) {
1460
1548
  const t = useDubsTheme();
1461
1549
  const accent = accentColor || t.accent;
1462
- const [step, setStep] = useState10(0);
1463
- const [avatarSeed, setAvatarSeed] = useState10(generateSeed);
1464
- const [avatarStyle, setAvatarStyle] = useState10("adventurer");
1465
- const [showStyles, setShowStyles] = useState10(false);
1466
- const [username, setUsername] = useState10("");
1467
- const [referralCode, setReferralCode] = useState10("");
1468
- const [checking, setChecking] = useState10(false);
1469
- const [availability, setAvailability] = useState10(null);
1550
+ const [step, setStep] = useState11(0);
1551
+ const [avatarSeed, setAvatarSeed] = useState11(generateSeed);
1552
+ const [avatarStyle, setAvatarStyle] = useState11("adventurer");
1553
+ const [showStyles, setShowStyles] = useState11(false);
1554
+ const [username, setUsername] = useState11("");
1555
+ const [referralCode, setReferralCode] = useState11("");
1556
+ const [checking, setChecking] = useState11(false);
1557
+ const [availability, setAvailability] = useState11(null);
1470
1558
  const debounceRef = useRef3(null);
1471
1559
  const fadeAnim = useRef3(new Animated.Value(1)).current;
1472
1560
  const slideAnim = useRef3(new Animated.Value(0)).current;
@@ -1494,7 +1582,7 @@ function DefaultRegistrationScreen({
1494
1582
  if (debounceRef.current) clearTimeout(debounceRef.current);
1495
1583
  };
1496
1584
  }, [username, client]);
1497
- const animateToStep = useCallback10((newStep) => {
1585
+ const animateToStep = useCallback11((newStep) => {
1498
1586
  const dir = newStep > step ? 1 : -1;
1499
1587
  Keyboard.dismiss();
1500
1588
  Animated.parallel([
@@ -1816,7 +1904,7 @@ function DubsProvider({
1816
1904
  const client = useMemo(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
1817
1905
  const connection = useMemo(() => new Connection(rpcUrl, { commitment: "confirmed" }), [rpcUrl]);
1818
1906
  const storage = useMemo(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
1819
- const [uiConfig, setUiConfig] = useState11(null);
1907
+ const [uiConfig, setUiConfig] = useState12(null);
1820
1908
  useEffect7(() => {
1821
1909
  client.getAppConfig().then((config2) => {
1822
1910
  console.log("[DubsProvider] UI config loaded:", JSON.stringify(config2));
@@ -1892,7 +1980,7 @@ function ManagedInner({
1892
1980
  children
1893
1981
  }) {
1894
1982
  const managedDisconnect = useDisconnect();
1895
- const disconnect = useCallback11(async () => {
1983
+ const disconnect = useCallback12(async () => {
1896
1984
  client.setToken(null);
1897
1985
  await managedDisconnect?.();
1898
1986
  }, [client, managedDisconnect]);
@@ -1932,7 +2020,7 @@ function ExternalWalletProvider({
1932
2020
  uiConfig,
1933
2021
  children
1934
2022
  }) {
1935
- const disconnect = useCallback11(async () => {
2023
+ const disconnect = useCallback12(async () => {
1936
2024
  client.setToken(null);
1937
2025
  await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
1938
2026
  });
@@ -2195,7 +2283,7 @@ var styles3 = StyleSheet4.create({
2195
2283
  });
2196
2284
 
2197
2285
  // src/ui/game/GamePoster.tsx
2198
- import { useState as useState12 } from "react";
2286
+ import { useState as useState13 } from "react";
2199
2287
  import { StyleSheet as StyleSheet5, View as View5, Text as Text5 } from "react-native";
2200
2288
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2201
2289
  function computeCountdown(lockTimestamp) {
@@ -2245,7 +2333,7 @@ function GamePoster({ game, ImageComponent }) {
2245
2333
  ] });
2246
2334
  }
2247
2335
  function TeamLogoInternal({ url, size, Img }) {
2248
- const [failed, setFailed] = useState12(false);
2336
+ const [failed, setFailed] = useState13(false);
2249
2337
  if (!url || failed) {
2250
2338
  return /* @__PURE__ */ jsx7(View5, { style: [styles4.logoPlaceholder, { width: size, height: size, borderRadius: size / 2 }] });
2251
2339
  }
@@ -2425,7 +2513,7 @@ var styles5 = StyleSheet6.create({
2425
2513
  });
2426
2514
 
2427
2515
  // src/ui/game/PickWinnerCard.tsx
2428
- import { useState as useState13, useMemo as useMemo4 } from "react";
2516
+ import { useState as useState14, useMemo as useMemo4 } from "react";
2429
2517
  import { StyleSheet as StyleSheet7, View as View7, Text as Text7, TouchableOpacity as TouchableOpacity4 } from "react-native";
2430
2518
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2431
2519
  function PickWinnerCard({
@@ -2496,7 +2584,7 @@ function TeamOption({
2496
2584
  ImageComponent,
2497
2585
  t
2498
2586
  }) {
2499
- const [imgFailed, setImgFailed] = useState13(false);
2587
+ const [imgFailed, setImgFailed] = useState14(false);
2500
2588
  const Img = ImageComponent || __require("react-native").Image;
2501
2589
  const showImage = imageUrl && !imgFailed;
2502
2590
  return /* @__PURE__ */ jsxs7(
@@ -2537,7 +2625,7 @@ var styles6 = StyleSheet7.create({
2537
2625
  });
2538
2626
 
2539
2627
  // src/ui/game/PlayersCard.tsx
2540
- import { useState as useState14 } from "react";
2628
+ import { useState as useState15 } from "react";
2541
2629
  import { StyleSheet as StyleSheet8, View as View8, Text as Text8 } from "react-native";
2542
2630
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2543
2631
  function truncateWallet(addr, chars) {
@@ -2586,7 +2674,7 @@ function BettorRow({
2586
2674
  ImageComponent,
2587
2675
  t
2588
2676
  }) {
2589
- const [imgFailed, setImgFailed] = useState14(false);
2677
+ const [imgFailed, setImgFailed] = useState15(false);
2590
2678
  const Img = ImageComponent || __require("react-native").Image;
2591
2679
  const showAvatar = bettor.avatar && !imgFailed;
2592
2680
  return /* @__PURE__ */ jsxs8(View8, { style: [styles7.row, !isFirst && { borderTopColor: t.border, borderTopWidth: 1 }], children: [
@@ -2663,9 +2751,368 @@ var styles8 = StyleSheet9.create({
2663
2751
  buttonText: { color: "#000", fontSize: 16, fontWeight: "800" },
2664
2752
  joiningRow: { flexDirection: "row", alignItems: "center", gap: 10 }
2665
2753
  });
2754
+
2755
+ // src/ui/game/CreateCustomGameSheet.tsx
2756
+ import { useState as useState16, useEffect as useEffect8, useRef as useRef4, useCallback as useCallback13 } from "react";
2757
+ import {
2758
+ View as View10,
2759
+ Text as Text10,
2760
+ TextInput as TextInput2,
2761
+ TouchableOpacity as TouchableOpacity6,
2762
+ ActivityIndicator as ActivityIndicator5,
2763
+ Modal,
2764
+ Animated as Animated2,
2765
+ StyleSheet as StyleSheet10,
2766
+ KeyboardAvoidingView as KeyboardAvoidingView2,
2767
+ Platform as Platform2
2768
+ } from "react-native";
2769
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2770
+ var STATUS_LABELS2 = {
2771
+ building: "Building transaction...",
2772
+ signing: "Approve in wallet...",
2773
+ confirming: "Confirming...",
2774
+ success: "Game Created!"
2775
+ };
2776
+ function CreateCustomGameSheet({
2777
+ visible,
2778
+ onDismiss,
2779
+ title,
2780
+ maxPlayers = 2,
2781
+ fee = 5,
2782
+ presetAmounts = [0.01, 0.1, 0.5, 1],
2783
+ defaultAmount = 0.01,
2784
+ metadata,
2785
+ onSuccess,
2786
+ onError
2787
+ }) {
2788
+ const t = useDubsTheme();
2789
+ const { wallet } = useDubs();
2790
+ const mutation = useCreateCustomGame();
2791
+ const [selectedAmount, setSelectedAmount] = useState16(null);
2792
+ const [customAmount, setCustomAmount] = useState16("");
2793
+ const [isCustom, setIsCustom] = useState16(false);
2794
+ const overlayOpacity = useRef4(new Animated2.Value(0)).current;
2795
+ useEffect8(() => {
2796
+ Animated2.timing(overlayOpacity, {
2797
+ toValue: visible ? 1 : 0,
2798
+ duration: 250,
2799
+ useNativeDriver: true
2800
+ }).start();
2801
+ }, [visible, overlayOpacity]);
2802
+ useEffect8(() => {
2803
+ if (visible) {
2804
+ setSelectedAmount(defaultAmount ?? null);
2805
+ setCustomAmount("");
2806
+ setIsCustom(false);
2807
+ mutation.reset();
2808
+ }
2809
+ }, [visible]);
2810
+ useEffect8(() => {
2811
+ if (mutation.status === "success" && mutation.data) {
2812
+ onSuccess?.(mutation.data);
2813
+ const timer = setTimeout(() => {
2814
+ onDismiss();
2815
+ }, 1500);
2816
+ return () => clearTimeout(timer);
2817
+ }
2818
+ }, [mutation.status, mutation.data]);
2819
+ useEffect8(() => {
2820
+ if (mutation.status === "error" && mutation.error) {
2821
+ onError?.(mutation.error);
2822
+ }
2823
+ }, [mutation.status, mutation.error]);
2824
+ const handlePresetSelect = useCallback13((amount) => {
2825
+ setSelectedAmount(amount);
2826
+ setIsCustom(false);
2827
+ setCustomAmount("");
2828
+ }, []);
2829
+ const handleCustomSelect = useCallback13(() => {
2830
+ setIsCustom(true);
2831
+ setSelectedAmount(null);
2832
+ }, []);
2833
+ const handleCustomAmountChange = useCallback13((text) => {
2834
+ const cleaned = text.replace(/[^0-9.]/g, "").replace(/(\..*?)\..*/g, "$1");
2835
+ setCustomAmount(cleaned);
2836
+ const parsed = parseFloat(cleaned);
2837
+ setSelectedAmount(parsed > 0 ? parsed : null);
2838
+ }, []);
2839
+ const effectiveAmount = selectedAmount;
2840
+ const playerCount = maxPlayers || 2;
2841
+ const pot = effectiveAmount ? effectiveAmount * playerCount : 0;
2842
+ const winnerTakes = pot * (1 - fee / 100);
2843
+ const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
2844
+ const canCreate = effectiveAmount !== null && effectiveAmount > 0 && !isMutating && mutation.status !== "success";
2845
+ const handleCreate = useCallback13(async () => {
2846
+ if (!effectiveAmount || !wallet.publicKey) return;
2847
+ try {
2848
+ await mutation.execute({
2849
+ playerWallet: wallet.publicKey.toBase58(),
2850
+ teamChoice: "home",
2851
+ wagerAmount: effectiveAmount,
2852
+ title,
2853
+ maxPlayers,
2854
+ metadata
2855
+ });
2856
+ } catch {
2857
+ }
2858
+ }, [effectiveAmount, wallet.publicKey, mutation.execute, title, maxPlayers, metadata]);
2859
+ const statusLabel = STATUS_LABELS2[mutation.status] || "";
2860
+ const playersLabel = playerCount === 2 ? "2 (1v1)" : `${playerCount} players`;
2861
+ return /* @__PURE__ */ jsxs10(
2862
+ Modal,
2863
+ {
2864
+ visible,
2865
+ animationType: "slide",
2866
+ transparent: true,
2867
+ onRequestClose: onDismiss,
2868
+ children: [
2869
+ /* @__PURE__ */ jsx12(Animated2.View, { style: [styles9.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ jsx12(TouchableOpacity6, { style: styles9.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
2870
+ /* @__PURE__ */ jsx12(
2871
+ KeyboardAvoidingView2,
2872
+ {
2873
+ style: styles9.keyboardView,
2874
+ behavior: Platform2.OS === "ios" ? "padding" : void 0,
2875
+ children: /* @__PURE__ */ jsx12(View10, { style: styles9.sheetPositioner, children: /* @__PURE__ */ jsxs10(View10, { style: [styles9.sheet, { backgroundColor: t.background }], children: [
2876
+ /* @__PURE__ */ jsx12(View10, { style: styles9.handleRow, children: /* @__PURE__ */ jsx12(View10, { style: [styles9.handle, { backgroundColor: t.textMuted }] }) }),
2877
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.header, children: [
2878
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.headerTitle, { color: t.text }], children: "New Game" }),
2879
+ /* @__PURE__ */ jsx12(TouchableOpacity6, { onPress: onDismiss, activeOpacity: 0.8, children: /* @__PURE__ */ jsx12(Text10, { style: [styles9.closeButton, { color: t.textMuted }], children: "\u2715" }) })
2880
+ ] }),
2881
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.section, children: [
2882
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.sectionLabel, { color: t.textSecondary }], children: "Buy-In Amount" }),
2883
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.chipsRow, children: [
2884
+ presetAmounts.map((amount) => {
2885
+ const active = !isCustom && selectedAmount === amount;
2886
+ return /* @__PURE__ */ jsx12(
2887
+ TouchableOpacity6,
2888
+ {
2889
+ style: [
2890
+ styles9.chip,
2891
+ { borderColor: active ? t.accent : t.border },
2892
+ active && { backgroundColor: t.accent }
2893
+ ],
2894
+ onPress: () => handlePresetSelect(amount),
2895
+ activeOpacity: 0.8,
2896
+ children: /* @__PURE__ */ jsxs10(Text10, { style: [styles9.chipText, { color: active ? "#FFFFFF" : t.text }], children: [
2897
+ amount,
2898
+ " SOL"
2899
+ ] })
2900
+ },
2901
+ amount
2902
+ );
2903
+ }),
2904
+ /* @__PURE__ */ jsx12(
2905
+ TouchableOpacity6,
2906
+ {
2907
+ style: [
2908
+ styles9.chip,
2909
+ { borderColor: isCustom ? t.accent : t.border },
2910
+ isCustom && { backgroundColor: t.accent }
2911
+ ],
2912
+ onPress: handleCustomSelect,
2913
+ activeOpacity: 0.8,
2914
+ children: /* @__PURE__ */ jsx12(Text10, { style: [styles9.chipText, { color: isCustom ? "#FFFFFF" : t.text }], children: "Custom" })
2915
+ }
2916
+ )
2917
+ ] }),
2918
+ isCustom && /* @__PURE__ */ jsx12(
2919
+ TextInput2,
2920
+ {
2921
+ style: [styles9.input, { backgroundColor: t.surface, color: t.text, borderColor: t.accent }],
2922
+ placeholder: "Enter amount in SOL",
2923
+ placeholderTextColor: t.textDim,
2924
+ keyboardType: "decimal-pad",
2925
+ value: customAmount,
2926
+ onChangeText: handleCustomAmountChange,
2927
+ autoFocus: true
2928
+ }
2929
+ )
2930
+ ] }),
2931
+ /* @__PURE__ */ jsxs10(View10, { style: [styles9.summaryCard, { backgroundColor: t.surface, borderColor: t.border }], children: [
2932
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.summaryRow, children: [
2933
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryLabel, { color: t.textMuted }], children: "Your buy-in" }),
2934
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryValue, { color: t.text }], children: effectiveAmount ? `${effectiveAmount} SOL` : "\u2014" })
2935
+ ] }),
2936
+ /* @__PURE__ */ jsx12(View10, { style: [styles9.summarySep, { backgroundColor: t.border }] }),
2937
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.summaryRow, children: [
2938
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryLabel, { color: t.textMuted }], children: "Players" }),
2939
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryValue, { color: t.text }], children: playersLabel })
2940
+ ] }),
2941
+ /* @__PURE__ */ jsx12(View10, { style: [styles9.summarySep, { backgroundColor: t.border }] }),
2942
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.summaryRow, children: [
2943
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryLabel, { color: t.textMuted }], children: "Winner Takes" }),
2944
+ /* @__PURE__ */ jsxs10(View10, { style: styles9.winnerCol, children: [
2945
+ /* @__PURE__ */ jsx12(Text10, { style: [styles9.summaryValue, { color: t.success }], children: effectiveAmount ? `${winnerTakes.toFixed(4)} SOL` : "\u2014" }),
2946
+ effectiveAmount ? /* @__PURE__ */ jsxs10(Text10, { style: [styles9.feeNote, { color: t.textDim }], children: [
2947
+ fee,
2948
+ "% platform fee"
2949
+ ] }) : null
2950
+ ] })
2951
+ ] })
2952
+ ] }),
2953
+ mutation.error && /* @__PURE__ */ jsx12(View10, { style: [styles9.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ jsx12(Text10, { style: [styles9.errorText, { color: t.errorText }], children: mutation.error.message }) }),
2954
+ /* @__PURE__ */ jsx12(
2955
+ TouchableOpacity6,
2956
+ {
2957
+ style: [
2958
+ styles9.ctaButton,
2959
+ { backgroundColor: canCreate ? t.accent : t.border }
2960
+ ],
2961
+ disabled: !canCreate,
2962
+ onPress: handleCreate,
2963
+ activeOpacity: 0.8,
2964
+ children: isMutating ? /* @__PURE__ */ jsxs10(View10, { style: styles9.ctaLoading, children: [
2965
+ /* @__PURE__ */ jsx12(ActivityIndicator5, { size: "small", color: "#FFFFFF" }),
2966
+ /* @__PURE__ */ jsx12(Text10, { style: styles9.ctaText, children: statusLabel })
2967
+ ] }) : mutation.status === "success" ? /* @__PURE__ */ jsx12(Text10, { style: styles9.ctaText, children: STATUS_LABELS2.success }) : /* @__PURE__ */ jsx12(Text10, { style: [styles9.ctaText, !canCreate && { opacity: 0.5 }], children: effectiveAmount ? `Create Game \u2014 ${effectiveAmount} SOL` : "Select buy-in amount" })
2968
+ }
2969
+ )
2970
+ ] }) })
2971
+ }
2972
+ )
2973
+ ]
2974
+ }
2975
+ );
2976
+ }
2977
+ var styles9 = StyleSheet10.create({
2978
+ overlay: {
2979
+ ...StyleSheet10.absoluteFillObject,
2980
+ backgroundColor: "rgba(0,0,0,0.5)"
2981
+ },
2982
+ overlayTap: {
2983
+ flex: 1
2984
+ },
2985
+ keyboardView: {
2986
+ flex: 1,
2987
+ justifyContent: "flex-end"
2988
+ },
2989
+ sheetPositioner: {
2990
+ justifyContent: "flex-end"
2991
+ },
2992
+ sheet: {
2993
+ borderTopLeftRadius: 24,
2994
+ borderTopRightRadius: 24,
2995
+ paddingHorizontal: 20,
2996
+ paddingBottom: 40
2997
+ },
2998
+ handleRow: {
2999
+ alignItems: "center",
3000
+ paddingTop: 10,
3001
+ paddingBottom: 8
3002
+ },
3003
+ handle: {
3004
+ width: 36,
3005
+ height: 4,
3006
+ borderRadius: 2,
3007
+ opacity: 0.4
3008
+ },
3009
+ header: {
3010
+ flexDirection: "row",
3011
+ alignItems: "center",
3012
+ justifyContent: "space-between",
3013
+ paddingVertical: 12
3014
+ },
3015
+ headerTitle: {
3016
+ fontSize: 20,
3017
+ fontWeight: "700"
3018
+ },
3019
+ closeButton: {
3020
+ fontSize: 20,
3021
+ padding: 4
3022
+ },
3023
+ section: {
3024
+ gap: 12,
3025
+ paddingTop: 8
3026
+ },
3027
+ sectionLabel: {
3028
+ fontSize: 15,
3029
+ fontWeight: "600"
3030
+ },
3031
+ chipsRow: {
3032
+ flexDirection: "row",
3033
+ flexWrap: "wrap",
3034
+ gap: 10
3035
+ },
3036
+ chip: {
3037
+ paddingHorizontal: 18,
3038
+ paddingVertical: 10,
3039
+ borderRadius: 14,
3040
+ borderWidth: 1.5
3041
+ },
3042
+ chipText: {
3043
+ fontSize: 15,
3044
+ fontWeight: "600"
3045
+ },
3046
+ input: {
3047
+ height: 56,
3048
+ borderRadius: 16,
3049
+ borderWidth: 1.5,
3050
+ paddingHorizontal: 16,
3051
+ fontSize: 16
3052
+ },
3053
+ summaryCard: {
3054
+ marginTop: 20,
3055
+ borderRadius: 16,
3056
+ borderWidth: 1,
3057
+ overflow: "hidden"
3058
+ },
3059
+ summaryRow: {
3060
+ flexDirection: "row",
3061
+ alignItems: "center",
3062
+ justifyContent: "space-between",
3063
+ paddingHorizontal: 16,
3064
+ paddingVertical: 14
3065
+ },
3066
+ summaryLabel: {
3067
+ fontSize: 14
3068
+ },
3069
+ summaryValue: {
3070
+ fontSize: 15,
3071
+ fontWeight: "700"
3072
+ },
3073
+ summarySep: {
3074
+ height: 1,
3075
+ marginHorizontal: 16
3076
+ },
3077
+ winnerCol: {
3078
+ alignItems: "flex-end",
3079
+ gap: 2
3080
+ },
3081
+ feeNote: {
3082
+ fontSize: 11
3083
+ },
3084
+ errorBox: {
3085
+ marginTop: 16,
3086
+ borderRadius: 12,
3087
+ borderWidth: 1,
3088
+ padding: 12
3089
+ },
3090
+ errorText: {
3091
+ fontSize: 13,
3092
+ fontWeight: "500"
3093
+ },
3094
+ ctaButton: {
3095
+ marginTop: 20,
3096
+ height: 56,
3097
+ borderRadius: 14,
3098
+ justifyContent: "center",
3099
+ alignItems: "center"
3100
+ },
3101
+ ctaText: {
3102
+ color: "#FFFFFF",
3103
+ fontSize: 16,
3104
+ fontWeight: "700"
3105
+ },
3106
+ ctaLoading: {
3107
+ flexDirection: "row",
3108
+ alignItems: "center",
3109
+ gap: 10
3110
+ }
3111
+ });
2666
3112
  export {
2667
3113
  AuthGate,
2668
3114
  ConnectWalletScreen,
3115
+ CreateCustomGameSheet,
2669
3116
  DEFAULT_BASE_URL,
2670
3117
  DEFAULT_RPC_URL,
2671
3118
  DubsApiError,
@@ -2689,6 +3136,7 @@ export {
2689
3136
  useAppConfig,
2690
3137
  useAuth,
2691
3138
  useClaim,
3139
+ useCreateCustomGame,
2692
3140
  useCreateGame,
2693
3141
  useDubs,
2694
3142
  useDubsTheme,