@dubsdotapp/expo 0.2.28 → 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.mjs CHANGED
@@ -277,7 +277,8 @@ var DubsClient = class {
277
277
  gameId: res.gameId,
278
278
  gameAddress: res.gameAddress,
279
279
  transaction: res.transaction,
280
- lockTimestamp: res.lockTimestamp
280
+ lockTimestamp: res.lockTimestamp,
281
+ externalGameId: res.externalGameId ?? null
281
282
  };
282
283
  }
283
284
  async confirmCustomGame(params) {
@@ -324,6 +325,7 @@ var DubsClient = class {
324
325
  const qs = new URLSearchParams();
325
326
  if (params?.wallet) qs.set("wallet", params.wallet);
326
327
  if (params?.status) qs.set("status", params.status);
328
+ if (params?.externalGameId) qs.set("externalGameId", params.externalGameId);
327
329
  if (params?.limit != null) qs.set("limit", String(params.limit));
328
330
  if (params?.offset != null) qs.set("offset", String(params.offset));
329
331
  const query = qs.toString();
@@ -455,6 +457,7 @@ var DubsClient = class {
455
457
  // src/storage.ts
456
458
  var STORAGE_KEYS = {
457
459
  MWA_AUTH_TOKEN: "dubs_mwa_auth_token",
460
+ MWA_WALLET_ADDRESS: "dubs_mwa_wallet_address",
458
461
  JWT_TOKEN: "dubs_jwt_token",
459
462
  PHANTOM_SESSION: "dubs_phantom_session",
460
463
  PHANTOM_CONNECT_IN_FLIGHT: "dubs_phantom_connect_in_flight"
@@ -528,6 +531,16 @@ var MwaWalletAdapter = class {
528
531
  setAuthToken(token) {
529
532
  this._authToken = token;
530
533
  }
534
+ /**
535
+ * Restore a previous session silently (no wallet interaction).
536
+ * Sets the public key and auth token so the adapter appears connected.
537
+ * The next signing operation will reauthorize with Phantom.
538
+ */
539
+ restoreSession(token, walletAddressBase58) {
540
+ this._authToken = token;
541
+ this._publicKey = new PublicKey(walletAddressBase58);
542
+ this._connected = true;
543
+ }
531
544
  /**
532
545
  * Connect to a mobile wallet. Call this before any signing.
533
546
  * Tries reauthorize first (if we have a saved token), then falls back to
@@ -1398,19 +1411,20 @@ function ManagedWalletProvider({
1398
1411
  }
1399
1412
  try {
1400
1413
  const savedToken = await storage.getItem(STORAGE_KEYS.MWA_AUTH_TOKEN);
1401
- if (savedToken && !cancelled) {
1402
- console.log(TAG3, "Found saved MWA auth token, reconnecting...");
1403
- adapter.setAuthToken(savedToken);
1404
- await adapter.connect();
1405
- if (!cancelled) {
1406
- console.log(TAG3, "MWA reconnected from saved token");
1407
- setConnected(true);
1408
- }
1414
+ const savedAddress = await storage.getItem(STORAGE_KEYS.MWA_WALLET_ADDRESS);
1415
+ if (savedToken && savedAddress && !cancelled) {
1416
+ console.log(TAG3, "Found saved MWA session, restoring silently for wallet:", savedAddress);
1417
+ adapter.restoreSession(savedToken, savedAddress);
1418
+ setConnected(true);
1409
1419
  } else {
1410
- console.log(TAG3, "No saved MWA auth token");
1420
+ console.log(TAG3, "No saved MWA session (token or address missing)");
1411
1421
  }
1412
1422
  } catch (err) {
1413
- console.log(TAG3, "MWA silent reconnect failed:", err instanceof Error ? err.message : err);
1423
+ console.log(TAG3, "MWA session restore failed:", err instanceof Error ? err.message : err);
1424
+ await storage.deleteItem(STORAGE_KEYS.MWA_AUTH_TOKEN).catch(() => {
1425
+ });
1426
+ await storage.deleteItem(STORAGE_KEYS.MWA_WALLET_ADDRESS).catch(() => {
1427
+ });
1414
1428
  } finally {
1415
1429
  if (!cancelled) {
1416
1430
  console.log(TAG3, "MWA init complete, marking ready");
@@ -1429,7 +1443,12 @@ function ManagedWalletProvider({
1429
1443
  setError(null);
1430
1444
  try {
1431
1445
  await adapter.connect();
1432
- console.log(TAG3, "handleConnect() \u2014 success, wallet:", adapter.publicKey?.toBase58());
1446
+ const walletAddress = adapter.publicKey?.toBase58();
1447
+ console.log(TAG3, "handleConnect() \u2014 success, wallet:", walletAddress);
1448
+ if (!usePhantom && walletAddress) {
1449
+ storage.setItem(STORAGE_KEYS.MWA_WALLET_ADDRESS, walletAddress).catch(() => {
1450
+ });
1451
+ }
1433
1452
  setConnected(true);
1434
1453
  } catch (err) {
1435
1454
  const message = err instanceof Error ? err.message : "Connection failed";
@@ -1438,7 +1457,7 @@ function ManagedWalletProvider({
1438
1457
  } finally {
1439
1458
  setConnecting(false);
1440
1459
  }
1441
- }, [adapter]);
1460
+ }, [adapter, storage, usePhantom]);
1442
1461
  const disconnect = useCallback(async () => {
1443
1462
  console.log(TAG3, "disconnect() \u2014 clearing all state");
1444
1463
  adapter.disconnect?.();
@@ -1450,6 +1469,8 @@ function ManagedWalletProvider({
1450
1469
  }
1451
1470
  await storage.deleteItem(STORAGE_KEYS.MWA_AUTH_TOKEN).catch(() => {
1452
1471
  });
1472
+ await storage.deleteItem(STORAGE_KEYS.MWA_WALLET_ADDRESS).catch(() => {
1473
+ });
1453
1474
  await storage.deleteItem(STORAGE_KEYS.PHANTOM_SESSION).catch(() => {
1454
1475
  });
1455
1476
  await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
@@ -1846,7 +1867,8 @@ function useCreateCustomGame() {
1846
1867
  gameAddress: createResult.gameAddress,
1847
1868
  signature,
1848
1869
  explorerUrl,
1849
- buyIn: params.wagerAmount
1870
+ buyIn: params.wagerAmount,
1871
+ externalGameId: createResult.externalGameId ?? null
1850
1872
  };
1851
1873
  setData(result);
1852
1874
  setStatus("success");
@@ -3446,6 +3468,7 @@ function CreateCustomGameSheet({
3446
3468
  presetAmounts = [0.01, 0.1, 0.5, 1],
3447
3469
  defaultAmount = 0.01,
3448
3470
  metadata,
3471
+ externalGameId,
3449
3472
  onAmountChange,
3450
3473
  onSuccess,
3451
3474
  onError
@@ -3520,11 +3543,12 @@ function CreateCustomGameSheet({
3520
3543
  wagerAmount: effectiveAmount,
3521
3544
  title,
3522
3545
  maxPlayers,
3523
- metadata
3546
+ metadata,
3547
+ externalGameId
3524
3548
  });
3525
3549
  } catch {
3526
3550
  }
3527
- }, [effectiveAmount, wallet.publicKey, mutation.execute, title, maxPlayers, metadata]);
3551
+ }, [effectiveAmount, wallet.publicKey, mutation.execute, title, maxPlayers, metadata, externalGameId]);
3528
3552
  const statusLabel = STATUS_LABELS2[mutation.status] || "";
3529
3553
  const playersLabel = playerCount === 2 ? "2 (1v1)" : `${playerCount} players`;
3530
3554
  return /* @__PURE__ */ jsxs10(
@@ -3778,6 +3802,401 @@ var styles9 = StyleSheet10.create({
3778
3802
  gap: 10
3779
3803
  }
3780
3804
  });
3805
+
3806
+ // src/ui/game/JoinGameSheet.tsx
3807
+ import { useState as useState17, useEffect as useEffect9, useRef as useRef5, useCallback as useCallback14, useMemo as useMemo6 } from "react";
3808
+ import {
3809
+ View as View11,
3810
+ Text as Text11,
3811
+ TouchableOpacity as TouchableOpacity7,
3812
+ ActivityIndicator as ActivityIndicator6,
3813
+ Modal as Modal2,
3814
+ Animated as Animated3,
3815
+ StyleSheet as StyleSheet11,
3816
+ KeyboardAvoidingView as KeyboardAvoidingView3,
3817
+ Platform as Platform5
3818
+ } from "react-native";
3819
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3820
+ var STATUS_LABELS3 = {
3821
+ building: "Building transaction...",
3822
+ signing: "Approve in wallet...",
3823
+ confirming: "Confirming...",
3824
+ success: "Joined!"
3825
+ };
3826
+ var CUSTOM_GAME_MODE = 6;
3827
+ function JoinGameSheet({
3828
+ visible,
3829
+ onDismiss,
3830
+ game,
3831
+ ImageComponent,
3832
+ shortName,
3833
+ homeColor = "#3B82F6",
3834
+ awayColor = "#EF4444",
3835
+ onSuccess,
3836
+ onError
3837
+ }) {
3838
+ const t = useDubsTheme();
3839
+ const { wallet } = useDubs();
3840
+ const mutation = useJoinGame();
3841
+ const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
3842
+ const [selectedTeam, setSelectedTeam] = useState17(null);
3843
+ const overlayOpacity = useRef5(new Animated3.Value(0)).current;
3844
+ useEffect9(() => {
3845
+ Animated3.timing(overlayOpacity, {
3846
+ toValue: visible ? 1 : 0,
3847
+ duration: 250,
3848
+ useNativeDriver: true
3849
+ }).start();
3850
+ }, [visible, overlayOpacity]);
3851
+ useEffect9(() => {
3852
+ if (visible) {
3853
+ setSelectedTeam(isCustomGame ? "away" : null);
3854
+ mutation.reset();
3855
+ }
3856
+ }, [visible]);
3857
+ useEffect9(() => {
3858
+ if (mutation.status === "success" && mutation.data) {
3859
+ onSuccess?.(mutation.data);
3860
+ const timer = setTimeout(() => {
3861
+ onDismiss();
3862
+ }, 1500);
3863
+ return () => clearTimeout(timer);
3864
+ }
3865
+ }, [mutation.status, mutation.data]);
3866
+ useEffect9(() => {
3867
+ if (mutation.status === "error" && mutation.error) {
3868
+ onError?.(mutation.error);
3869
+ }
3870
+ }, [mutation.status, mutation.error]);
3871
+ const opponents = game.opponents || [];
3872
+ const bettors = game.bettors || [];
3873
+ const totalPool = game.totalPool || 0;
3874
+ const homePool = game.homePool || 0;
3875
+ const awayPool = game.awayPool || 0;
3876
+ const buyIn = game.buyIn;
3877
+ const { homeOdds, awayOdds, homeBets, awayBets } = useMemo6(() => ({
3878
+ homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
3879
+ awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
3880
+ homeBets: bettors.filter((b) => b.team === "home").length,
3881
+ awayBets: bettors.filter((b) => b.team === "away").length
3882
+ }), [totalPool, homePool, awayPool, bettors]);
3883
+ const poolAfterJoin = totalPool + buyIn;
3884
+ const selectedOdds = selectedTeam === "home" ? homeOdds : selectedTeam === "away" ? awayOdds : "\u2014";
3885
+ const potentialWinnings = selectedOdds !== "\u2014" ? (parseFloat(selectedOdds) * buyIn).toFixed(4) : "\u2014";
3886
+ const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
3887
+ const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
3888
+ const selectedName = selectedTeam === "home" ? homeName : selectedTeam === "away" ? awayName : "\u2014";
3889
+ const alreadyJoined = useMemo6(() => {
3890
+ if (!wallet.publicKey) return false;
3891
+ const addr = wallet.publicKey.toBase58();
3892
+ return bettors.some((b) => b.wallet === addr);
3893
+ }, [bettors, wallet.publicKey]);
3894
+ const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
3895
+ const canJoin = selectedTeam !== null && !isMutating && mutation.status !== "success" && !alreadyJoined;
3896
+ const handleJoin = useCallback14(async () => {
3897
+ if (!selectedTeam || !wallet.publicKey) return;
3898
+ try {
3899
+ await mutation.execute({
3900
+ playerWallet: wallet.publicKey.toBase58(),
3901
+ gameId: game.gameId,
3902
+ teamChoice: selectedTeam,
3903
+ amount: buyIn
3904
+ });
3905
+ } catch {
3906
+ }
3907
+ }, [selectedTeam, wallet.publicKey, mutation.execute, game.gameId, buyIn]);
3908
+ const statusLabel = STATUS_LABELS3[mutation.status] || "";
3909
+ return /* @__PURE__ */ jsxs11(
3910
+ Modal2,
3911
+ {
3912
+ visible,
3913
+ animationType: "slide",
3914
+ transparent: true,
3915
+ onRequestClose: onDismiss,
3916
+ children: [
3917
+ /* @__PURE__ */ jsx13(Animated3.View, { style: [styles10.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ jsx13(TouchableOpacity7, { style: styles10.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
3918
+ /* @__PURE__ */ jsx13(
3919
+ KeyboardAvoidingView3,
3920
+ {
3921
+ style: styles10.keyboardView,
3922
+ behavior: Platform5.OS === "ios" ? "padding" : void 0,
3923
+ children: /* @__PURE__ */ jsx13(View11, { style: styles10.sheetPositioner, children: /* @__PURE__ */ jsxs11(View11, { style: [styles10.sheet, { backgroundColor: t.background }], children: [
3924
+ /* @__PURE__ */ jsx13(View11, { style: styles10.handleRow, children: /* @__PURE__ */ jsx13(View11, { style: [styles10.handle, { backgroundColor: t.textMuted }] }) }),
3925
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.header, children: [
3926
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.headerTitle, { color: t.text }], children: "Join Game" }),
3927
+ /* @__PURE__ */ jsx13(TouchableOpacity7, { onPress: onDismiss, activeOpacity: 0.8, children: /* @__PURE__ */ jsx13(Text11, { style: [styles10.closeButton, { color: t.textMuted }], children: "\u2715" }) })
3928
+ ] }),
3929
+ !isCustomGame && /* @__PURE__ */ jsxs11(View11, { style: styles10.section, children: [
3930
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
3931
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.teamsRow, children: [
3932
+ /* @__PURE__ */ jsx13(
3933
+ TeamButton,
3934
+ {
3935
+ name: homeName,
3936
+ imageUrl: opponents[0]?.imageUrl,
3937
+ odds: homeOdds,
3938
+ bets: homeBets,
3939
+ color: homeColor,
3940
+ selected: selectedTeam === "home",
3941
+ onPress: () => setSelectedTeam("home"),
3942
+ ImageComponent,
3943
+ t
3944
+ }
3945
+ ),
3946
+ /* @__PURE__ */ jsx13(
3947
+ TeamButton,
3948
+ {
3949
+ name: awayName,
3950
+ imageUrl: opponents[1]?.imageUrl,
3951
+ odds: awayOdds,
3952
+ bets: awayBets,
3953
+ color: awayColor,
3954
+ selected: selectedTeam === "away",
3955
+ onPress: () => setSelectedTeam("away"),
3956
+ ImageComponent,
3957
+ t
3958
+ }
3959
+ )
3960
+ ] })
3961
+ ] }),
3962
+ /* @__PURE__ */ jsxs11(View11, { style: [styles10.summaryCard, { backgroundColor: t.surface, borderColor: t.border }], children: [
3963
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.summaryRow, children: [
3964
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Buy-in" }),
3965
+ /* @__PURE__ */ jsxs11(Text11, { style: [styles10.summaryValue, { color: t.text }], children: [
3966
+ buyIn,
3967
+ " SOL"
3968
+ ] })
3969
+ ] }),
3970
+ /* @__PURE__ */ jsx13(View11, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
3971
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.summaryRow, children: [
3972
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Your side" }),
3973
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryValue, { color: t.text }], children: selectedName })
3974
+ ] }),
3975
+ /* @__PURE__ */ jsx13(View11, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
3976
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.summaryRow, children: [
3977
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Total pool" }),
3978
+ /* @__PURE__ */ jsxs11(Text11, { style: [styles10.summaryValue, { color: t.text }], children: [
3979
+ poolAfterJoin,
3980
+ " SOL"
3981
+ ] })
3982
+ ] }),
3983
+ /* @__PURE__ */ jsx13(View11, { style: [styles10.summarySep, { backgroundColor: t.border }] }),
3984
+ /* @__PURE__ */ jsxs11(View11, { style: styles10.summaryRow, children: [
3985
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryLabel, { color: t.textMuted }], children: "Potential winnings" }),
3986
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.summaryValue, { color: t.success }], children: potentialWinnings !== "\u2014" ? `${potentialWinnings} SOL` : "\u2014" })
3987
+ ] })
3988
+ ] }),
3989
+ alreadyJoined && /* @__PURE__ */ jsx13(View11, { style: [styles10.errorBox, { backgroundColor: t.surface, borderColor: t.border }], children: /* @__PURE__ */ jsx13(Text11, { style: [styles10.errorText, { color: t.textMuted }], children: "You've already joined this game." }) }),
3990
+ mutation.error && /* @__PURE__ */ jsx13(View11, { style: [styles10.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ jsx13(Text11, { style: [styles10.errorText, { color: t.errorText }], children: mutation.error.message }) }),
3991
+ /* @__PURE__ */ jsx13(
3992
+ TouchableOpacity7,
3993
+ {
3994
+ style: [
3995
+ styles10.ctaButton,
3996
+ { backgroundColor: canJoin ? t.accent : t.border }
3997
+ ],
3998
+ disabled: !canJoin,
3999
+ onPress: handleJoin,
4000
+ activeOpacity: 0.8,
4001
+ children: isMutating ? /* @__PURE__ */ jsxs11(View11, { style: styles10.ctaLoading, children: [
4002
+ /* @__PURE__ */ jsx13(ActivityIndicator6, { size: "small", color: "#FFFFFF" }),
4003
+ /* @__PURE__ */ jsx13(Text11, { style: styles10.ctaText, children: statusLabel })
4004
+ ] }) : mutation.status === "success" ? /* @__PURE__ */ jsx13(Text11, { style: styles10.ctaText, children: STATUS_LABELS3.success }) : /* @__PURE__ */ jsx13(Text11, { style: [styles10.ctaText, !canJoin && { opacity: 0.5 }], children: alreadyJoined ? "Already Joined" : selectedTeam ? `Join Game \u2014 ${buyIn} SOL` : "Pick a side to join" })
4005
+ }
4006
+ )
4007
+ ] }) })
4008
+ }
4009
+ )
4010
+ ]
4011
+ }
4012
+ );
4013
+ }
4014
+ function TeamButton({
4015
+ name,
4016
+ imageUrl,
4017
+ odds,
4018
+ bets,
4019
+ color,
4020
+ selected,
4021
+ onPress,
4022
+ ImageComponent,
4023
+ t
4024
+ }) {
4025
+ const [imgFailed, setImgFailed] = useState17(false);
4026
+ const Img = ImageComponent || __require("react-native").Image;
4027
+ const showImage = imageUrl && !imgFailed;
4028
+ return /* @__PURE__ */ jsxs11(
4029
+ TouchableOpacity7,
4030
+ {
4031
+ style: [styles10.teamOption, { borderColor: selected ? color : t.border, backgroundColor: selected ? color + "15" : t.background }],
4032
+ onPress,
4033
+ activeOpacity: 0.7,
4034
+ children: [
4035
+ showImage ? /* @__PURE__ */ jsx13(Img, { source: { uri: imageUrl }, style: styles10.teamLogo, resizeMode: "contain", onError: () => setImgFailed(true) }) : /* @__PURE__ */ jsx13(View11, { style: [styles10.teamLogo, styles10.teamLogoPlaceholder] }),
4036
+ /* @__PURE__ */ jsx13(Text11, { style: [styles10.teamName, { color: t.text }], numberOfLines: 1, children: name }),
4037
+ /* @__PURE__ */ jsxs11(Text11, { style: [styles10.teamOdds, { color }], children: [
4038
+ odds,
4039
+ "x"
4040
+ ] }),
4041
+ /* @__PURE__ */ jsxs11(Text11, { style: [styles10.teamBets, { color: t.textMuted }], children: [
4042
+ bets,
4043
+ " ",
4044
+ bets === 1 ? "bet" : "bets"
4045
+ ] }),
4046
+ selected && /* @__PURE__ */ jsx13(View11, { style: [styles10.teamBadge, { backgroundColor: color }], children: /* @__PURE__ */ jsx13(Text11, { style: styles10.teamBadgeText, children: "Selected" }) })
4047
+ ]
4048
+ }
4049
+ );
4050
+ }
4051
+ var styles10 = StyleSheet11.create({
4052
+ overlay: {
4053
+ ...StyleSheet11.absoluteFillObject,
4054
+ backgroundColor: "rgba(0,0,0,0.5)"
4055
+ },
4056
+ overlayTap: {
4057
+ flex: 1
4058
+ },
4059
+ keyboardView: {
4060
+ flex: 1,
4061
+ justifyContent: "flex-end"
4062
+ },
4063
+ sheetPositioner: {
4064
+ justifyContent: "flex-end"
4065
+ },
4066
+ sheet: {
4067
+ borderTopLeftRadius: 24,
4068
+ borderTopRightRadius: 24,
4069
+ paddingHorizontal: 20,
4070
+ paddingBottom: 40
4071
+ },
4072
+ handleRow: {
4073
+ alignItems: "center",
4074
+ paddingTop: 10,
4075
+ paddingBottom: 8
4076
+ },
4077
+ handle: {
4078
+ width: 36,
4079
+ height: 4,
4080
+ borderRadius: 2,
4081
+ opacity: 0.4
4082
+ },
4083
+ header: {
4084
+ flexDirection: "row",
4085
+ alignItems: "center",
4086
+ justifyContent: "space-between",
4087
+ paddingVertical: 12
4088
+ },
4089
+ headerTitle: {
4090
+ fontSize: 20,
4091
+ fontWeight: "700"
4092
+ },
4093
+ closeButton: {
4094
+ fontSize: 20,
4095
+ padding: 4
4096
+ },
4097
+ section: {
4098
+ gap: 12,
4099
+ paddingTop: 8
4100
+ },
4101
+ sectionLabel: {
4102
+ fontSize: 15,
4103
+ fontWeight: "600"
4104
+ },
4105
+ teamsRow: {
4106
+ flexDirection: "row",
4107
+ gap: 12
4108
+ },
4109
+ summaryCard: {
4110
+ marginTop: 20,
4111
+ borderRadius: 16,
4112
+ borderWidth: 1,
4113
+ overflow: "hidden"
4114
+ },
4115
+ summaryRow: {
4116
+ flexDirection: "row",
4117
+ alignItems: "center",
4118
+ justifyContent: "space-between",
4119
+ paddingHorizontal: 16,
4120
+ paddingVertical: 14
4121
+ },
4122
+ summaryLabel: {
4123
+ fontSize: 14
4124
+ },
4125
+ summaryValue: {
4126
+ fontSize: 15,
4127
+ fontWeight: "700"
4128
+ },
4129
+ summarySep: {
4130
+ height: 1,
4131
+ marginHorizontal: 16
4132
+ },
4133
+ errorBox: {
4134
+ marginTop: 16,
4135
+ borderRadius: 12,
4136
+ borderWidth: 1,
4137
+ padding: 12
4138
+ },
4139
+ errorText: {
4140
+ fontSize: 13,
4141
+ fontWeight: "500"
4142
+ },
4143
+ ctaButton: {
4144
+ marginTop: 20,
4145
+ height: 56,
4146
+ borderRadius: 14,
4147
+ justifyContent: "center",
4148
+ alignItems: "center"
4149
+ },
4150
+ ctaText: {
4151
+ color: "#FFFFFF",
4152
+ fontSize: 16,
4153
+ fontWeight: "700"
4154
+ },
4155
+ ctaLoading: {
4156
+ flexDirection: "row",
4157
+ alignItems: "center",
4158
+ gap: 10
4159
+ },
4160
+ // Team button styles
4161
+ teamOption: {
4162
+ flex: 1,
4163
+ borderWidth: 2,
4164
+ borderRadius: 16,
4165
+ padding: 16,
4166
+ alignItems: "center",
4167
+ gap: 8
4168
+ },
4169
+ teamLogo: {
4170
+ width: 48,
4171
+ height: 48,
4172
+ borderRadius: 24
4173
+ },
4174
+ teamLogoPlaceholder: {
4175
+ backgroundColor: "rgba(128,128,128,0.2)"
4176
+ },
4177
+ teamName: {
4178
+ fontSize: 15,
4179
+ fontWeight: "700"
4180
+ },
4181
+ teamOdds: {
4182
+ fontSize: 20,
4183
+ fontWeight: "800"
4184
+ },
4185
+ teamBets: {
4186
+ fontSize: 12
4187
+ },
4188
+ teamBadge: {
4189
+ borderRadius: 8,
4190
+ paddingHorizontal: 12,
4191
+ paddingVertical: 4,
4192
+ marginTop: 4
4193
+ },
4194
+ teamBadgeText: {
4195
+ color: "#FFF",
4196
+ fontSize: 12,
4197
+ fontWeight: "700"
4198
+ }
4199
+ });
3781
4200
  export {
3782
4201
  AuthGate,
3783
4202
  ConnectWalletScreen,
@@ -3789,6 +4208,7 @@ export {
3789
4208
  DubsProvider,
3790
4209
  GamePoster,
3791
4210
  JoinGameButton,
4211
+ JoinGameSheet,
3792
4212
  LivePoolsCard,
3793
4213
  MwaWalletAdapter,
3794
4214
  NETWORK_CONFIG,