@dubsdotapp/expo 0.5.16 → 0.5.18
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 +2081 -0
- package/dist/index.d.ts +2081 -0
- package/dist/index.js +2102 -170
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2052 -123
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -4
- package/src/chat/hooks.ts +320 -0
- package/src/chat/index.ts +40 -0
- package/src/chat/provider.tsx +213 -0
- package/src/chat/socket.ts +175 -0
- package/src/chat/types.ts +146 -0
- package/src/client.ts +182 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useEnterJackpot.ts +80 -0
- package/src/hooks/useJackpot.ts +37 -0
- package/src/hooks/useJackpotHistory.ts +34 -0
- package/src/index.ts +55 -0
- package/src/types.ts +60 -0
- package/src/ui/game/JoinGameSheet.tsx +173 -16
- package/src/ui/index.ts +4 -0
- package/src/ui/jackpot/JackpotCard.tsx +417 -0
- package/src/ui/jackpot/JackpotSheet.tsx +683 -0
- package/src/ui/jackpot/JackpotWidget.tsx +74 -0
- package/src/ui/jackpot/index.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -32,6 +32,8 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ArcadeLeaderboardSheet: () => ArcadeLeaderboardSheet,
|
|
34
34
|
AuthGate: () => AuthGate,
|
|
35
|
+
ChatProvider: () => ChatProvider,
|
|
36
|
+
ChatSocket: () => ChatSocket,
|
|
35
37
|
ClaimButton: () => ClaimButton,
|
|
36
38
|
ClaimPrizeSheet: () => ClaimPrizeSheet,
|
|
37
39
|
ConnectWalletButton: () => ConnectWalletButton,
|
|
@@ -45,6 +47,9 @@ __export(index_exports, {
|
|
|
45
47
|
DubsProvider: () => DubsProvider,
|
|
46
48
|
EnterArcadePoolSheet: () => EnterArcadePoolSheet,
|
|
47
49
|
GamePoster: () => GamePoster,
|
|
50
|
+
JackpotCard: () => JackpotCard,
|
|
51
|
+
JackpotSheet: () => JackpotSheet,
|
|
52
|
+
JackpotWidget: () => JackpotWidget,
|
|
48
53
|
JoinGameButton: () => JoinGameButton,
|
|
49
54
|
JoinGameSheet: () => JoinGameSheet,
|
|
50
55
|
LivePoolsCard: () => LivePoolsCard,
|
|
@@ -73,23 +78,39 @@ __export(index_exports, {
|
|
|
73
78
|
useArcadePool: () => useArcadePool,
|
|
74
79
|
useArcadePools: () => useArcadePools,
|
|
75
80
|
useAuth: () => useAuth,
|
|
81
|
+
useChatContext: () => useChatContext,
|
|
82
|
+
useChatMessages: () => useChatMessages,
|
|
83
|
+
useChatStatus: () => useChatStatus,
|
|
76
84
|
useClaim: () => useClaim,
|
|
85
|
+
useConversations: () => useConversations,
|
|
77
86
|
useCreateCustomGame: () => useCreateCustomGame,
|
|
78
87
|
useCreateGame: () => useCreateGame,
|
|
88
|
+
useDirectMessages: () => useDirectMessages,
|
|
79
89
|
useDubs: () => useDubs,
|
|
80
90
|
useDubsTheme: () => useDubsTheme,
|
|
81
91
|
useEnterArcadePool: () => useEnterArcadePool,
|
|
92
|
+
useEnterJackpot: () => useEnterJackpot,
|
|
82
93
|
useEvents: () => useEvents,
|
|
94
|
+
useFriendRequests: () => useFriendRequests,
|
|
95
|
+
useFriends: () => useFriends,
|
|
83
96
|
useGame: () => useGame,
|
|
84
97
|
useGames: () => useGames,
|
|
85
98
|
useHasClaimed: () => useHasClaimed,
|
|
86
99
|
useHighlights: () => useHighlights,
|
|
100
|
+
useJackpot: () => useJackpot,
|
|
101
|
+
useJackpotHistory: () => useJackpotHistory,
|
|
87
102
|
useJoinGame: () => useJoinGame,
|
|
88
103
|
useNetworkGames: () => useNetworkGames,
|
|
104
|
+
useOnlineUsers: () => useOnlineUsers,
|
|
89
105
|
usePushNotifications: () => usePushNotifications,
|
|
106
|
+
useRespondToFriendRequest: () => useRespondToFriendRequest,
|
|
107
|
+
useSearchUsers: () => useSearchUsers,
|
|
108
|
+
useSendFriendRequest: () => useSendFriendRequest,
|
|
109
|
+
useSendMessage: () => useSendMessage,
|
|
90
110
|
useShorts: () => useShorts,
|
|
91
111
|
useUFCFightCard: () => useUFCFightCard,
|
|
92
|
-
useUFCFighterDetail: () => useUFCFighterDetail
|
|
112
|
+
useUFCFighterDetail: () => useUFCFighterDetail,
|
|
113
|
+
useUnreadCount: () => useUnreadCount
|
|
93
114
|
});
|
|
94
115
|
module.exports = __toCommonJS(index_exports);
|
|
95
116
|
|
|
@@ -682,6 +703,151 @@ var DubsClient = class {
|
|
|
682
703
|
);
|
|
683
704
|
return res.entry;
|
|
684
705
|
}
|
|
706
|
+
// ── Jackpot ──
|
|
707
|
+
/** Get current jackpot round + last winner */
|
|
708
|
+
async getJackpotCurrent() {
|
|
709
|
+
const res = await this.request(
|
|
710
|
+
"GET",
|
|
711
|
+
"/jackpot/current"
|
|
712
|
+
);
|
|
713
|
+
return { round: res.round, lastWinner: res.lastWinner };
|
|
714
|
+
}
|
|
715
|
+
/** Get current round entries with odds */
|
|
716
|
+
async getJackpotEntries() {
|
|
717
|
+
const res = await this.request(
|
|
718
|
+
"GET",
|
|
719
|
+
"/jackpot/entries"
|
|
720
|
+
);
|
|
721
|
+
return { roundId: res.roundId, entries: res.entries, totalEntries: res.totalEntries };
|
|
722
|
+
}
|
|
723
|
+
/** Get recent jackpot round results */
|
|
724
|
+
async getJackpotHistory(limit) {
|
|
725
|
+
const qs = limit ? `?limit=${limit}` : "";
|
|
726
|
+
const res = await this.request(
|
|
727
|
+
"GET",
|
|
728
|
+
`/jackpot/history${qs}`
|
|
729
|
+
);
|
|
730
|
+
return res.rounds;
|
|
731
|
+
}
|
|
732
|
+
/** Get jackpot protocol config */
|
|
733
|
+
async getJackpotConfig() {
|
|
734
|
+
const res = await this.request(
|
|
735
|
+
"GET",
|
|
736
|
+
"/jackpot/config"
|
|
737
|
+
);
|
|
738
|
+
return res.config;
|
|
739
|
+
}
|
|
740
|
+
/** Build unsigned jackpot enter transaction */
|
|
741
|
+
async buildJackpotEnter(playerAddress, amount) {
|
|
742
|
+
const res = await this.request(
|
|
743
|
+
"POST",
|
|
744
|
+
"/jackpot/build-enter",
|
|
745
|
+
{ playerAddress, amount }
|
|
746
|
+
);
|
|
747
|
+
return { transaction: res.transaction, roundId: res.roundId, amount: res.amount, amountSol: res.amountSol };
|
|
748
|
+
}
|
|
749
|
+
/** Confirm jackpot entry after wallet signs (creates developer attribution) */
|
|
750
|
+
async confirmJackpotEnter(params) {
|
|
751
|
+
const res = await this.request(
|
|
752
|
+
"POST",
|
|
753
|
+
"/jackpot/confirm-enter",
|
|
754
|
+
params
|
|
755
|
+
);
|
|
756
|
+
return { attributed: res.attributed, appId: res.appId, signature: res.signature };
|
|
757
|
+
}
|
|
758
|
+
// ── Chat ──
|
|
759
|
+
/** Get recent global chat messages */
|
|
760
|
+
async getChatMessages(params) {
|
|
761
|
+
const qs = new URLSearchParams();
|
|
762
|
+
if (params?.limit) qs.set("limit", String(params.limit));
|
|
763
|
+
if (params?.before) qs.set("before", String(params.before));
|
|
764
|
+
const query = qs.toString();
|
|
765
|
+
return this.request("GET", `/chat/messages${query ? `?${query}` : ""}`);
|
|
766
|
+
}
|
|
767
|
+
/** Send a message to global chat */
|
|
768
|
+
async sendChatMessage(params) {
|
|
769
|
+
return this.request("POST", "/chat/message", params);
|
|
770
|
+
}
|
|
771
|
+
/** Edit your own message */
|
|
772
|
+
async editChatMessage(id, message) {
|
|
773
|
+
return this.request("PUT", `/chat/message/${id}`, { message });
|
|
774
|
+
}
|
|
775
|
+
/** Delete your own message */
|
|
776
|
+
async deleteChatMessage(id) {
|
|
777
|
+
return this.request("DELETE", `/chat/message/${id}`);
|
|
778
|
+
}
|
|
779
|
+
/** Block a user */
|
|
780
|
+
async blockUser(targetUserId) {
|
|
781
|
+
await this.request("POST", `/chat/block/${targetUserId}`);
|
|
782
|
+
}
|
|
783
|
+
/** Unblock a user */
|
|
784
|
+
async unblockUser(targetUserId) {
|
|
785
|
+
await this.request("DELETE", `/chat/block/${targetUserId}`);
|
|
786
|
+
}
|
|
787
|
+
// ── DMs ──
|
|
788
|
+
/** Get DM conversations inbox */
|
|
789
|
+
async getConversations(limit) {
|
|
790
|
+
const qs = limit ? `?limit=${limit}` : "";
|
|
791
|
+
return this.request("GET", `/dm/conversations${qs}`);
|
|
792
|
+
}
|
|
793
|
+
/** Get conversation history with a specific user */
|
|
794
|
+
async getConversation(walletAddress, params) {
|
|
795
|
+
const qs = new URLSearchParams();
|
|
796
|
+
if (params?.limit) qs.set("limit", String(params.limit));
|
|
797
|
+
if (params?.beforeId) qs.set("beforeId", String(params.beforeId));
|
|
798
|
+
const query = qs.toString();
|
|
799
|
+
return this.request("GET", `/dm/conversation/${encodeURIComponent(walletAddress)}${query ? `?${query}` : ""}`);
|
|
800
|
+
}
|
|
801
|
+
/** Send a direct message */
|
|
802
|
+
async sendDirectMessage(params) {
|
|
803
|
+
return this.request("POST", "/dm/send", params);
|
|
804
|
+
}
|
|
805
|
+
/** Mark all DMs from a user as read */
|
|
806
|
+
async markDMRead(walletAddress) {
|
|
807
|
+
return this.request("POST", `/dm/read/${encodeURIComponent(walletAddress)}`);
|
|
808
|
+
}
|
|
809
|
+
/** Get unread DM count */
|
|
810
|
+
async getDMUnreadCount() {
|
|
811
|
+
return this.request("GET", "/dm/unread");
|
|
812
|
+
}
|
|
813
|
+
/** Delete a DM conversation (soft delete) */
|
|
814
|
+
async deleteConversation(walletAddress) {
|
|
815
|
+
await this.request("DELETE", `/dm/conversation/${encodeURIComponent(walletAddress)}`);
|
|
816
|
+
}
|
|
817
|
+
// ── Social ──
|
|
818
|
+
/** Search users by username */
|
|
819
|
+
async searchUsers(query) {
|
|
820
|
+
const qs = query ? `?q=${encodeURIComponent(query)}` : "";
|
|
821
|
+
return this.request("GET", `/social/search${qs}`);
|
|
822
|
+
}
|
|
823
|
+
/** Send a friend request */
|
|
824
|
+
async sendFriendRequest(targetUserId) {
|
|
825
|
+
return this.request("POST", `/social/friend-request/${targetUserId}`);
|
|
826
|
+
}
|
|
827
|
+
/** Get pending friend requests (received) */
|
|
828
|
+
async getPendingFriendRequests() {
|
|
829
|
+
return this.request("GET", "/social/friend-requests");
|
|
830
|
+
}
|
|
831
|
+
/** Accept a friend request */
|
|
832
|
+
async acceptFriendRequest(requestId) {
|
|
833
|
+
await this.request("POST", `/social/request/${requestId}/accept`);
|
|
834
|
+
}
|
|
835
|
+
/** Reject a friend request */
|
|
836
|
+
async rejectFriendRequest(requestId) {
|
|
837
|
+
await this.request("POST", `/social/request/${requestId}/reject`);
|
|
838
|
+
}
|
|
839
|
+
/** Get friends list */
|
|
840
|
+
async getFriends() {
|
|
841
|
+
return this.request("GET", "/social/friends");
|
|
842
|
+
}
|
|
843
|
+
/** Remove a friend */
|
|
844
|
+
async removeFriend(targetUserId) {
|
|
845
|
+
await this.request("DELETE", `/social/friend/${targetUserId}`);
|
|
846
|
+
}
|
|
847
|
+
/** Get blocked users list */
|
|
848
|
+
async getBlockedUsers() {
|
|
849
|
+
return this.request("GET", "/social/blocked");
|
|
850
|
+
}
|
|
685
851
|
// ── App Config ──
|
|
686
852
|
/** Fetch the app's UI customization config (accent color, icon, tagline, environment) */
|
|
687
853
|
async getAppConfig() {
|
|
@@ -733,7 +899,7 @@ function createSecureStoreStorage() {
|
|
|
733
899
|
}
|
|
734
900
|
|
|
735
901
|
// src/provider.tsx
|
|
736
|
-
var
|
|
902
|
+
var import_react29 = require("react");
|
|
737
903
|
|
|
738
904
|
// src/ui/theme.ts
|
|
739
905
|
var import_react = require("react");
|
|
@@ -1791,7 +1957,7 @@ function ManagedWalletProvider({
|
|
|
1791
1957
|
}
|
|
1792
1958
|
|
|
1793
1959
|
// src/ui/AuthGate.tsx
|
|
1794
|
-
var
|
|
1960
|
+
var import_react28 = __toESM(require("react"));
|
|
1795
1961
|
var import_react_native8 = require("react-native");
|
|
1796
1962
|
|
|
1797
1963
|
// src/hooks/useEvents.ts
|
|
@@ -3002,6 +3168,117 @@ function useArcadeBridge({
|
|
|
3002
3168
|
return { webviewRef, handleMessage, triggerPlay, lastResult, bridgeLoading };
|
|
3003
3169
|
}
|
|
3004
3170
|
|
|
3171
|
+
// src/hooks/useJackpot.ts
|
|
3172
|
+
var import_react25 = require("react");
|
|
3173
|
+
function useJackpot() {
|
|
3174
|
+
const { client } = useDubs();
|
|
3175
|
+
const [round, setRound] = (0, import_react25.useState)(null);
|
|
3176
|
+
const [lastWinner, setLastWinner] = (0, import_react25.useState)(null);
|
|
3177
|
+
const [loading, setLoading] = (0, import_react25.useState)(false);
|
|
3178
|
+
const [error, setError] = (0, import_react25.useState)(null);
|
|
3179
|
+
const fetch2 = (0, import_react25.useCallback)(async () => {
|
|
3180
|
+
setLoading(true);
|
|
3181
|
+
setError(null);
|
|
3182
|
+
try {
|
|
3183
|
+
const result = await client.getJackpotCurrent();
|
|
3184
|
+
setRound(result.round);
|
|
3185
|
+
setLastWinner(result.lastWinner);
|
|
3186
|
+
} catch (err) {
|
|
3187
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3188
|
+
} finally {
|
|
3189
|
+
setLoading(false);
|
|
3190
|
+
}
|
|
3191
|
+
}, [client]);
|
|
3192
|
+
(0, import_react25.useEffect)(() => {
|
|
3193
|
+
fetch2();
|
|
3194
|
+
}, [fetch2]);
|
|
3195
|
+
return { round, lastWinner, loading, error, refetch: fetch2 };
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
// src/hooks/useJackpotHistory.ts
|
|
3199
|
+
var import_react26 = require("react");
|
|
3200
|
+
function useJackpotHistory(limit) {
|
|
3201
|
+
const { client } = useDubs();
|
|
3202
|
+
const [rounds, setRounds] = (0, import_react26.useState)([]);
|
|
3203
|
+
const [loading, setLoading] = (0, import_react26.useState)(false);
|
|
3204
|
+
const [error, setError] = (0, import_react26.useState)(null);
|
|
3205
|
+
const fetch2 = (0, import_react26.useCallback)(async () => {
|
|
3206
|
+
setLoading(true);
|
|
3207
|
+
setError(null);
|
|
3208
|
+
try {
|
|
3209
|
+
const result = await client.getJackpotHistory(limit);
|
|
3210
|
+
setRounds(result);
|
|
3211
|
+
} catch (err) {
|
|
3212
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3213
|
+
} finally {
|
|
3214
|
+
setLoading(false);
|
|
3215
|
+
}
|
|
3216
|
+
}, [client, limit]);
|
|
3217
|
+
(0, import_react26.useEffect)(() => {
|
|
3218
|
+
fetch2();
|
|
3219
|
+
}, [fetch2]);
|
|
3220
|
+
return { rounds, loading, error, refetch: fetch2 };
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
// src/hooks/useEnterJackpot.ts
|
|
3224
|
+
var import_react27 = require("react");
|
|
3225
|
+
function useEnterJackpot() {
|
|
3226
|
+
const { client, wallet, connection } = useDubs();
|
|
3227
|
+
const [status, setStatus] = (0, import_react27.useState)("idle");
|
|
3228
|
+
const [error, setError] = (0, import_react27.useState)(null);
|
|
3229
|
+
const [data, setData] = (0, import_react27.useState)(null);
|
|
3230
|
+
const reset = (0, import_react27.useCallback)(() => {
|
|
3231
|
+
setStatus("idle");
|
|
3232
|
+
setError(null);
|
|
3233
|
+
setData(null);
|
|
3234
|
+
}, []);
|
|
3235
|
+
const execute = (0, import_react27.useCallback)(async (amountLamports) => {
|
|
3236
|
+
if (!wallet.publicKey) throw new Error("Wallet not connected");
|
|
3237
|
+
const walletAddress = wallet.publicKey.toBase58();
|
|
3238
|
+
setStatus("building");
|
|
3239
|
+
setError(null);
|
|
3240
|
+
setData(null);
|
|
3241
|
+
try {
|
|
3242
|
+
console.log("[useEnterJackpot] Step 1: Building transaction...", { walletAddress, amountLamports });
|
|
3243
|
+
const buildResult = await client.buildJackpotEnter(walletAddress, amountLamports);
|
|
3244
|
+
console.log("[useEnterJackpot] Step 1 done:", { roundId: buildResult.roundId, amount: buildResult.amount });
|
|
3245
|
+
setStatus("signing");
|
|
3246
|
+
console.log("[useEnterJackpot] Step 2: Signing and sending...");
|
|
3247
|
+
const signature = await signAndSendBase64Transaction(
|
|
3248
|
+
buildResult.transaction,
|
|
3249
|
+
wallet,
|
|
3250
|
+
connection
|
|
3251
|
+
);
|
|
3252
|
+
console.log("[useEnterJackpot] Step 2 done. Signature:", signature);
|
|
3253
|
+
setStatus("confirming");
|
|
3254
|
+
console.log("[useEnterJackpot] Step 3: Confirming with backend...");
|
|
3255
|
+
await client.confirmJackpotEnter({
|
|
3256
|
+
playerAddress: walletAddress,
|
|
3257
|
+
roundId: buildResult.roundId,
|
|
3258
|
+
amount: amountLamports,
|
|
3259
|
+
signature
|
|
3260
|
+
});
|
|
3261
|
+
console.log("[useEnterJackpot] Step 3 done. Entry confirmed + attributed.");
|
|
3262
|
+
const result = {
|
|
3263
|
+
roundId: buildResult.roundId,
|
|
3264
|
+
amount: buildResult.amount,
|
|
3265
|
+
amountSol: buildResult.amountSol,
|
|
3266
|
+
signature
|
|
3267
|
+
};
|
|
3268
|
+
setData(result);
|
|
3269
|
+
setStatus("success");
|
|
3270
|
+
return result;
|
|
3271
|
+
} catch (err) {
|
|
3272
|
+
console.error("[useEnterJackpot] FAILED:", err);
|
|
3273
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
3274
|
+
setError(e);
|
|
3275
|
+
setStatus("error");
|
|
3276
|
+
throw e;
|
|
3277
|
+
}
|
|
3278
|
+
}, [client, wallet, connection]);
|
|
3279
|
+
return { execute, status, error, data, reset };
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3005
3282
|
// src/ui/AvatarEditor.tsx
|
|
3006
3283
|
var import_react_native7 = require("react-native");
|
|
3007
3284
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -3163,11 +3440,11 @@ function AuthGate({
|
|
|
3163
3440
|
}) {
|
|
3164
3441
|
const { client, pushEnabled } = useDubs();
|
|
3165
3442
|
const auth = useAuth();
|
|
3166
|
-
const [phase, setPhase] = (0,
|
|
3167
|
-
const [registrationPhase, setRegistrationPhase] = (0,
|
|
3168
|
-
const [showPushSetup, setShowPushSetup] = (0,
|
|
3169
|
-
const [isRestoredSession, setIsRestoredSession] = (0,
|
|
3170
|
-
(0,
|
|
3443
|
+
const [phase, setPhase] = (0, import_react28.useState)("init");
|
|
3444
|
+
const [registrationPhase, setRegistrationPhase] = (0, import_react28.useState)(false);
|
|
3445
|
+
const [showPushSetup, setShowPushSetup] = (0, import_react28.useState)(false);
|
|
3446
|
+
const [isRestoredSession, setIsRestoredSession] = (0, import_react28.useState)(false);
|
|
3447
|
+
(0, import_react28.useEffect)(() => {
|
|
3171
3448
|
let cancelled = false;
|
|
3172
3449
|
(async () => {
|
|
3173
3450
|
try {
|
|
@@ -3194,23 +3471,23 @@ function AuthGate({
|
|
|
3194
3471
|
cancelled = true;
|
|
3195
3472
|
};
|
|
3196
3473
|
}, []);
|
|
3197
|
-
(0,
|
|
3474
|
+
(0, import_react28.useEffect)(() => {
|
|
3198
3475
|
if (auth.status === "needsRegistration") setRegistrationPhase(true);
|
|
3199
3476
|
}, [auth.status]);
|
|
3200
|
-
(0,
|
|
3477
|
+
(0, import_react28.useEffect)(() => {
|
|
3201
3478
|
if (pushEnabled && auth.status === "authenticated" && registrationPhase && !isRestoredSession) {
|
|
3202
3479
|
setShowPushSetup(true);
|
|
3203
3480
|
}
|
|
3204
3481
|
}, [pushEnabled, auth.status, registrationPhase, isRestoredSession]);
|
|
3205
|
-
(0,
|
|
3482
|
+
(0, import_react28.useEffect)(() => {
|
|
3206
3483
|
if (auth.token) onSaveToken(auth.token);
|
|
3207
3484
|
}, [auth.token]);
|
|
3208
|
-
const retry = (0,
|
|
3485
|
+
const retry = (0, import_react28.useCallback)(() => {
|
|
3209
3486
|
setRegistrationPhase(false);
|
|
3210
3487
|
auth.reset();
|
|
3211
3488
|
auth.authenticate();
|
|
3212
3489
|
}, [auth]);
|
|
3213
|
-
const handleRegister = (0,
|
|
3490
|
+
const handleRegister = (0, import_react28.useCallback)(
|
|
3214
3491
|
(username, referralCode, avatarUrl) => {
|
|
3215
3492
|
auth.register(username, referralCode, avatarUrl);
|
|
3216
3493
|
},
|
|
@@ -3310,7 +3587,7 @@ function DefaultErrorScreen({ error, onRetry, appName, accentColor }) {
|
|
|
3310
3587
|
function StepIndicator({ currentStep }) {
|
|
3311
3588
|
const t = useDubsTheme();
|
|
3312
3589
|
const steps = [0, 1, 2, 3];
|
|
3313
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native8.View, { style: s.stepRow, children: steps.map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
3590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native8.View, { style: s.stepRow, children: steps.map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react28.default.Fragment, { children: [
|
|
3314
3591
|
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native8.View, { style: [s.stepLine, { backgroundColor: i <= currentStep ? t.success : t.border }] }),
|
|
3315
3592
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3316
3593
|
import_react_native8.View,
|
|
@@ -3334,20 +3611,20 @@ function DefaultRegistrationScreen({
|
|
|
3334
3611
|
}) {
|
|
3335
3612
|
const t = useDubsTheme();
|
|
3336
3613
|
const accent = accentColor || t.accent;
|
|
3337
|
-
const [step, setStep] = (0,
|
|
3338
|
-
const [avatarSeed, setAvatarSeed] = (0,
|
|
3339
|
-
const [avatarStyle, setAvatarStyle] = (0,
|
|
3340
|
-
const [avatarBg, setAvatarBg] = (0,
|
|
3341
|
-
const [showStyles, setShowStyles] = (0,
|
|
3342
|
-
const [username, setUsername] = (0,
|
|
3343
|
-
const [referralCode, setReferralCode] = (0,
|
|
3344
|
-
const [checking, setChecking] = (0,
|
|
3345
|
-
const [availability, setAvailability] = (0,
|
|
3346
|
-
const debounceRef = (0,
|
|
3347
|
-
const fadeAnim = (0,
|
|
3348
|
-
const slideAnim = (0,
|
|
3614
|
+
const [step, setStep] = (0, import_react28.useState)(0);
|
|
3615
|
+
const [avatarSeed, setAvatarSeed] = (0, import_react28.useState)(generateSeed);
|
|
3616
|
+
const [avatarStyle, setAvatarStyle] = (0, import_react28.useState)("adventurer");
|
|
3617
|
+
const [avatarBg, setAvatarBg] = (0, import_react28.useState)("1a1a2e");
|
|
3618
|
+
const [showStyles, setShowStyles] = (0, import_react28.useState)(false);
|
|
3619
|
+
const [username, setUsername] = (0, import_react28.useState)("");
|
|
3620
|
+
const [referralCode, setReferralCode] = (0, import_react28.useState)("");
|
|
3621
|
+
const [checking, setChecking] = (0, import_react28.useState)(false);
|
|
3622
|
+
const [availability, setAvailability] = (0, import_react28.useState)(null);
|
|
3623
|
+
const debounceRef = (0, import_react28.useRef)(null);
|
|
3624
|
+
const fadeAnim = (0, import_react28.useRef)(new import_react_native8.Animated.Value(1)).current;
|
|
3625
|
+
const slideAnim = (0, import_react28.useRef)(new import_react_native8.Animated.Value(0)).current;
|
|
3349
3626
|
const avatarUrl = getAvatarUrl(avatarStyle, avatarSeed, avatarBg);
|
|
3350
|
-
(0,
|
|
3627
|
+
(0, import_react28.useEffect)(() => {
|
|
3351
3628
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3352
3629
|
const trimmed = username.trim();
|
|
3353
3630
|
if (trimmed.length < 3) {
|
|
@@ -3370,7 +3647,7 @@ function DefaultRegistrationScreen({
|
|
|
3370
3647
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3371
3648
|
};
|
|
3372
3649
|
}, [username, client]);
|
|
3373
|
-
const animateToStep = (0,
|
|
3650
|
+
const animateToStep = (0, import_react28.useCallback)((newStep) => {
|
|
3374
3651
|
const dir = newStep > step ? 1 : -1;
|
|
3375
3652
|
import_react_native8.Keyboard.dismiss();
|
|
3376
3653
|
import_react_native8.Animated.parallel([
|
|
@@ -3609,8 +3886,8 @@ function DefaultRegistrationScreen({
|
|
|
3609
3886
|
}
|
|
3610
3887
|
function PushTokenRestorer() {
|
|
3611
3888
|
const push = usePushNotifications();
|
|
3612
|
-
const restored = (0,
|
|
3613
|
-
(0,
|
|
3889
|
+
const restored = (0, import_react28.useRef)(false);
|
|
3890
|
+
(0, import_react28.useEffect)(() => {
|
|
3614
3891
|
if (restored.current) return;
|
|
3615
3892
|
restored.current = true;
|
|
3616
3893
|
push.restoreIfGranted();
|
|
@@ -3625,9 +3902,9 @@ function PushSetupScreen({
|
|
|
3625
3902
|
const t = useDubsTheme();
|
|
3626
3903
|
const accent = accentColor || t.accent;
|
|
3627
3904
|
const push = usePushNotifications();
|
|
3628
|
-
const fadeAnim = (0,
|
|
3629
|
-
const slideAnim = (0,
|
|
3630
|
-
(0,
|
|
3905
|
+
const fadeAnim = (0, import_react28.useRef)(new import_react_native8.Animated.Value(0)).current;
|
|
3906
|
+
const slideAnim = (0, import_react28.useRef)(new import_react_native8.Animated.Value(30)).current;
|
|
3907
|
+
(0, import_react28.useEffect)(() => {
|
|
3631
3908
|
import_react_native8.Animated.parallel([
|
|
3632
3909
|
import_react_native8.Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true }),
|
|
3633
3910
|
import_react_native8.Animated.timing(slideAnim, { toValue: 0, duration: 300, useNativeDriver: true })
|
|
@@ -3763,7 +4040,7 @@ var s = import_react_native8.StyleSheet.create({
|
|
|
3763
4040
|
|
|
3764
4041
|
// src/provider.tsx
|
|
3765
4042
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
3766
|
-
var DubsContext = (0,
|
|
4043
|
+
var DubsContext = (0, import_react29.createContext)(null);
|
|
3767
4044
|
function DubsProvider({
|
|
3768
4045
|
apiKey,
|
|
3769
4046
|
children,
|
|
@@ -3785,11 +4062,11 @@ function DubsProvider({
|
|
|
3785
4062
|
const config = NETWORK_CONFIG[network];
|
|
3786
4063
|
const baseUrl = baseUrlOverride || config.baseUrl;
|
|
3787
4064
|
const rpcUrl = rpcUrlOverride || config.rpcUrl;
|
|
3788
|
-
const client = (0,
|
|
3789
|
-
const storage = (0,
|
|
3790
|
-
const [uiConfig, setUiConfig] = (0,
|
|
3791
|
-
const [resolvedNetwork, setResolvedNetwork] = (0,
|
|
3792
|
-
(0,
|
|
4065
|
+
const client = (0, import_react29.useMemo)(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
|
|
4066
|
+
const storage = (0, import_react29.useMemo)(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
|
|
4067
|
+
const [uiConfig, setUiConfig] = (0, import_react29.useState)(null);
|
|
4068
|
+
const [resolvedNetwork, setResolvedNetwork] = (0, import_react29.useState)(network);
|
|
4069
|
+
(0, import_react29.useEffect)(() => {
|
|
3793
4070
|
client.getAppConfig().then((cfg) => {
|
|
3794
4071
|
console.log("[DubsProvider] UI config loaded:", JSON.stringify(cfg));
|
|
3795
4072
|
setUiConfig(cfg);
|
|
@@ -3805,7 +4082,7 @@ function DubsProvider({
|
|
|
3805
4082
|
const resolvedConfig = NETWORK_CONFIG[resolvedNetwork];
|
|
3806
4083
|
const resolvedRpcUrl = rpcUrlOverride || resolvedConfig.rpcUrl;
|
|
3807
4084
|
const cluster = resolvedConfig.cluster;
|
|
3808
|
-
const connection = (0,
|
|
4085
|
+
const connection = (0, import_react29.useMemo)(() => new import_web34.Connection(resolvedRpcUrl, { commitment: "confirmed" }), [resolvedRpcUrl]);
|
|
3809
4086
|
if (uiConfig === null) return null;
|
|
3810
4087
|
const themeOverrides = {};
|
|
3811
4088
|
if (uiConfig.accentColor) {
|
|
@@ -3881,11 +4158,11 @@ function ManagedInner({
|
|
|
3881
4158
|
children
|
|
3882
4159
|
}) {
|
|
3883
4160
|
const managedDisconnect = useDisconnect();
|
|
3884
|
-
const disconnect = (0,
|
|
4161
|
+
const disconnect = (0, import_react29.useCallback)(async () => {
|
|
3885
4162
|
client.setToken(null);
|
|
3886
4163
|
await managedDisconnect?.();
|
|
3887
4164
|
}, [client, managedDisconnect]);
|
|
3888
|
-
const value = (0,
|
|
4165
|
+
const value = (0, import_react29.useMemo)(
|
|
3889
4166
|
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled }),
|
|
3890
4167
|
[client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled]
|
|
3891
4168
|
);
|
|
@@ -3922,13 +4199,13 @@ function ExternalWalletProvider({
|
|
|
3922
4199
|
pushEnabled,
|
|
3923
4200
|
children
|
|
3924
4201
|
}) {
|
|
3925
|
-
const disconnect = (0,
|
|
4202
|
+
const disconnect = (0, import_react29.useCallback)(async () => {
|
|
3926
4203
|
client.setToken(null);
|
|
3927
4204
|
await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
|
|
3928
4205
|
});
|
|
3929
4206
|
await wallet.disconnect?.();
|
|
3930
4207
|
}, [client, storage, wallet]);
|
|
3931
|
-
const value = (0,
|
|
4208
|
+
const value = (0, import_react29.useMemo)(
|
|
3932
4209
|
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled }),
|
|
3933
4210
|
[client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled]
|
|
3934
4211
|
);
|
|
@@ -3953,14 +4230,14 @@ function ExternalWalletProvider({
|
|
|
3953
4230
|
) });
|
|
3954
4231
|
}
|
|
3955
4232
|
function useDubs() {
|
|
3956
|
-
const ctx = (0,
|
|
4233
|
+
const ctx = (0, import_react29.useContext)(DubsContext);
|
|
3957
4234
|
if (!ctx) {
|
|
3958
4235
|
throw new Error("useDubs must be used within a <DubsProvider>");
|
|
3959
4236
|
}
|
|
3960
4237
|
return ctx;
|
|
3961
4238
|
}
|
|
3962
4239
|
function useAppConfig() {
|
|
3963
|
-
const ctx = (0,
|
|
4240
|
+
const ctx = (0, import_react29.useContext)(DubsContext);
|
|
3964
4241
|
return ctx?.uiConfig || {};
|
|
3965
4242
|
}
|
|
3966
4243
|
|
|
@@ -4018,7 +4295,7 @@ var styles3 = import_react_native9.StyleSheet.create({
|
|
|
4018
4295
|
});
|
|
4019
4296
|
|
|
4020
4297
|
// src/ui/UserProfileCard.tsx
|
|
4021
|
-
var
|
|
4298
|
+
var import_react30 = require("react");
|
|
4022
4299
|
var import_react_native10 = require("react-native");
|
|
4023
4300
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
4024
4301
|
function truncateAddress(address, chars = 4) {
|
|
@@ -4038,7 +4315,7 @@ function UserProfileCard({
|
|
|
4038
4315
|
memberSince
|
|
4039
4316
|
}) {
|
|
4040
4317
|
const t = useDubsTheme();
|
|
4041
|
-
const imageUri = (0,
|
|
4318
|
+
const imageUri = (0, import_react30.useMemo)(
|
|
4042
4319
|
() => ensurePngAvatar(avatarUrl) || `https://api.dicebear.com/9.x/avataaars/png?seed=${walletAddress}&size=128`,
|
|
4043
4320
|
[avatarUrl, walletAddress]
|
|
4044
4321
|
);
|
|
@@ -4231,7 +4508,7 @@ var styles5 = import_react_native11.StyleSheet.create({
|
|
|
4231
4508
|
});
|
|
4232
4509
|
|
|
4233
4510
|
// src/ui/UserProfileSheet.tsx
|
|
4234
|
-
var
|
|
4511
|
+
var import_react31 = require("react");
|
|
4235
4512
|
var import_react_native12 = require("react-native");
|
|
4236
4513
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
4237
4514
|
function truncateAddress3(address, chars = 4) {
|
|
@@ -4249,31 +4526,31 @@ function UserProfileSheet({
|
|
|
4249
4526
|
const { client } = useDubs();
|
|
4250
4527
|
const { refreshUser } = useAuth();
|
|
4251
4528
|
const push = usePushNotifications();
|
|
4252
|
-
const overlayOpacity = (0,
|
|
4253
|
-
const parsed = (0,
|
|
4254
|
-
const [avatarStyle, setAvatarStyle] = (0,
|
|
4255
|
-
const [avatarSeed, setAvatarSeed] = (0,
|
|
4256
|
-
const [bgColor, setBgColor] = (0,
|
|
4257
|
-
const [saving, setSaving] = (0,
|
|
4258
|
-
const [error, setError] = (0,
|
|
4259
|
-
(0,
|
|
4529
|
+
const overlayOpacity = (0, import_react31.useRef)(new import_react_native12.Animated.Value(0)).current;
|
|
4530
|
+
const parsed = (0, import_react31.useMemo)(() => parseAvatarUrl(user.avatar), [user.avatar]);
|
|
4531
|
+
const [avatarStyle, setAvatarStyle] = (0, import_react31.useState)(parsed.style);
|
|
4532
|
+
const [avatarSeed, setAvatarSeed] = (0, import_react31.useState)(parsed.seed);
|
|
4533
|
+
const [bgColor, setBgColor] = (0, import_react31.useState)(parsed.bg);
|
|
4534
|
+
const [saving, setSaving] = (0, import_react31.useState)(false);
|
|
4535
|
+
const [error, setError] = (0, import_react31.useState)(null);
|
|
4536
|
+
(0, import_react31.useEffect)(() => {
|
|
4260
4537
|
const p = parseAvatarUrl(user.avatar);
|
|
4261
4538
|
setAvatarStyle(p.style);
|
|
4262
4539
|
setAvatarSeed(p.seed);
|
|
4263
4540
|
setBgColor(p.bg);
|
|
4264
4541
|
}, [user.avatar]);
|
|
4265
|
-
(0,
|
|
4542
|
+
(0, import_react31.useEffect)(() => {
|
|
4266
4543
|
import_react_native12.Animated.timing(overlayOpacity, {
|
|
4267
4544
|
toValue: visible ? 1 : 0,
|
|
4268
4545
|
duration: 250,
|
|
4269
4546
|
useNativeDriver: true
|
|
4270
4547
|
}).start();
|
|
4271
4548
|
}, [visible, overlayOpacity]);
|
|
4272
|
-
(0,
|
|
4549
|
+
(0, import_react31.useEffect)(() => {
|
|
4273
4550
|
if (visible) setError(null);
|
|
4274
4551
|
}, [visible]);
|
|
4275
4552
|
const currentAvatarUrl = getAvatarUrl(avatarStyle, avatarSeed, bgColor);
|
|
4276
|
-
const saveAvatar = (0,
|
|
4553
|
+
const saveAvatar = (0, import_react31.useCallback)(async (newUrl) => {
|
|
4277
4554
|
setSaving(true);
|
|
4278
4555
|
setError(null);
|
|
4279
4556
|
try {
|
|
@@ -4286,16 +4563,16 @@ function UserProfileSheet({
|
|
|
4286
4563
|
setSaving(false);
|
|
4287
4564
|
}
|
|
4288
4565
|
}, [client, refreshUser, onAvatarUpdated]);
|
|
4289
|
-
const handleStyleChange = (0,
|
|
4566
|
+
const handleStyleChange = (0, import_react31.useCallback)((style) => {
|
|
4290
4567
|
setAvatarStyle(style);
|
|
4291
4568
|
saveAvatar(getAvatarUrl(style, avatarSeed, bgColor));
|
|
4292
4569
|
}, [avatarSeed, bgColor, saveAvatar]);
|
|
4293
|
-
const handleShuffle = (0,
|
|
4570
|
+
const handleShuffle = (0, import_react31.useCallback)(() => {
|
|
4294
4571
|
const newSeed = generateSeed();
|
|
4295
4572
|
setAvatarSeed(newSeed);
|
|
4296
4573
|
saveAvatar(getAvatarUrl(avatarStyle, newSeed, bgColor));
|
|
4297
4574
|
}, [avatarStyle, bgColor, saveAvatar]);
|
|
4298
|
-
const handleBgChange = (0,
|
|
4575
|
+
const handleBgChange = (0, import_react31.useCallback)((color) => {
|
|
4299
4576
|
setBgColor(color);
|
|
4300
4577
|
saveAvatar(getAvatarUrl(avatarStyle, avatarSeed, color));
|
|
4301
4578
|
}, [avatarStyle, avatarSeed, saveAvatar]);
|
|
@@ -4575,7 +4852,7 @@ var styles6 = import_react_native12.StyleSheet.create({
|
|
|
4575
4852
|
});
|
|
4576
4853
|
|
|
4577
4854
|
// src/ui/game/GamePoster.tsx
|
|
4578
|
-
var
|
|
4855
|
+
var import_react32 = require("react");
|
|
4579
4856
|
var import_react_native13 = require("react-native");
|
|
4580
4857
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
4581
4858
|
function computeCountdown(lockTimestamp) {
|
|
@@ -4625,7 +4902,7 @@ function GamePoster({ game, ImageComponent }) {
|
|
|
4625
4902
|
] });
|
|
4626
4903
|
}
|
|
4627
4904
|
function TeamLogoInternal({ url, size, Img }) {
|
|
4628
|
-
const [failed, setFailed] = (0,
|
|
4905
|
+
const [failed, setFailed] = (0, import_react32.useState)(false);
|
|
4629
4906
|
if (!url || failed) {
|
|
4630
4907
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: [styles7.logoPlaceholder, { width: size, height: size, borderRadius: size / 2 }] });
|
|
4631
4908
|
}
|
|
@@ -4726,7 +5003,7 @@ var styles7 = import_react_native13.StyleSheet.create({
|
|
|
4726
5003
|
});
|
|
4727
5004
|
|
|
4728
5005
|
// src/ui/game/LivePoolsCard.tsx
|
|
4729
|
-
var
|
|
5006
|
+
var import_react33 = require("react");
|
|
4730
5007
|
var import_react_native14 = require("react-native");
|
|
4731
5008
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
4732
5009
|
function LivePoolsCard({
|
|
@@ -4742,7 +5019,7 @@ function LivePoolsCard({
|
|
|
4742
5019
|
const homePool = game.homePool || 0;
|
|
4743
5020
|
const awayPool = game.awayPool || 0;
|
|
4744
5021
|
const totalPool = game.totalPool || 0;
|
|
4745
|
-
const { homePercent, awayPercent, homeOdds, awayOdds } = (0,
|
|
5022
|
+
const { homePercent, awayPercent, homeOdds, awayOdds } = (0, import_react33.useMemo)(() => {
|
|
4746
5023
|
return {
|
|
4747
5024
|
homePercent: totalPool > 0 ? homePool / totalPool * 100 : 50,
|
|
4748
5025
|
awayPercent: totalPool > 0 ? awayPool / totalPool * 100 : 50,
|
|
@@ -4805,7 +5082,7 @@ var styles8 = import_react_native14.StyleSheet.create({
|
|
|
4805
5082
|
});
|
|
4806
5083
|
|
|
4807
5084
|
// src/ui/game/PickWinnerCard.tsx
|
|
4808
|
-
var
|
|
5085
|
+
var import_react34 = require("react");
|
|
4809
5086
|
var import_react_native15 = require("react-native");
|
|
4810
5087
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
4811
5088
|
function PickWinnerCard({
|
|
@@ -4823,7 +5100,7 @@ function PickWinnerCard({
|
|
|
4823
5100
|
const totalPool = game.totalPool || 0;
|
|
4824
5101
|
const homePool = game.homePool || 0;
|
|
4825
5102
|
const awayPool = game.awayPool || 0;
|
|
4826
|
-
const { homeOdds, awayOdds, homeBets, awayBets } = (0,
|
|
5103
|
+
const { homeOdds, awayOdds, homeBets, awayBets } = (0, import_react34.useMemo)(() => ({
|
|
4827
5104
|
homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
|
|
4828
5105
|
awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
|
|
4829
5106
|
homeBets: bettors.filter((b) => b.team === "home").length,
|
|
@@ -4876,7 +5153,7 @@ function TeamOption({
|
|
|
4876
5153
|
ImageComponent,
|
|
4877
5154
|
t
|
|
4878
5155
|
}) {
|
|
4879
|
-
const [imgFailed, setImgFailed] = (0,
|
|
5156
|
+
const [imgFailed, setImgFailed] = (0, import_react34.useState)(false);
|
|
4880
5157
|
const Img = ImageComponent || require("react-native").Image;
|
|
4881
5158
|
const showImage = imageUrl && !imgFailed;
|
|
4882
5159
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
@@ -4917,7 +5194,7 @@ var styles9 = import_react_native15.StyleSheet.create({
|
|
|
4917
5194
|
});
|
|
4918
5195
|
|
|
4919
5196
|
// src/ui/game/PlayersCard.tsx
|
|
4920
|
-
var
|
|
5197
|
+
var import_react35 = require("react");
|
|
4921
5198
|
var import_react_native16 = require("react-native");
|
|
4922
5199
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
4923
5200
|
function truncateWallet(addr, chars) {
|
|
@@ -4966,7 +5243,7 @@ function BettorRow({
|
|
|
4966
5243
|
ImageComponent,
|
|
4967
5244
|
t
|
|
4968
5245
|
}) {
|
|
4969
|
-
const [imgFailed, setImgFailed] = (0,
|
|
5246
|
+
const [imgFailed, setImgFailed] = (0, import_react35.useState)(false);
|
|
4970
5247
|
const Img = ImageComponent || require("react-native").Image;
|
|
4971
5248
|
const showAvatar = bettor.avatar && !imgFailed;
|
|
4972
5249
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native16.View, { style: [styles10.row, !isFirst && { borderTopColor: t.border, borderTopWidth: 1 }], children: [
|
|
@@ -4993,7 +5270,7 @@ var styles10 = import_react_native16.StyleSheet.create({
|
|
|
4993
5270
|
});
|
|
4994
5271
|
|
|
4995
5272
|
// src/ui/game/JoinGameButton.tsx
|
|
4996
|
-
var
|
|
5273
|
+
var import_react36 = require("react");
|
|
4997
5274
|
var import_react_native17 = require("react-native");
|
|
4998
5275
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
4999
5276
|
var STATUS_LABELS = {
|
|
@@ -5004,7 +5281,7 @@ var STATUS_LABELS = {
|
|
|
5004
5281
|
};
|
|
5005
5282
|
function JoinGameButton({ game, walletAddress, selectedTeam, status, onJoin }) {
|
|
5006
5283
|
const t = useDubsTheme();
|
|
5007
|
-
const alreadyJoined = (0,
|
|
5284
|
+
const alreadyJoined = (0, import_react36.useMemo)(() => {
|
|
5008
5285
|
if (!walletAddress) return false;
|
|
5009
5286
|
return (game.bettors || []).some((b) => b.wallet === walletAddress);
|
|
5010
5287
|
}, [game.bettors, walletAddress]);
|
|
@@ -5045,7 +5322,7 @@ var styles11 = import_react_native17.StyleSheet.create({
|
|
|
5045
5322
|
});
|
|
5046
5323
|
|
|
5047
5324
|
// src/ui/game/CreateCustomGameSheet.tsx
|
|
5048
|
-
var
|
|
5325
|
+
var import_react37 = require("react");
|
|
5049
5326
|
var import_react_native18 = require("react-native");
|
|
5050
5327
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
5051
5328
|
var STATUS_LABELS2 = {
|
|
@@ -5071,18 +5348,18 @@ function CreateCustomGameSheet({
|
|
|
5071
5348
|
const t = useDubsTheme();
|
|
5072
5349
|
const { wallet } = useDubs();
|
|
5073
5350
|
const mutation = useCreateCustomGame();
|
|
5074
|
-
const [selectedAmount, setSelectedAmount] = (0,
|
|
5075
|
-
const [customAmount, setCustomAmount] = (0,
|
|
5076
|
-
const [isCustom, setIsCustom] = (0,
|
|
5077
|
-
const overlayOpacity = (0,
|
|
5078
|
-
(0,
|
|
5351
|
+
const [selectedAmount, setSelectedAmount] = (0, import_react37.useState)(null);
|
|
5352
|
+
const [customAmount, setCustomAmount] = (0, import_react37.useState)("");
|
|
5353
|
+
const [isCustom, setIsCustom] = (0, import_react37.useState)(false);
|
|
5354
|
+
const overlayOpacity = (0, import_react37.useRef)(new import_react_native18.Animated.Value(0)).current;
|
|
5355
|
+
(0, import_react37.useEffect)(() => {
|
|
5079
5356
|
import_react_native18.Animated.timing(overlayOpacity, {
|
|
5080
5357
|
toValue: visible ? 1 : 0,
|
|
5081
5358
|
duration: 250,
|
|
5082
5359
|
useNativeDriver: true
|
|
5083
5360
|
}).start();
|
|
5084
5361
|
}, [visible, overlayOpacity]);
|
|
5085
|
-
(0,
|
|
5362
|
+
(0, import_react37.useEffect)(() => {
|
|
5086
5363
|
if (visible) {
|
|
5087
5364
|
setSelectedAmount(defaultAmount ?? null);
|
|
5088
5365
|
setCustomAmount("");
|
|
@@ -5090,7 +5367,7 @@ function CreateCustomGameSheet({
|
|
|
5090
5367
|
mutation.reset();
|
|
5091
5368
|
}
|
|
5092
5369
|
}, [visible]);
|
|
5093
|
-
(0,
|
|
5370
|
+
(0, import_react37.useEffect)(() => {
|
|
5094
5371
|
if (mutation.status === "success" && mutation.data) {
|
|
5095
5372
|
onSuccess?.(mutation.data);
|
|
5096
5373
|
const timer = setTimeout(() => {
|
|
@@ -5099,23 +5376,23 @@ function CreateCustomGameSheet({
|
|
|
5099
5376
|
return () => clearTimeout(timer);
|
|
5100
5377
|
}
|
|
5101
5378
|
}, [mutation.status, mutation.data]);
|
|
5102
|
-
(0,
|
|
5379
|
+
(0, import_react37.useEffect)(() => {
|
|
5103
5380
|
if (mutation.status === "error" && mutation.error) {
|
|
5104
5381
|
onError?.(mutation.error);
|
|
5105
5382
|
}
|
|
5106
5383
|
}, [mutation.status, mutation.error]);
|
|
5107
|
-
const handlePresetSelect = (0,
|
|
5384
|
+
const handlePresetSelect = (0, import_react37.useCallback)((amount) => {
|
|
5108
5385
|
setSelectedAmount(amount);
|
|
5109
5386
|
setIsCustom(false);
|
|
5110
5387
|
setCustomAmount("");
|
|
5111
5388
|
onAmountChange?.(amount);
|
|
5112
5389
|
}, [onAmountChange]);
|
|
5113
|
-
const handleCustomSelect = (0,
|
|
5390
|
+
const handleCustomSelect = (0, import_react37.useCallback)(() => {
|
|
5114
5391
|
setIsCustom(true);
|
|
5115
5392
|
setSelectedAmount(null);
|
|
5116
5393
|
onAmountChange?.(null);
|
|
5117
5394
|
}, [onAmountChange]);
|
|
5118
|
-
const handleCustomAmountChange = (0,
|
|
5395
|
+
const handleCustomAmountChange = (0, import_react37.useCallback)((text) => {
|
|
5119
5396
|
const cleaned = text.replace(/[^0-9.]/g, "").replace(/(\..*?)\..*/g, "$1");
|
|
5120
5397
|
setCustomAmount(cleaned);
|
|
5121
5398
|
const parsed = parseFloat(cleaned);
|
|
@@ -5130,7 +5407,7 @@ function CreateCustomGameSheet({
|
|
|
5130
5407
|
const winnerTakes = pot * (1 - fee / 100);
|
|
5131
5408
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
5132
5409
|
const canCreate = finalAmount !== null && finalAmount > 0 && !isMutating && mutation.status !== "success";
|
|
5133
|
-
const handleCreate = (0,
|
|
5410
|
+
const handleCreate = (0, import_react37.useCallback)(async () => {
|
|
5134
5411
|
if (!finalAmount || !wallet.publicKey) return;
|
|
5135
5412
|
try {
|
|
5136
5413
|
await mutation.execute({
|
|
@@ -5399,11 +5676,11 @@ var styles12 = import_react_native18.StyleSheet.create({
|
|
|
5399
5676
|
});
|
|
5400
5677
|
|
|
5401
5678
|
// src/ui/game/JoinGameSheet.tsx
|
|
5402
|
-
var
|
|
5679
|
+
var import_react40 = require("react");
|
|
5403
5680
|
var import_react_native21 = require("react-native");
|
|
5404
5681
|
|
|
5405
5682
|
// src/ui/game/SolSlider.tsx
|
|
5406
|
-
var
|
|
5683
|
+
var import_react38 = require("react");
|
|
5407
5684
|
var import_react_native19 = require("react-native");
|
|
5408
5685
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
5409
5686
|
var THUMB_SIZE = 32;
|
|
@@ -5422,9 +5699,9 @@ function SolSlider({
|
|
|
5422
5699
|
}) {
|
|
5423
5700
|
const t = useDubsTheme();
|
|
5424
5701
|
const accent = accentColor || t.accent;
|
|
5425
|
-
const trackRef = (0,
|
|
5426
|
-
const trackWidth = (0,
|
|
5427
|
-
const lastTickValue = (0,
|
|
5702
|
+
const trackRef = (0, import_react38.useRef)(null);
|
|
5703
|
+
const trackWidth = (0, import_react38.useRef)(0);
|
|
5704
|
+
const lastTickValue = (0, import_react38.useRef)(value);
|
|
5428
5705
|
const clamp = (v) => {
|
|
5429
5706
|
const stepped = Math.round(v / step) * step;
|
|
5430
5707
|
return Math.max(min, Math.min(max, parseFloat(stepped.toFixed(4))));
|
|
@@ -5437,7 +5714,7 @@ function SolSlider({
|
|
|
5437
5714
|
const ratio2 = Math.max(0, Math.min(1, x / trackWidth.current));
|
|
5438
5715
|
return clamp(min + ratio2 * (max - min));
|
|
5439
5716
|
};
|
|
5440
|
-
const panResponder = (0,
|
|
5717
|
+
const panResponder = (0, import_react38.useRef)(
|
|
5441
5718
|
import_react_native19.PanResponder.create({
|
|
5442
5719
|
onStartShouldSetPanResponder: () => !disabled,
|
|
5443
5720
|
onMoveShouldSetPanResponder: () => !disabled,
|
|
@@ -5592,7 +5869,7 @@ var styles13 = import_react_native19.StyleSheet.create({
|
|
|
5592
5869
|
});
|
|
5593
5870
|
|
|
5594
5871
|
// src/ui/game/TeamButton.tsx
|
|
5595
|
-
var
|
|
5872
|
+
var import_react39 = require("react");
|
|
5596
5873
|
var import_react_native20 = require("react-native");
|
|
5597
5874
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
5598
5875
|
function TeamButton({
|
|
@@ -5606,7 +5883,7 @@ function TeamButton({
|
|
|
5606
5883
|
ImageComponent,
|
|
5607
5884
|
t
|
|
5608
5885
|
}) {
|
|
5609
|
-
const [imgFailed, setImgFailed] = (0,
|
|
5886
|
+
const [imgFailed, setImgFailed] = (0, import_react39.useState)(false);
|
|
5610
5887
|
const Img = ImageComponent || require("react-native").Image;
|
|
5611
5888
|
const showImage = imageUrl && !imgFailed;
|
|
5612
5889
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
@@ -5710,20 +5987,20 @@ function JoinGameSheet({
|
|
|
5710
5987
|
const { wallet } = useDubs();
|
|
5711
5988
|
const mutation = useJoinGame();
|
|
5712
5989
|
const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
|
|
5713
|
-
const [selectedTeam, setSelectedTeam] = (0,
|
|
5714
|
-
const [wager, setWager] = (0,
|
|
5715
|
-
const [showSuccess, setShowSuccess] = (0,
|
|
5716
|
-
const overlayOpacity = (0,
|
|
5717
|
-
const successScale = (0,
|
|
5718
|
-
const successOpacity = (0,
|
|
5719
|
-
(0,
|
|
5990
|
+
const [selectedTeam, setSelectedTeam] = (0, import_react40.useState)(null);
|
|
5991
|
+
const [wager, setWager] = (0, import_react40.useState)(game.buyIn);
|
|
5992
|
+
const [showSuccess, setShowSuccess] = (0, import_react40.useState)(false);
|
|
5993
|
+
const overlayOpacity = (0, import_react40.useRef)(new import_react_native21.Animated.Value(0)).current;
|
|
5994
|
+
const successScale = (0, import_react40.useRef)(new import_react_native21.Animated.Value(0)).current;
|
|
5995
|
+
const successOpacity = (0, import_react40.useRef)(new import_react_native21.Animated.Value(0)).current;
|
|
5996
|
+
(0, import_react40.useEffect)(() => {
|
|
5720
5997
|
import_react_native21.Animated.timing(overlayOpacity, {
|
|
5721
5998
|
toValue: visible ? 1 : 0,
|
|
5722
5999
|
duration: 250,
|
|
5723
6000
|
useNativeDriver: true
|
|
5724
6001
|
}).start();
|
|
5725
6002
|
}, [visible, overlayOpacity]);
|
|
5726
|
-
(0,
|
|
6003
|
+
(0, import_react40.useEffect)(() => {
|
|
5727
6004
|
if (visible) {
|
|
5728
6005
|
setSelectedTeam(isPoolModeEnabled ? "home" : isCustomGame ? "away" : null);
|
|
5729
6006
|
setWager(game.buyIn);
|
|
@@ -5733,7 +6010,7 @@ function JoinGameSheet({
|
|
|
5733
6010
|
mutation.reset();
|
|
5734
6011
|
}
|
|
5735
6012
|
}, [visible]);
|
|
5736
|
-
(0,
|
|
6013
|
+
(0, import_react40.useEffect)(() => {
|
|
5737
6014
|
if (mutation.status === "success" && mutation.data) {
|
|
5738
6015
|
setShowSuccess(true);
|
|
5739
6016
|
onSuccess?.(mutation.data);
|
|
@@ -5750,7 +6027,7 @@ function JoinGameSheet({
|
|
|
5750
6027
|
return () => clearTimeout(timer);
|
|
5751
6028
|
}
|
|
5752
6029
|
}, [mutation.status, mutation.data]);
|
|
5753
|
-
(0,
|
|
6030
|
+
(0, import_react40.useEffect)(() => {
|
|
5754
6031
|
if (mutation.status === "error" && mutation.error) {
|
|
5755
6032
|
onError?.(mutation.error);
|
|
5756
6033
|
}
|
|
@@ -5765,7 +6042,7 @@ function JoinGameSheet({
|
|
|
5765
6042
|
const drawBettors = bettors.filter((b) => b.team === "draw");
|
|
5766
6043
|
const hasDrawOption = drawPool > 0 || drawBettors.length > 0 || game.league && ["English Premier League", "EPL", "MLS", "La Liga", "Serie A", "Bundesliga", "Ligue 1"].some((l) => (game.league || "").includes(l));
|
|
5767
6044
|
const poolAfterJoin = totalPool + wager;
|
|
5768
|
-
const { homeOdds, awayOdds, drawOdds, homeBets, awayBets, drawBets } = (0,
|
|
6045
|
+
const { homeOdds, awayOdds, drawOdds, homeBets, awayBets, drawBets } = (0, import_react40.useMemo)(() => {
|
|
5769
6046
|
const homeBetsCount = bettors.filter((b) => b.team === "home").length;
|
|
5770
6047
|
const awayBetsCount = bettors.filter((b) => b.team === "away").length;
|
|
5771
6048
|
const drawBetsCount = bettors.filter((b) => b.team === "draw").length;
|
|
@@ -5786,7 +6063,7 @@ function JoinGameSheet({
|
|
|
5786
6063
|
const potentialWinnings = selectedOdds !== "\u2014" ? formatSol(parseFloat(selectedOdds) * wager) : "\u2014";
|
|
5787
6064
|
const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
|
|
5788
6065
|
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
5789
|
-
const myBet = (0,
|
|
6066
|
+
const myBet = (0, import_react40.useMemo)(() => {
|
|
5790
6067
|
if (!wallet.publicKey) return null;
|
|
5791
6068
|
const addr = wallet.publicKey.toBase58();
|
|
5792
6069
|
return bettors.find((b) => b.wallet === addr) ?? null;
|
|
@@ -5794,7 +6071,7 @@ function JoinGameSheet({
|
|
|
5794
6071
|
const alreadyJoined = myBet !== null;
|
|
5795
6072
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
5796
6073
|
const canJoin = selectedTeam !== null && !isMutating && mutation.status !== "success" && !alreadyJoined;
|
|
5797
|
-
const handleJoin = (0,
|
|
6074
|
+
const handleJoin = (0, import_react40.useCallback)(async () => {
|
|
5798
6075
|
if (!selectedTeam || !wallet.publicKey) return;
|
|
5799
6076
|
try {
|
|
5800
6077
|
await mutation.execute({
|
|
@@ -5854,13 +6131,15 @@ function JoinGameSheet({
|
|
|
5854
6131
|
] }) })
|
|
5855
6132
|
] })
|
|
5856
6133
|
] }),
|
|
5857
|
-
!isCustomGame && !isPoolModeEnabled && !alreadyJoined &&
|
|
5858
|
-
/*
|
|
5859
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.
|
|
6134
|
+
!isCustomGame && !isPoolModeEnabled && !alreadyJoined && (hasDrawOption ? (
|
|
6135
|
+
/* ── 3-way layout: Home / VS / Away / OR / Draw ── */
|
|
6136
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.section, children: [
|
|
6137
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.sectionLabel, { color: t.textSecondary }], children: "Who will win?" }),
|
|
5860
6138
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5861
|
-
|
|
6139
|
+
PickRow,
|
|
5862
6140
|
{
|
|
5863
6141
|
name: homeName,
|
|
6142
|
+
subtitle: "Home Team",
|
|
5864
6143
|
imageUrl: opponents[0]?.imageUrl,
|
|
5865
6144
|
odds: homeOdds,
|
|
5866
6145
|
bets: homeBets,
|
|
@@ -5874,10 +6153,16 @@ function JoinGameSheet({
|
|
|
5874
6153
|
t
|
|
5875
6154
|
}
|
|
5876
6155
|
),
|
|
6156
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.dividerRow, children: [
|
|
6157
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [styles15.dividerLine, { backgroundColor: t.border }] }),
|
|
6158
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.dividerText, { color: t.textMuted }], children: "VS" }),
|
|
6159
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [styles15.dividerLine, { backgroundColor: t.border }] })
|
|
6160
|
+
] }),
|
|
5877
6161
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5878
|
-
|
|
6162
|
+
PickRow,
|
|
5879
6163
|
{
|
|
5880
6164
|
name: awayName,
|
|
6165
|
+
subtitle: "Away Team",
|
|
5881
6166
|
imageUrl: opponents[1]?.imageUrl,
|
|
5882
6167
|
odds: awayOdds,
|
|
5883
6168
|
bets: awayBets,
|
|
@@ -5890,24 +6175,71 @@ function JoinGameSheet({
|
|
|
5890
6175
|
ImageComponent,
|
|
5891
6176
|
t
|
|
5892
6177
|
}
|
|
6178
|
+
),
|
|
6179
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.dividerRow, children: [
|
|
6180
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [styles15.dividerLine, { backgroundColor: t.border }] }),
|
|
6181
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.dividerText, { color: t.textMuted }], children: "OR" }),
|
|
6182
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [styles15.dividerLine, { backgroundColor: t.border }] })
|
|
6183
|
+
] }),
|
|
6184
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
6185
|
+
PickRow,
|
|
6186
|
+
{
|
|
6187
|
+
name: "Draw",
|
|
6188
|
+
subtitle: "Match ends in a tie",
|
|
6189
|
+
odds: drawOdds,
|
|
6190
|
+
bets: drawBets,
|
|
6191
|
+
color: drawColor,
|
|
6192
|
+
selected: selectedTeam === "draw",
|
|
6193
|
+
onPress: () => {
|
|
6194
|
+
setSelectedTeam("draw");
|
|
6195
|
+
onTeamSelect?.("draw");
|
|
6196
|
+
},
|
|
6197
|
+
t
|
|
6198
|
+
}
|
|
5893
6199
|
)
|
|
5894
|
-
] })
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
6200
|
+
] })
|
|
6201
|
+
) : (
|
|
6202
|
+
/* ── 2-way layout: side by side ── */
|
|
6203
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.section, children: [
|
|
6204
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
|
|
6205
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: styles15.teamsRow, children: [
|
|
6206
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
6207
|
+
TeamButton,
|
|
6208
|
+
{
|
|
6209
|
+
name: homeName,
|
|
6210
|
+
imageUrl: opponents[0]?.imageUrl,
|
|
6211
|
+
odds: homeOdds,
|
|
6212
|
+
bets: homeBets,
|
|
6213
|
+
color: homeColor,
|
|
6214
|
+
selected: selectedTeam === "home",
|
|
6215
|
+
onPress: () => {
|
|
6216
|
+
setSelectedTeam("home");
|
|
6217
|
+
onTeamSelect?.("home");
|
|
6218
|
+
},
|
|
6219
|
+
ImageComponent,
|
|
6220
|
+
t
|
|
6221
|
+
}
|
|
6222
|
+
),
|
|
6223
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
6224
|
+
TeamButton,
|
|
6225
|
+
{
|
|
6226
|
+
name: awayName,
|
|
6227
|
+
imageUrl: opponents[1]?.imageUrl,
|
|
6228
|
+
odds: awayOdds,
|
|
6229
|
+
bets: awayBets,
|
|
6230
|
+
color: awayColor,
|
|
6231
|
+
selected: selectedTeam === "away",
|
|
6232
|
+
onPress: () => {
|
|
6233
|
+
setSelectedTeam("away");
|
|
6234
|
+
onTeamSelect?.("away");
|
|
6235
|
+
},
|
|
6236
|
+
ImageComponent,
|
|
6237
|
+
t
|
|
6238
|
+
}
|
|
6239
|
+
)
|
|
6240
|
+
] })
|
|
6241
|
+
] })
|
|
6242
|
+
)),
|
|
5911
6243
|
alreadyJoined && myBet && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: [styles15.myBetCard, { backgroundColor: (myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor) + "15", borderColor: myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor }], children: [
|
|
5912
6244
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.myBetLabel, { color: myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor }], children: "YOUR BET" }),
|
|
5913
6245
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [styles15.myBetTeam, { color: t.text }], children: myBet.team === "home" ? homeName : myBet.team === "away" ? awayName : "Draw" }),
|
|
@@ -5990,6 +6322,100 @@ function JoinGameSheet({
|
|
|
5990
6322
|
}
|
|
5991
6323
|
);
|
|
5992
6324
|
}
|
|
6325
|
+
function PickRow({
|
|
6326
|
+
name,
|
|
6327
|
+
subtitle,
|
|
6328
|
+
imageUrl,
|
|
6329
|
+
odds,
|
|
6330
|
+
bets,
|
|
6331
|
+
color,
|
|
6332
|
+
selected,
|
|
6333
|
+
onPress,
|
|
6334
|
+
ImageComponent,
|
|
6335
|
+
t
|
|
6336
|
+
}) {
|
|
6337
|
+
const [imgFailed, setImgFailed] = (0, import_react40.useState)(false);
|
|
6338
|
+
const Img = ImageComponent || require("react-native").Image;
|
|
6339
|
+
const showImage = imageUrl && !imgFailed;
|
|
6340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
6341
|
+
import_react_native21.TouchableOpacity,
|
|
6342
|
+
{
|
|
6343
|
+
style: [pickStyles.row, { borderColor: selected ? color : t.border, backgroundColor: selected ? color + "12" : t.background }],
|
|
6344
|
+
onPress,
|
|
6345
|
+
activeOpacity: 0.7,
|
|
6346
|
+
children: [
|
|
6347
|
+
showImage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Img, { source: { uri: imageUrl }, style: pickStyles.logo, resizeMode: "contain", onError: () => setImgFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [pickStyles.logoPlaceholder, { backgroundColor: color + "20" }], children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [pickStyles.logoEmoji, { color }], children: name === "Draw" ? "\u{1F91D}" : name.charAt(0) }) }),
|
|
6348
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: pickStyles.info, children: [
|
|
6349
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [pickStyles.name, { color: t.text }], children: name }),
|
|
6350
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [pickStyles.subtitle, { color: t.textMuted }], children: subtitle })
|
|
6351
|
+
] }),
|
|
6352
|
+
odds !== "\u2014" && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.Text, { style: [pickStyles.odds, { color }], children: [
|
|
6353
|
+
odds,
|
|
6354
|
+
"x"
|
|
6355
|
+
] }),
|
|
6356
|
+
bets > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: [pickStyles.bets, { color: t.textMuted }], children: bets }),
|
|
6357
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: [pickStyles.check, { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.Text, { style: pickStyles.checkText, children: "\u2713" }) })
|
|
6358
|
+
]
|
|
6359
|
+
}
|
|
6360
|
+
);
|
|
6361
|
+
}
|
|
6362
|
+
var pickStyles = import_react_native21.StyleSheet.create({
|
|
6363
|
+
row: {
|
|
6364
|
+
flexDirection: "row",
|
|
6365
|
+
alignItems: "center",
|
|
6366
|
+
borderWidth: 1.5,
|
|
6367
|
+
borderRadius: 14,
|
|
6368
|
+
paddingVertical: 12,
|
|
6369
|
+
paddingHorizontal: 14,
|
|
6370
|
+
gap: 12
|
|
6371
|
+
},
|
|
6372
|
+
logo: {
|
|
6373
|
+
width: 36,
|
|
6374
|
+
height: 36,
|
|
6375
|
+
borderRadius: 18
|
|
6376
|
+
},
|
|
6377
|
+
logoPlaceholder: {
|
|
6378
|
+
width: 36,
|
|
6379
|
+
height: 36,
|
|
6380
|
+
borderRadius: 18,
|
|
6381
|
+
alignItems: "center",
|
|
6382
|
+
justifyContent: "center"
|
|
6383
|
+
},
|
|
6384
|
+
logoEmoji: {
|
|
6385
|
+
fontSize: 16,
|
|
6386
|
+
fontWeight: "800"
|
|
6387
|
+
},
|
|
6388
|
+
info: {
|
|
6389
|
+
flex: 1
|
|
6390
|
+
},
|
|
6391
|
+
name: {
|
|
6392
|
+
fontSize: 15,
|
|
6393
|
+
fontWeight: "700"
|
|
6394
|
+
},
|
|
6395
|
+
subtitle: {
|
|
6396
|
+
fontSize: 12,
|
|
6397
|
+
marginTop: 1
|
|
6398
|
+
},
|
|
6399
|
+
odds: {
|
|
6400
|
+
fontSize: 16,
|
|
6401
|
+
fontWeight: "800"
|
|
6402
|
+
},
|
|
6403
|
+
bets: {
|
|
6404
|
+
fontSize: 12
|
|
6405
|
+
},
|
|
6406
|
+
check: {
|
|
6407
|
+
width: 22,
|
|
6408
|
+
height: 22,
|
|
6409
|
+
borderRadius: 11,
|
|
6410
|
+
alignItems: "center",
|
|
6411
|
+
justifyContent: "center"
|
|
6412
|
+
},
|
|
6413
|
+
checkText: {
|
|
6414
|
+
color: "#FFF",
|
|
6415
|
+
fontSize: 13,
|
|
6416
|
+
fontWeight: "800"
|
|
6417
|
+
}
|
|
6418
|
+
});
|
|
5993
6419
|
var styles15 = import_react_native21.StyleSheet.create({
|
|
5994
6420
|
overlay: {
|
|
5995
6421
|
...import_react_native21.StyleSheet.absoluteFillObject,
|
|
@@ -6112,8 +6538,22 @@ var styles15 = import_react_native21.StyleSheet.create({
|
|
|
6112
6538
|
drawRow: {
|
|
6113
6539
|
marginTop: 8
|
|
6114
6540
|
},
|
|
6115
|
-
|
|
6116
|
-
|
|
6541
|
+
dividerRow: {
|
|
6542
|
+
flexDirection: "row",
|
|
6543
|
+
alignItems: "center",
|
|
6544
|
+
gap: 12,
|
|
6545
|
+
marginVertical: 6
|
|
6546
|
+
},
|
|
6547
|
+
dividerLine: {
|
|
6548
|
+
flex: 1,
|
|
6549
|
+
height: 1
|
|
6550
|
+
},
|
|
6551
|
+
dividerText: {
|
|
6552
|
+
fontSize: 12,
|
|
6553
|
+
fontWeight: "700"
|
|
6554
|
+
},
|
|
6555
|
+
summaryCard: {
|
|
6556
|
+
marginTop: 20,
|
|
6117
6557
|
borderRadius: 16,
|
|
6118
6558
|
borderWidth: 1,
|
|
6119
6559
|
overflow: "hidden"
|
|
@@ -6187,7 +6627,7 @@ var styles15 = import_react_native21.StyleSheet.create({
|
|
|
6187
6627
|
});
|
|
6188
6628
|
|
|
6189
6629
|
// src/ui/game/ClaimPrizeSheet.tsx
|
|
6190
|
-
var
|
|
6630
|
+
var import_react41 = require("react");
|
|
6191
6631
|
var import_react_native22 = require("react-native");
|
|
6192
6632
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
6193
6633
|
var STATUS_LABELS4 = {
|
|
@@ -6208,18 +6648,18 @@ function ClaimPrizeSheet({
|
|
|
6208
6648
|
const t = useDubsTheme();
|
|
6209
6649
|
const { wallet } = useDubs();
|
|
6210
6650
|
const mutation = useClaim();
|
|
6211
|
-
const overlayOpacity = (0,
|
|
6212
|
-
const celebrationScale = (0,
|
|
6213
|
-
const celebrationOpacity = (0,
|
|
6214
|
-
const [showCelebration, setShowCelebration] = (0,
|
|
6215
|
-
(0,
|
|
6651
|
+
const overlayOpacity = (0, import_react41.useRef)(new import_react_native22.Animated.Value(0)).current;
|
|
6652
|
+
const celebrationScale = (0, import_react41.useRef)(new import_react_native22.Animated.Value(0)).current;
|
|
6653
|
+
const celebrationOpacity = (0, import_react41.useRef)(new import_react_native22.Animated.Value(0)).current;
|
|
6654
|
+
const [showCelebration, setShowCelebration] = (0, import_react41.useState)(false);
|
|
6655
|
+
(0, import_react41.useEffect)(() => {
|
|
6216
6656
|
import_react_native22.Animated.timing(overlayOpacity, {
|
|
6217
6657
|
toValue: visible ? 1 : 0,
|
|
6218
6658
|
duration: 250,
|
|
6219
6659
|
useNativeDriver: true
|
|
6220
6660
|
}).start();
|
|
6221
6661
|
}, [visible, overlayOpacity]);
|
|
6222
|
-
(0,
|
|
6662
|
+
(0, import_react41.useEffect)(() => {
|
|
6223
6663
|
if (visible) {
|
|
6224
6664
|
mutation.reset();
|
|
6225
6665
|
setShowCelebration(false);
|
|
@@ -6227,7 +6667,7 @@ function ClaimPrizeSheet({
|
|
|
6227
6667
|
celebrationOpacity.setValue(0);
|
|
6228
6668
|
}
|
|
6229
6669
|
}, [visible]);
|
|
6230
|
-
(0,
|
|
6670
|
+
(0, import_react41.useEffect)(() => {
|
|
6231
6671
|
if (mutation.status === "success" && mutation.data) {
|
|
6232
6672
|
setShowCelebration(true);
|
|
6233
6673
|
import_react_native22.Animated.parallel([
|
|
@@ -6250,14 +6690,14 @@ function ClaimPrizeSheet({
|
|
|
6250
6690
|
return () => clearTimeout(timer);
|
|
6251
6691
|
}
|
|
6252
6692
|
}, [mutation.status, mutation.data]);
|
|
6253
|
-
(0,
|
|
6693
|
+
(0, import_react41.useEffect)(() => {
|
|
6254
6694
|
if (mutation.status === "error" && mutation.error) {
|
|
6255
6695
|
onError?.(mutation.error);
|
|
6256
6696
|
}
|
|
6257
6697
|
}, [mutation.status, mutation.error]);
|
|
6258
6698
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
6259
6699
|
const canClaim = !isMutating && mutation.status !== "success" && !!wallet.publicKey;
|
|
6260
|
-
const handleClaim = (0,
|
|
6700
|
+
const handleClaim = (0, import_react41.useCallback)(async () => {
|
|
6261
6701
|
if (!wallet.publicKey) return;
|
|
6262
6702
|
try {
|
|
6263
6703
|
await mutation.execute({
|
|
@@ -6490,7 +6930,7 @@ var styles16 = import_react_native22.StyleSheet.create({
|
|
|
6490
6930
|
});
|
|
6491
6931
|
|
|
6492
6932
|
// src/ui/game/ClaimButton.tsx
|
|
6493
|
-
var
|
|
6933
|
+
var import_react42 = require("react");
|
|
6494
6934
|
var import_react_native23 = require("react-native");
|
|
6495
6935
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
6496
6936
|
function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
@@ -6498,9 +6938,9 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
6498
6938
|
const { wallet } = useDubs();
|
|
6499
6939
|
const game = useGame(gameId);
|
|
6500
6940
|
const claimStatus = useHasClaimed(gameId);
|
|
6501
|
-
const [sheetVisible, setSheetVisible] = (0,
|
|
6941
|
+
const [sheetVisible, setSheetVisible] = (0, import_react42.useState)(false);
|
|
6502
6942
|
const walletAddress = wallet.publicKey?.toBase58() ?? null;
|
|
6503
|
-
const myBet = (0,
|
|
6943
|
+
const myBet = (0, import_react42.useMemo)(() => {
|
|
6504
6944
|
if (!walletAddress || !game.data?.bettors) return null;
|
|
6505
6945
|
return game.data.bettors.find((b) => b.wallet === walletAddress) ?? null;
|
|
6506
6946
|
}, [walletAddress, game.data?.bettors]);
|
|
@@ -6509,7 +6949,7 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
6509
6949
|
const isWinner = isResolved && myBet != null && myBet.team === game.data?.winnerSide;
|
|
6510
6950
|
const isEligible = myBet != null && isResolved && (isWinner || isRefund);
|
|
6511
6951
|
const prizeAmount = isRefund ? myBet?.amount ?? 0 : game.data?.totalPool ?? 0;
|
|
6512
|
-
const handleSuccess = (0,
|
|
6952
|
+
const handleSuccess = (0, import_react42.useCallback)(
|
|
6513
6953
|
(result) => {
|
|
6514
6954
|
claimStatus.refetch();
|
|
6515
6955
|
onSuccess?.(result);
|
|
@@ -6596,7 +7036,7 @@ var styles17 = import_react_native23.StyleSheet.create({
|
|
|
6596
7036
|
});
|
|
6597
7037
|
|
|
6598
7038
|
// src/ui/game/EnterArcadePoolSheet.tsx
|
|
6599
|
-
var
|
|
7039
|
+
var import_react43 = require("react");
|
|
6600
7040
|
var import_react_native24 = require("react-native");
|
|
6601
7041
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6602
7042
|
var STATUS_LABELS5 = {
|
|
@@ -6617,20 +7057,20 @@ function EnterArcadePoolSheet({
|
|
|
6617
7057
|
const t = useDubsTheme();
|
|
6618
7058
|
const { wallet } = useDubs();
|
|
6619
7059
|
const mutation = useEnterArcadePool();
|
|
6620
|
-
const overlayOpacity = (0,
|
|
6621
|
-
(0,
|
|
7060
|
+
const overlayOpacity = (0, import_react43.useRef)(new import_react_native24.Animated.Value(0)).current;
|
|
7061
|
+
(0, import_react43.useEffect)(() => {
|
|
6622
7062
|
import_react_native24.Animated.timing(overlayOpacity, {
|
|
6623
7063
|
toValue: visible ? 1 : 0,
|
|
6624
7064
|
duration: 250,
|
|
6625
7065
|
useNativeDriver: true
|
|
6626
7066
|
}).start();
|
|
6627
7067
|
}, [visible, overlayOpacity]);
|
|
6628
|
-
(0,
|
|
7068
|
+
(0, import_react43.useEffect)(() => {
|
|
6629
7069
|
if (visible) {
|
|
6630
7070
|
mutation.reset();
|
|
6631
7071
|
}
|
|
6632
7072
|
}, [visible]);
|
|
6633
|
-
(0,
|
|
7073
|
+
(0, import_react43.useEffect)(() => {
|
|
6634
7074
|
if (mutation.status === "success" && mutation.data) {
|
|
6635
7075
|
onSuccess?.(mutation.data);
|
|
6636
7076
|
const timer = setTimeout(() => {
|
|
@@ -6639,7 +7079,7 @@ function EnterArcadePoolSheet({
|
|
|
6639
7079
|
return () => clearTimeout(timer);
|
|
6640
7080
|
}
|
|
6641
7081
|
}, [mutation.status, mutation.data]);
|
|
6642
|
-
(0,
|
|
7082
|
+
(0, import_react43.useEffect)(() => {
|
|
6643
7083
|
if (mutation.status === "error" && mutation.error) {
|
|
6644
7084
|
onError?.(mutation.error);
|
|
6645
7085
|
}
|
|
@@ -6651,7 +7091,7 @@ function EnterArcadePoolSheet({
|
|
|
6651
7091
|
const potSol = (pool.buy_in_lamports * Number(totalBuyIns) / 1e9).toFixed(4);
|
|
6652
7092
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
6653
7093
|
const canJoin = !isMutating && mutation.status !== "success";
|
|
6654
|
-
const handleJoin = (0,
|
|
7094
|
+
const handleJoin = (0, import_react43.useCallback)(async () => {
|
|
6655
7095
|
if (!wallet.publicKey) return;
|
|
6656
7096
|
try {
|
|
6657
7097
|
await mutation.execute(pool.id);
|
|
@@ -6802,7 +7242,7 @@ var styles18 = import_react_native24.StyleSheet.create({
|
|
|
6802
7242
|
});
|
|
6803
7243
|
|
|
6804
7244
|
// src/ui/game/ArcadeLeaderboardSheet.tsx
|
|
6805
|
-
var
|
|
7245
|
+
var import_react44 = require("react");
|
|
6806
7246
|
var import_react_native25 = require("react-native");
|
|
6807
7247
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
6808
7248
|
function RankLabel({ index }) {
|
|
@@ -6819,15 +7259,15 @@ function ArcadeLeaderboardSheet({
|
|
|
6819
7259
|
}) {
|
|
6820
7260
|
const t = useDubsTheme();
|
|
6821
7261
|
const { pool, leaderboard, stats, loading, refetch } = useArcadePool(poolId);
|
|
6822
|
-
const overlayOpacity = (0,
|
|
6823
|
-
(0,
|
|
7262
|
+
const overlayOpacity = (0, import_react44.useRef)(new import_react_native25.Animated.Value(0)).current;
|
|
7263
|
+
(0, import_react44.useEffect)(() => {
|
|
6824
7264
|
import_react_native25.Animated.timing(overlayOpacity, {
|
|
6825
7265
|
toValue: visible ? 1 : 0,
|
|
6826
7266
|
duration: 250,
|
|
6827
7267
|
useNativeDriver: true
|
|
6828
7268
|
}).start();
|
|
6829
7269
|
}, [visible, overlayOpacity]);
|
|
6830
|
-
(0,
|
|
7270
|
+
(0, import_react44.useEffect)(() => {
|
|
6831
7271
|
if (visible) refetch();
|
|
6832
7272
|
}, [visible]);
|
|
6833
7273
|
const renderItem = ({ item, index }) => {
|
|
@@ -6974,7 +7414,7 @@ var styles19 = import_react_native25.StyleSheet.create({
|
|
|
6974
7414
|
});
|
|
6975
7415
|
|
|
6976
7416
|
// src/ui/game/CreateGameSheet.tsx
|
|
6977
|
-
var
|
|
7417
|
+
var import_react45 = require("react");
|
|
6978
7418
|
var import_react_native26 = require("react-native");
|
|
6979
7419
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
6980
7420
|
var STATUS_LABELS6 = {
|
|
@@ -7003,20 +7443,20 @@ function CreateGameSheet({
|
|
|
7003
7443
|
const t = useDubsTheme();
|
|
7004
7444
|
const { wallet } = useDubs();
|
|
7005
7445
|
const mutation = useCreateGame();
|
|
7006
|
-
const [selectedTeam, setSelectedTeam] = (0,
|
|
7007
|
-
const [wager, setWager] = (0,
|
|
7008
|
-
const [showSuccess, setShowSuccess] = (0,
|
|
7009
|
-
const overlayOpacity = (0,
|
|
7010
|
-
const successScale = (0,
|
|
7011
|
-
const successOpacity = (0,
|
|
7012
|
-
(0,
|
|
7446
|
+
const [selectedTeam, setSelectedTeam] = (0, import_react45.useState)(null);
|
|
7447
|
+
const [wager, setWager] = (0, import_react45.useState)(0.01);
|
|
7448
|
+
const [showSuccess, setShowSuccess] = (0, import_react45.useState)(false);
|
|
7449
|
+
const overlayOpacity = (0, import_react45.useRef)(new import_react_native26.Animated.Value(0)).current;
|
|
7450
|
+
const successScale = (0, import_react45.useRef)(new import_react_native26.Animated.Value(0)).current;
|
|
7451
|
+
const successOpacity = (0, import_react45.useRef)(new import_react_native26.Animated.Value(0)).current;
|
|
7452
|
+
(0, import_react45.useEffect)(() => {
|
|
7013
7453
|
import_react_native26.Animated.timing(overlayOpacity, {
|
|
7014
7454
|
toValue: visible ? 1 : 0,
|
|
7015
7455
|
duration: 250,
|
|
7016
7456
|
useNativeDriver: true
|
|
7017
7457
|
}).start();
|
|
7018
7458
|
}, [visible]);
|
|
7019
|
-
(0,
|
|
7459
|
+
(0, import_react45.useEffect)(() => {
|
|
7020
7460
|
if (visible) {
|
|
7021
7461
|
setSelectedTeam(null);
|
|
7022
7462
|
setWager(0.01);
|
|
@@ -7026,7 +7466,7 @@ function CreateGameSheet({
|
|
|
7026
7466
|
mutation.reset();
|
|
7027
7467
|
}
|
|
7028
7468
|
}, [visible]);
|
|
7029
|
-
(0,
|
|
7469
|
+
(0, import_react45.useEffect)(() => {
|
|
7030
7470
|
if (mutation.status === "success" && mutation.data) {
|
|
7031
7471
|
setShowSuccess(true);
|
|
7032
7472
|
onSuccess?.(mutation.data);
|
|
@@ -7043,7 +7483,7 @@ function CreateGameSheet({
|
|
|
7043
7483
|
return () => clearTimeout(timer);
|
|
7044
7484
|
}
|
|
7045
7485
|
}, [mutation.status, mutation.data]);
|
|
7046
|
-
(0,
|
|
7486
|
+
(0, import_react45.useEffect)(() => {
|
|
7047
7487
|
if (mutation.status === "error" && mutation.error) {
|
|
7048
7488
|
onError?.(mutation.error);
|
|
7049
7489
|
}
|
|
@@ -7053,7 +7493,7 @@ function CreateGameSheet({
|
|
|
7053
7493
|
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
7054
7494
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
7055
7495
|
const canCreate = selectedTeam !== null && !isMutating && mutation.status !== "success";
|
|
7056
|
-
const handleCreate = (0,
|
|
7496
|
+
const handleCreate = (0, import_react45.useCallback)(async () => {
|
|
7057
7497
|
if (!selectedTeam || !wallet.publicKey) return;
|
|
7058
7498
|
try {
|
|
7059
7499
|
await mutation.execute({
|
|
@@ -7199,10 +7639,1483 @@ var styles20 = import_react_native26.StyleSheet.create({
|
|
|
7199
7639
|
successTitle: { color: "#FFFFFF", fontSize: 28, fontWeight: "900" },
|
|
7200
7640
|
successSub: { color: "#8E8E93", fontSize: 16 }
|
|
7201
7641
|
});
|
|
7642
|
+
|
|
7643
|
+
// src/ui/jackpot/JackpotCard.tsx
|
|
7644
|
+
var import_react46 = require("react");
|
|
7645
|
+
var import_react_native27 = require("react-native");
|
|
7646
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
7647
|
+
function formatSOL(lamports) {
|
|
7648
|
+
const val = typeof lamports === "string" ? parseInt(lamports, 10) : lamports;
|
|
7649
|
+
if (isNaN(val) || val === 0) return "0";
|
|
7650
|
+
const sol = val / 1e9;
|
|
7651
|
+
if (sol >= 100) return sol.toFixed(0);
|
|
7652
|
+
if (sol >= 1) return sol.toFixed(2);
|
|
7653
|
+
if (sol >= 0.01) return sol.toFixed(3);
|
|
7654
|
+
return sol.toFixed(4);
|
|
7655
|
+
}
|
|
7656
|
+
function truncateWallet2(addr) {
|
|
7657
|
+
if (!addr || addr.length < 8) return addr || "";
|
|
7658
|
+
return `${addr.slice(0, 4)}...${addr.slice(-4)}`;
|
|
7659
|
+
}
|
|
7660
|
+
function JackpotCard({ round, lastWinner, entries, onPress, style }) {
|
|
7661
|
+
const shimmerAnim = (0, import_react46.useRef)(new import_react_native27.Animated.Value(-1)).current;
|
|
7662
|
+
const pulseAnim = (0, import_react46.useRef)(new import_react_native27.Animated.Value(0.4)).current;
|
|
7663
|
+
(0, import_react46.useEffect)(() => {
|
|
7664
|
+
const shimmer = import_react_native27.Animated.loop(
|
|
7665
|
+
import_react_native27.Animated.sequence([
|
|
7666
|
+
import_react_native27.Animated.timing(shimmerAnim, { toValue: 1, duration: 4e3, useNativeDriver: true }),
|
|
7667
|
+
import_react_native27.Animated.delay(500),
|
|
7668
|
+
import_react_native27.Animated.timing(shimmerAnim, { toValue: -1, duration: 0, useNativeDriver: true })
|
|
7669
|
+
])
|
|
7670
|
+
);
|
|
7671
|
+
shimmer.start();
|
|
7672
|
+
const pulse = import_react_native27.Animated.loop(
|
|
7673
|
+
import_react_native27.Animated.sequence([
|
|
7674
|
+
import_react_native27.Animated.timing(pulseAnim, { toValue: 1, duration: 1e3, useNativeDriver: true }),
|
|
7675
|
+
import_react_native27.Animated.timing(pulseAnim, { toValue: 0.4, duration: 1e3, useNativeDriver: true })
|
|
7676
|
+
])
|
|
7677
|
+
);
|
|
7678
|
+
pulse.start();
|
|
7679
|
+
return () => {
|
|
7680
|
+
shimmer.stop();
|
|
7681
|
+
pulse.stop();
|
|
7682
|
+
};
|
|
7683
|
+
}, [shimmerAnim, pulseAnim]);
|
|
7684
|
+
const potSol = round ? formatSOL(round.totalPotLamports) : "0";
|
|
7685
|
+
const isOpen = round?.status === "Open";
|
|
7686
|
+
const entryCount = round?.entryCount ?? 0;
|
|
7687
|
+
const totalWeight = round ? Number(BigInt(round.totalWeight || "0")) : 0;
|
|
7688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
7689
|
+
import_react_native27.TouchableOpacity,
|
|
7690
|
+
{
|
|
7691
|
+
activeOpacity: 0.9,
|
|
7692
|
+
onPress,
|
|
7693
|
+
style: [styles21.card, style],
|
|
7694
|
+
children: [
|
|
7695
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.View, { style: styles21.gradientBg }),
|
|
7696
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7697
|
+
import_react_native27.Animated.View,
|
|
7698
|
+
{
|
|
7699
|
+
style: [
|
|
7700
|
+
styles21.shimmer,
|
|
7701
|
+
{
|
|
7702
|
+
transform: [{
|
|
7703
|
+
translateX: shimmerAnim.interpolate({
|
|
7704
|
+
inputRange: [-1, 1],
|
|
7705
|
+
outputRange: [-400, 400]
|
|
7706
|
+
})
|
|
7707
|
+
}]
|
|
7708
|
+
}
|
|
7709
|
+
]
|
|
7710
|
+
}
|
|
7711
|
+
),
|
|
7712
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.View, { style: styles21.accentBar }),
|
|
7713
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.content, children: [
|
|
7714
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.statusRow, children: [
|
|
7715
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: [styles21.statusBadge, isOpen ? styles21.statusOpen : styles21.statusClosed], children: [
|
|
7716
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Animated.View, { style: [styles21.statusDot, { opacity: pulseAnim }] }),
|
|
7717
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: [styles21.statusText, { color: isOpen ? "#22c55e" : "#9ca3af" }], children: isOpen ? "Open" : round?.status ?? "Loading" })
|
|
7718
|
+
] }),
|
|
7719
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.Text, { style: styles21.entryCountText, children: [
|
|
7720
|
+
entryCount,
|
|
7721
|
+
" player",
|
|
7722
|
+
entryCount !== 1 ? "s" : ""
|
|
7723
|
+
] })
|
|
7724
|
+
] }),
|
|
7725
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.heroSection, children: [
|
|
7726
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.potInfo, children: [
|
|
7727
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.jackpotLabel, children: "JACKPOT" }),
|
|
7728
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.Text, { style: styles21.potValue, children: [
|
|
7729
|
+
potSol,
|
|
7730
|
+
" SOL"
|
|
7731
|
+
] })
|
|
7732
|
+
] }),
|
|
7733
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.potEmoji, children: "\u{1F911}" })
|
|
7734
|
+
] }),
|
|
7735
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.infoGrid, children: [
|
|
7736
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.infoCard, children: [
|
|
7737
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.infoLabel, children: "PLAYERS" }),
|
|
7738
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.infoValue, children: entryCount })
|
|
7739
|
+
] }),
|
|
7740
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.infoCard, children: [
|
|
7741
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.infoLabel, children: "TOTAL POT" }),
|
|
7742
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: [styles21.infoValue, { color: "#4ade80" }], children: potSol })
|
|
7743
|
+
] }),
|
|
7744
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.infoCard, children: [
|
|
7745
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.infoLabel, children: "LAST WIN" }),
|
|
7746
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: [styles21.infoValue, { color: "#22c55e" }], children: lastWinner ? formatSOL(lastWinner.winAmount) : "\u2014" })
|
|
7747
|
+
] })
|
|
7748
|
+
] }),
|
|
7749
|
+
entries && entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.playersSection, children: [
|
|
7750
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.playersSectionHeader, children: [
|
|
7751
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.playersSectionTitle, children: "Players in Round" }),
|
|
7752
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.View, { style: styles21.activeCountBadge, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.activeCountText, children: entries.length }) })
|
|
7753
|
+
] }),
|
|
7754
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.playersCarousel, children: [
|
|
7755
|
+
entries.slice(0, 8).map((entry, i) => {
|
|
7756
|
+
const odds = entry.oddsPercent;
|
|
7757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: styles21.playerCard, children: [
|
|
7758
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.View, { style: styles21.playerAvatar, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.playerAvatarText, children: entry.player.slice(0, 2).toUpperCase() }) }),
|
|
7759
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.playerWallet, numberOfLines: 1, children: truncateWallet2(entry.player) }),
|
|
7760
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.Text, { style: styles21.playerWager, children: [
|
|
7761
|
+
entry.weightSol.toFixed(2),
|
|
7762
|
+
" SOL"
|
|
7763
|
+
] }),
|
|
7764
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.Text, { style: styles21.playerOdds, children: [
|
|
7765
|
+
odds,
|
|
7766
|
+
"%"
|
|
7767
|
+
] })
|
|
7768
|
+
] }, `${entry.player}-${i}`);
|
|
7769
|
+
}),
|
|
7770
|
+
entries.length > 8 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.View, { style: styles21.playerCardMore, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.Text, { style: styles21.playerMoreText, children: [
|
|
7771
|
+
"+",
|
|
7772
|
+
entries.length - 8
|
|
7773
|
+
] }) })
|
|
7774
|
+
] })
|
|
7775
|
+
] }),
|
|
7776
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7777
|
+
import_react_native27.TouchableOpacity,
|
|
7778
|
+
{
|
|
7779
|
+
style: styles21.placeBetButton,
|
|
7780
|
+
activeOpacity: 0.85,
|
|
7781
|
+
onPress,
|
|
7782
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native27.Text, { style: styles21.placeBetText, children: "Place Bet" })
|
|
7783
|
+
}
|
|
7784
|
+
)
|
|
7785
|
+
] })
|
|
7786
|
+
]
|
|
7787
|
+
}
|
|
7788
|
+
);
|
|
7789
|
+
}
|
|
7790
|
+
var styles21 = import_react_native27.StyleSheet.create({
|
|
7791
|
+
card: {
|
|
7792
|
+
borderRadius: 16,
|
|
7793
|
+
borderWidth: 1,
|
|
7794
|
+
borderColor: "rgba(34, 197, 94, 0.2)",
|
|
7795
|
+
backgroundColor: "#0c0c14",
|
|
7796
|
+
overflow: "hidden",
|
|
7797
|
+
position: "relative"
|
|
7798
|
+
},
|
|
7799
|
+
gradientBg: {
|
|
7800
|
+
...import_react_native27.StyleSheet.absoluteFillObject,
|
|
7801
|
+
backgroundColor: "rgba(34, 197, 94, 0.04)"
|
|
7802
|
+
},
|
|
7803
|
+
shimmer: {
|
|
7804
|
+
position: "absolute",
|
|
7805
|
+
top: 0,
|
|
7806
|
+
bottom: 0,
|
|
7807
|
+
width: 120,
|
|
7808
|
+
backgroundColor: "rgba(34, 197, 94, 0.08)"
|
|
7809
|
+
},
|
|
7810
|
+
accentBar: {
|
|
7811
|
+
position: "absolute",
|
|
7812
|
+
bottom: 0,
|
|
7813
|
+
left: 0,
|
|
7814
|
+
right: "40%",
|
|
7815
|
+
height: 2,
|
|
7816
|
+
backgroundColor: "#22c55e"
|
|
7817
|
+
},
|
|
7818
|
+
content: {
|
|
7819
|
+
padding: 16,
|
|
7820
|
+
gap: 12
|
|
7821
|
+
},
|
|
7822
|
+
// Status row
|
|
7823
|
+
statusRow: {
|
|
7824
|
+
flexDirection: "row",
|
|
7825
|
+
alignItems: "center",
|
|
7826
|
+
gap: 8
|
|
7827
|
+
},
|
|
7828
|
+
statusBadge: {
|
|
7829
|
+
flexDirection: "row",
|
|
7830
|
+
alignItems: "center",
|
|
7831
|
+
gap: 6,
|
|
7832
|
+
paddingHorizontal: 10,
|
|
7833
|
+
paddingVertical: 4,
|
|
7834
|
+
borderRadius: 100
|
|
7835
|
+
},
|
|
7836
|
+
statusOpen: {
|
|
7837
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)"
|
|
7838
|
+
},
|
|
7839
|
+
statusClosed: {
|
|
7840
|
+
backgroundColor: "rgba(156, 163, 175, 0.15)"
|
|
7841
|
+
},
|
|
7842
|
+
statusDot: {
|
|
7843
|
+
width: 6,
|
|
7844
|
+
height: 6,
|
|
7845
|
+
borderRadius: 3,
|
|
7846
|
+
backgroundColor: "#22c55e"
|
|
7847
|
+
},
|
|
7848
|
+
statusText: {
|
|
7849
|
+
fontSize: 12,
|
|
7850
|
+
fontWeight: "700"
|
|
7851
|
+
},
|
|
7852
|
+
entryCountText: {
|
|
7853
|
+
fontSize: 12,
|
|
7854
|
+
color: "#6b6b6b",
|
|
7855
|
+
fontWeight: "500"
|
|
7856
|
+
},
|
|
7857
|
+
// Hero pot
|
|
7858
|
+
heroSection: {
|
|
7859
|
+
flexDirection: "row",
|
|
7860
|
+
alignItems: "center",
|
|
7861
|
+
justifyContent: "space-between"
|
|
7862
|
+
},
|
|
7863
|
+
potInfo: {
|
|
7864
|
+
flex: 1
|
|
7865
|
+
},
|
|
7866
|
+
jackpotLabel: {
|
|
7867
|
+
fontSize: 10,
|
|
7868
|
+
fontWeight: "600",
|
|
7869
|
+
color: "#6b6b6b",
|
|
7870
|
+
letterSpacing: 3,
|
|
7871
|
+
textTransform: "uppercase",
|
|
7872
|
+
marginBottom: 4
|
|
7873
|
+
},
|
|
7874
|
+
potValue: {
|
|
7875
|
+
fontSize: 36,
|
|
7876
|
+
fontWeight: "900",
|
|
7877
|
+
color: "#4ade80",
|
|
7878
|
+
letterSpacing: -1
|
|
7879
|
+
},
|
|
7880
|
+
potEmoji: {
|
|
7881
|
+
fontSize: 40,
|
|
7882
|
+
opacity: 0.2
|
|
7883
|
+
},
|
|
7884
|
+
// Info grid
|
|
7885
|
+
infoGrid: {
|
|
7886
|
+
flexDirection: "row",
|
|
7887
|
+
gap: 8
|
|
7888
|
+
},
|
|
7889
|
+
infoCard: {
|
|
7890
|
+
flex: 1,
|
|
7891
|
+
borderRadius: 12,
|
|
7892
|
+
borderWidth: 1,
|
|
7893
|
+
borderColor: "#1e1e2a",
|
|
7894
|
+
backgroundColor: "#0c0c14",
|
|
7895
|
+
padding: 12
|
|
7896
|
+
},
|
|
7897
|
+
infoLabel: {
|
|
7898
|
+
fontSize: 9,
|
|
7899
|
+
fontWeight: "600",
|
|
7900
|
+
color: "#6b6b6b",
|
|
7901
|
+
letterSpacing: 2,
|
|
7902
|
+
textTransform: "uppercase",
|
|
7903
|
+
marginBottom: 4
|
|
7904
|
+
},
|
|
7905
|
+
infoValue: {
|
|
7906
|
+
fontSize: 18,
|
|
7907
|
+
fontWeight: "700",
|
|
7908
|
+
color: "#FFFFFF"
|
|
7909
|
+
},
|
|
7910
|
+
// Players section
|
|
7911
|
+
playersSection: {
|
|
7912
|
+
borderRadius: 12,
|
|
7913
|
+
borderWidth: 1,
|
|
7914
|
+
borderColor: "#1e1e2a",
|
|
7915
|
+
backgroundColor: "rgba(139, 92, 246, 0.04)",
|
|
7916
|
+
padding: 12,
|
|
7917
|
+
overflow: "hidden"
|
|
7918
|
+
},
|
|
7919
|
+
playersSectionHeader: {
|
|
7920
|
+
flexDirection: "row",
|
|
7921
|
+
alignItems: "center",
|
|
7922
|
+
justifyContent: "space-between",
|
|
7923
|
+
marginBottom: 10
|
|
7924
|
+
},
|
|
7925
|
+
playersSectionTitle: {
|
|
7926
|
+
fontSize: 13,
|
|
7927
|
+
fontWeight: "600",
|
|
7928
|
+
color: "#a0a0a0"
|
|
7929
|
+
},
|
|
7930
|
+
activeCountBadge: {
|
|
7931
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)",
|
|
7932
|
+
paddingHorizontal: 8,
|
|
7933
|
+
paddingVertical: 2,
|
|
7934
|
+
borderRadius: 100
|
|
7935
|
+
},
|
|
7936
|
+
activeCountText: {
|
|
7937
|
+
fontSize: 11,
|
|
7938
|
+
fontWeight: "700",
|
|
7939
|
+
color: "#22c55e"
|
|
7940
|
+
},
|
|
7941
|
+
playersCarousel: {
|
|
7942
|
+
flexDirection: "row",
|
|
7943
|
+
gap: 10
|
|
7944
|
+
},
|
|
7945
|
+
playerCard: {
|
|
7946
|
+
width: 96,
|
|
7947
|
+
borderRadius: 12,
|
|
7948
|
+
borderWidth: 1.5,
|
|
7949
|
+
borderColor: "rgba(139, 92, 246, 0.4)",
|
|
7950
|
+
backgroundColor: "rgba(139, 92, 246, 0.08)",
|
|
7951
|
+
padding: 10,
|
|
7952
|
+
alignItems: "center",
|
|
7953
|
+
gap: 4
|
|
7954
|
+
},
|
|
7955
|
+
playerAvatar: {
|
|
7956
|
+
width: 40,
|
|
7957
|
+
height: 40,
|
|
7958
|
+
borderRadius: 20,
|
|
7959
|
+
borderWidth: 1.5,
|
|
7960
|
+
borderColor: "#8b5cf6",
|
|
7961
|
+
backgroundColor: "rgba(139, 92, 246, 0.2)",
|
|
7962
|
+
alignItems: "center",
|
|
7963
|
+
justifyContent: "center"
|
|
7964
|
+
},
|
|
7965
|
+
playerAvatarText: {
|
|
7966
|
+
fontSize: 14,
|
|
7967
|
+
fontWeight: "700",
|
|
7968
|
+
color: "#a78bfa"
|
|
7969
|
+
},
|
|
7970
|
+
playerWallet: {
|
|
7971
|
+
fontSize: 10,
|
|
7972
|
+
fontWeight: "500",
|
|
7973
|
+
color: "#a0a0a0",
|
|
7974
|
+
width: "100%",
|
|
7975
|
+
textAlign: "center"
|
|
7976
|
+
},
|
|
7977
|
+
playerWager: {
|
|
7978
|
+
fontSize: 12,
|
|
7979
|
+
fontWeight: "600",
|
|
7980
|
+
color: "#a78bfa"
|
|
7981
|
+
},
|
|
7982
|
+
playerOdds: {
|
|
7983
|
+
fontSize: 10,
|
|
7984
|
+
fontWeight: "700",
|
|
7985
|
+
color: "#22c55e"
|
|
7986
|
+
},
|
|
7987
|
+
playerCardMore: {
|
|
7988
|
+
width: 96,
|
|
7989
|
+
borderRadius: 12,
|
|
7990
|
+
borderWidth: 1.5,
|
|
7991
|
+
borderColor: "#1e1e2a",
|
|
7992
|
+
backgroundColor: "#14141e",
|
|
7993
|
+
alignItems: "center",
|
|
7994
|
+
justifyContent: "center"
|
|
7995
|
+
},
|
|
7996
|
+
playerMoreText: {
|
|
7997
|
+
fontSize: 16,
|
|
7998
|
+
fontWeight: "700",
|
|
7999
|
+
color: "#6b6b6b"
|
|
8000
|
+
},
|
|
8001
|
+
// Place bet CTA
|
|
8002
|
+
placeBetButton: {
|
|
8003
|
+
height: 52,
|
|
8004
|
+
borderRadius: 12,
|
|
8005
|
+
alignItems: "center",
|
|
8006
|
+
justifyContent: "center",
|
|
8007
|
+
backgroundColor: "#22c55e",
|
|
8008
|
+
shadowColor: "#22c55e",
|
|
8009
|
+
shadowOffset: { width: 0, height: 4 },
|
|
8010
|
+
shadowOpacity: 0.25,
|
|
8011
|
+
shadowRadius: 12,
|
|
8012
|
+
elevation: 6
|
|
8013
|
+
},
|
|
8014
|
+
placeBetText: {
|
|
8015
|
+
color: "#FFFFFF",
|
|
8016
|
+
fontSize: 16,
|
|
8017
|
+
fontWeight: "700"
|
|
8018
|
+
}
|
|
8019
|
+
});
|
|
8020
|
+
|
|
8021
|
+
// src/ui/jackpot/JackpotSheet.tsx
|
|
8022
|
+
var import_react47 = require("react");
|
|
8023
|
+
var import_react_native28 = require("react-native");
|
|
8024
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
8025
|
+
var STATUS_LABELS7 = {
|
|
8026
|
+
building: "Building transaction...",
|
|
8027
|
+
signing: "Approve in wallet...",
|
|
8028
|
+
confirming: "Confirming entry...",
|
|
8029
|
+
success: "You're in! \u{1F3C6}"
|
|
8030
|
+
};
|
|
8031
|
+
var QUICK_AMOUNTS = [0.1, 0.5, 1];
|
|
8032
|
+
function formatSOL2(lamports) {
|
|
8033
|
+
const val = typeof lamports === "string" ? parseInt(lamports, 10) : lamports;
|
|
8034
|
+
if (isNaN(val) || val === 0) return "0";
|
|
8035
|
+
const sol = val / 1e9;
|
|
8036
|
+
if (sol >= 100) return sol.toFixed(0);
|
|
8037
|
+
if (sol >= 1) return sol.toFixed(2);
|
|
8038
|
+
if (sol >= 0.01) return sol.toFixed(3);
|
|
8039
|
+
return sol.toFixed(4);
|
|
8040
|
+
}
|
|
8041
|
+
function truncateWallet3(addr) {
|
|
8042
|
+
if (!addr || addr.length < 8) return addr || "";
|
|
8043
|
+
return `${addr.slice(0, 4)}...${addr.slice(-4)}`;
|
|
8044
|
+
}
|
|
8045
|
+
function JackpotSheet({
|
|
8046
|
+
visible,
|
|
8047
|
+
onDismiss,
|
|
8048
|
+
onSuccess,
|
|
8049
|
+
onError,
|
|
8050
|
+
minEntry = 0.01,
|
|
8051
|
+
maxEntry = 10
|
|
8052
|
+
}) {
|
|
8053
|
+
const t = useDubsTheme();
|
|
8054
|
+
const { wallet, client } = useDubs();
|
|
8055
|
+
const { round, lastWinner, refetch } = useJackpot();
|
|
8056
|
+
const mutation = useEnterJackpot();
|
|
8057
|
+
const [betAmount, setBetAmount] = (0, import_react47.useState)("0.1");
|
|
8058
|
+
const [entries, setEntries] = (0, import_react47.useState)([]);
|
|
8059
|
+
const overlayOpacity = (0, import_react47.useRef)(new import_react_native28.Animated.Value(0)).current;
|
|
8060
|
+
(0, import_react47.useEffect)(() => {
|
|
8061
|
+
import_react_native28.Animated.timing(overlayOpacity, {
|
|
8062
|
+
toValue: visible ? 1 : 0,
|
|
8063
|
+
duration: 250,
|
|
8064
|
+
useNativeDriver: true
|
|
8065
|
+
}).start();
|
|
8066
|
+
}, [visible, overlayOpacity]);
|
|
8067
|
+
(0, import_react47.useEffect)(() => {
|
|
8068
|
+
if (visible) {
|
|
8069
|
+
mutation.reset();
|
|
8070
|
+
setBetAmount("0.1");
|
|
8071
|
+
refetch();
|
|
8072
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8073
|
+
});
|
|
8074
|
+
}
|
|
8075
|
+
}, [visible]);
|
|
8076
|
+
(0, import_react47.useEffect)(() => {
|
|
8077
|
+
if (mutation.status === "success" && mutation.data) {
|
|
8078
|
+
onSuccess?.(mutation.data);
|
|
8079
|
+
refetch();
|
|
8080
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8081
|
+
});
|
|
8082
|
+
const timer = setTimeout(() => onDismiss(), 2500);
|
|
8083
|
+
return () => clearTimeout(timer);
|
|
8084
|
+
}
|
|
8085
|
+
}, [mutation.status, mutation.data]);
|
|
8086
|
+
(0, import_react47.useEffect)(() => {
|
|
8087
|
+
if (mutation.status === "error" && mutation.error) {
|
|
8088
|
+
onError?.(mutation.error);
|
|
8089
|
+
}
|
|
8090
|
+
}, [mutation.status, mutation.error]);
|
|
8091
|
+
const potSol = round ? Number(BigInt(round.totalPotLamports || "0")) / 1e9 : 0;
|
|
8092
|
+
const totalWeight = round ? Number(BigInt(round.totalWeight || "0")) : 0;
|
|
8093
|
+
const betSol = parseFloat(betAmount) || 0;
|
|
8094
|
+
const entryLamports = Math.round(betSol * 1e9);
|
|
8095
|
+
const userOdds = totalWeight > 0 ? (entryLamports / (totalWeight + entryLamports) * 100).toFixed(1) : entries.length === 0 ? "100.0" : "0.0";
|
|
8096
|
+
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
8097
|
+
const canEnter = !isMutating && mutation.status !== "success" && round?.status === "Open" && betSol >= minEntry;
|
|
8098
|
+
const handleQuickAdd = (0, import_react47.useCallback)((amount) => {
|
|
8099
|
+
setBetAmount((prev) => {
|
|
8100
|
+
const current = parseFloat(prev) || 0;
|
|
8101
|
+
const next = Math.min(current + amount, maxEntry);
|
|
8102
|
+
return next.toFixed(2);
|
|
8103
|
+
});
|
|
8104
|
+
}, [maxEntry]);
|
|
8105
|
+
const handleEnter = (0, import_react47.useCallback)(async () => {
|
|
8106
|
+
if (!wallet.publicKey || entryLamports < 1e4) return;
|
|
8107
|
+
try {
|
|
8108
|
+
await mutation.execute(entryLamports);
|
|
8109
|
+
} catch {
|
|
8110
|
+
}
|
|
8111
|
+
}, [wallet.publicKey, mutation.execute, entryLamports]);
|
|
8112
|
+
const statusLabel = STATUS_LABELS7[mutation.status] || "";
|
|
8113
|
+
const renderPlayerCard = ({ item, index }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.playerCard, children: [
|
|
8114
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.playerAvatar, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.playerAvatarText, children: item.player.slice(0, 2).toUpperCase() }) }),
|
|
8115
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.playerUsername, numberOfLines: 1, children: [
|
|
8116
|
+
"@",
|
|
8117
|
+
truncateWallet3(item.player)
|
|
8118
|
+
] }),
|
|
8119
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.playerWagerRow, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.playerWagerAmount, children: [
|
|
8120
|
+
item.weightSol.toFixed(2),
|
|
8121
|
+
" SOL"
|
|
8122
|
+
] }) }),
|
|
8123
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.playerOdds, children: [
|
|
8124
|
+
item.oddsPercent,
|
|
8125
|
+
"%"
|
|
8126
|
+
] })
|
|
8127
|
+
] });
|
|
8128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
8129
|
+
import_react_native28.Modal,
|
|
8130
|
+
{
|
|
8131
|
+
visible,
|
|
8132
|
+
animationType: "slide",
|
|
8133
|
+
transparent: true,
|
|
8134
|
+
onRequestClose: onDismiss,
|
|
8135
|
+
children: [
|
|
8136
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Animated.View, { style: [styles22.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.TouchableOpacity, { style: styles22.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
|
|
8137
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.sheetPositioner, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.sheet, children: [
|
|
8138
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.handleRow, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.handle }) }),
|
|
8139
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
8140
|
+
import_react_native28.ScrollView,
|
|
8141
|
+
{
|
|
8142
|
+
style: styles22.scrollView,
|
|
8143
|
+
contentContainerStyle: styles22.scrollContent,
|
|
8144
|
+
showsVerticalScrollIndicator: false,
|
|
8145
|
+
bounces: true,
|
|
8146
|
+
children: [
|
|
8147
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.header, children: [
|
|
8148
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.headerTitle, children: "Jackpot" }),
|
|
8149
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.TouchableOpacity, { onPress: onDismiss, activeOpacity: 0.8, style: styles22.closeBtn, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.closeBtnText, children: "\u2715" }) })
|
|
8150
|
+
] }),
|
|
8151
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.heroCard, children: [
|
|
8152
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.heroGradient }),
|
|
8153
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.heroLabel, children: "JACKPOT" }),
|
|
8154
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.heroPotRow, children: [
|
|
8155
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.heroPotValue, children: [
|
|
8156
|
+
potSol.toFixed(4),
|
|
8157
|
+
" SOL"
|
|
8158
|
+
] }),
|
|
8159
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.heroEmoji, children: "\u{1F911}" })
|
|
8160
|
+
] }),
|
|
8161
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.heroAccentBar })
|
|
8162
|
+
] }),
|
|
8163
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.infoRow, children: [
|
|
8164
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.infoCard, children: [
|
|
8165
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.infoCardLabel, children: "YOUR WAGER" }),
|
|
8166
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.infoCardValue, children: betSol.toFixed(2) })
|
|
8167
|
+
] }),
|
|
8168
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.infoCard, children: [
|
|
8169
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.infoCardLabel, children: "YOUR CHANCE" }),
|
|
8170
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: [styles22.infoCardValue, { color: "#22c55e" }], children: [
|
|
8171
|
+
userOdds,
|
|
8172
|
+
"%"
|
|
8173
|
+
] })
|
|
8174
|
+
] }),
|
|
8175
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.infoCard, children: [
|
|
8176
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.infoCardLabel, children: "PLAYERS" }),
|
|
8177
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.infoCardValue, children: entries.length })
|
|
8178
|
+
] })
|
|
8179
|
+
] }),
|
|
8180
|
+
entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.playersSection, children: [
|
|
8181
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.playersSectionHeader, children: [
|
|
8182
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.playersSectionTitle, children: "Players in Round" }),
|
|
8183
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.playersBadge, children: [
|
|
8184
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.playersBadgeDot }),
|
|
8185
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.playersBadgeText, children: [
|
|
8186
|
+
entries.length,
|
|
8187
|
+
" active"
|
|
8188
|
+
] })
|
|
8189
|
+
] })
|
|
8190
|
+
] }),
|
|
8191
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8192
|
+
import_react_native28.FlatList,
|
|
8193
|
+
{
|
|
8194
|
+
data: entries,
|
|
8195
|
+
renderItem: renderPlayerCard,
|
|
8196
|
+
keyExtractor: (item, i) => `${item.player}-${i}`,
|
|
8197
|
+
horizontal: true,
|
|
8198
|
+
showsHorizontalScrollIndicator: false,
|
|
8199
|
+
contentContainerStyle: styles22.playersListContent,
|
|
8200
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: { width: 10 } })
|
|
8201
|
+
}
|
|
8202
|
+
)
|
|
8203
|
+
] }),
|
|
8204
|
+
entries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.emptyState, children: [
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.emptyEmoji, children: "\u{1F911}" }),
|
|
8206
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.emptyTitle, children: "No players yet" }),
|
|
8207
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.emptySubtitle, children: "Be the first to join!" })
|
|
8208
|
+
] }),
|
|
8209
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.betSection, children: [
|
|
8210
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.betLabel, children: "Bet Amount" }),
|
|
8211
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.betInputRow, children: [
|
|
8212
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.solIcon, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.solIconText, children: "\u25CE" }) }),
|
|
8213
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8214
|
+
import_react_native28.TextInput,
|
|
8215
|
+
{
|
|
8216
|
+
style: styles22.betInput,
|
|
8217
|
+
value: betAmount,
|
|
8218
|
+
onChangeText: setBetAmount,
|
|
8219
|
+
keyboardType: "decimal-pad",
|
|
8220
|
+
placeholder: "0.00",
|
|
8221
|
+
placeholderTextColor: "#6b6b6b",
|
|
8222
|
+
selectTextOnFocus: true
|
|
8223
|
+
}
|
|
8224
|
+
),
|
|
8225
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.betInputSuffix, children: "SOL" })
|
|
8226
|
+
] }),
|
|
8227
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.quickBetRow, children: QUICK_AMOUNTS.map((amount) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8228
|
+
import_react_native28.TouchableOpacity,
|
|
8229
|
+
{
|
|
8230
|
+
style: styles22.quickBetBtn,
|
|
8231
|
+
onPress: () => handleQuickAdd(amount),
|
|
8232
|
+
activeOpacity: 0.7,
|
|
8233
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.quickBetText, children: [
|
|
8234
|
+
"+",
|
|
8235
|
+
amount,
|
|
8236
|
+
" SOL"
|
|
8237
|
+
] })
|
|
8238
|
+
},
|
|
8239
|
+
amount
|
|
8240
|
+
)) })
|
|
8241
|
+
] }),
|
|
8242
|
+
mutation.error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.View, { style: styles22.errorBox, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.errorText, children: mutation.error.message }) }),
|
|
8243
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8244
|
+
import_react_native28.TouchableOpacity,
|
|
8245
|
+
{
|
|
8246
|
+
style: [
|
|
8247
|
+
styles22.placeBetBtn,
|
|
8248
|
+
!canEnter && styles22.placeBetBtnDisabled,
|
|
8249
|
+
mutation.status === "success" && styles22.placeBetBtnSuccess
|
|
8250
|
+
],
|
|
8251
|
+
disabled: !canEnter,
|
|
8252
|
+
onPress: handleEnter,
|
|
8253
|
+
activeOpacity: 0.85,
|
|
8254
|
+
children: isMutating ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.placeBetLoading, children: [
|
|
8255
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
|
|
8256
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.placeBetText, children: statusLabel })
|
|
8257
|
+
] }) : mutation.status === "success" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.placeBetText, children: "You're in! \u{1F3C6}" }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: [styles22.placeBetText, !canEnter && { opacity: 0.5 }], children: [
|
|
8258
|
+
"Place Bet \u2014 ",
|
|
8259
|
+
betSol.toFixed(2),
|
|
8260
|
+
" SOL"
|
|
8261
|
+
] })
|
|
8262
|
+
}
|
|
8263
|
+
),
|
|
8264
|
+
lastWinner && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.lastWinnerSection, children: [
|
|
8265
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.lastWinnerLabel, children: "Last Winner" }),
|
|
8266
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.View, { style: styles22.lastWinnerRow, children: [
|
|
8267
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native28.Text, { style: styles22.lastWinnerWallet, children: truncateWallet3(lastWinner.winner) }),
|
|
8268
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native28.Text, { style: styles22.lastWinnerAmount, children: [
|
|
8269
|
+
"won ",
|
|
8270
|
+
formatSOL2(lastWinner.winAmount),
|
|
8271
|
+
" SOL"
|
|
8272
|
+
] })
|
|
8273
|
+
] })
|
|
8274
|
+
] })
|
|
8275
|
+
]
|
|
8276
|
+
}
|
|
8277
|
+
)
|
|
8278
|
+
] }) })
|
|
8279
|
+
]
|
|
8280
|
+
}
|
|
8281
|
+
);
|
|
8282
|
+
}
|
|
8283
|
+
var styles22 = import_react_native28.StyleSheet.create({
|
|
8284
|
+
overlay: {
|
|
8285
|
+
...import_react_native28.StyleSheet.absoluteFillObject,
|
|
8286
|
+
backgroundColor: "rgba(0,0,0,0.65)"
|
|
8287
|
+
},
|
|
8288
|
+
overlayTap: { flex: 1 },
|
|
8289
|
+
sheetPositioner: {
|
|
8290
|
+
flex: 1,
|
|
8291
|
+
justifyContent: "flex-end"
|
|
8292
|
+
},
|
|
8293
|
+
sheet: {
|
|
8294
|
+
backgroundColor: "#08080e",
|
|
8295
|
+
borderTopLeftRadius: 24,
|
|
8296
|
+
borderTopRightRadius: 24,
|
|
8297
|
+
maxHeight: "92%",
|
|
8298
|
+
borderWidth: 1,
|
|
8299
|
+
borderColor: "#1e1e2a",
|
|
8300
|
+
borderBottomWidth: 0
|
|
8301
|
+
},
|
|
8302
|
+
handleRow: { alignItems: "center", paddingTop: 10, paddingBottom: 4 },
|
|
8303
|
+
handle: { width: 36, height: 4, borderRadius: 2, backgroundColor: "#2a2a3a" },
|
|
8304
|
+
scrollView: { flexGrow: 0 },
|
|
8305
|
+
scrollContent: {
|
|
8306
|
+
paddingHorizontal: 16,
|
|
8307
|
+
paddingBottom: import_react_native28.Platform.OS === "ios" ? 40 : 24
|
|
8308
|
+
},
|
|
8309
|
+
// Header
|
|
8310
|
+
header: {
|
|
8311
|
+
flexDirection: "row",
|
|
8312
|
+
alignItems: "center",
|
|
8313
|
+
justifyContent: "space-between",
|
|
8314
|
+
paddingVertical: 12
|
|
8315
|
+
},
|
|
8316
|
+
headerTitle: { fontSize: 20, fontWeight: "700", color: "#FFFFFF" },
|
|
8317
|
+
closeBtn: { padding: 4 },
|
|
8318
|
+
closeBtnText: { fontSize: 20, color: "#6b6b6b" },
|
|
8319
|
+
// Hero pot card
|
|
8320
|
+
heroCard: {
|
|
8321
|
+
borderRadius: 16,
|
|
8322
|
+
borderWidth: 1,
|
|
8323
|
+
borderColor: "rgba(34, 197, 94, 0.2)",
|
|
8324
|
+
padding: 16,
|
|
8325
|
+
overflow: "hidden",
|
|
8326
|
+
position: "relative"
|
|
8327
|
+
},
|
|
8328
|
+
heroGradient: {
|
|
8329
|
+
...import_react_native28.StyleSheet.absoluteFillObject,
|
|
8330
|
+
backgroundColor: "rgba(34, 197, 94, 0.04)"
|
|
8331
|
+
},
|
|
8332
|
+
heroLabel: {
|
|
8333
|
+
fontSize: 10,
|
|
8334
|
+
fontWeight: "600",
|
|
8335
|
+
color: "#6b6b6b",
|
|
8336
|
+
letterSpacing: 3,
|
|
8337
|
+
marginBottom: 4
|
|
8338
|
+
},
|
|
8339
|
+
heroPotRow: {
|
|
8340
|
+
flexDirection: "row",
|
|
8341
|
+
alignItems: "center",
|
|
8342
|
+
justifyContent: "space-between"
|
|
8343
|
+
},
|
|
8344
|
+
heroPotValue: {
|
|
8345
|
+
fontSize: 32,
|
|
8346
|
+
fontWeight: "900",
|
|
8347
|
+
color: "#4ade80",
|
|
8348
|
+
letterSpacing: -1
|
|
8349
|
+
},
|
|
8350
|
+
heroEmoji: {
|
|
8351
|
+
fontSize: 36,
|
|
8352
|
+
opacity: 0.2
|
|
8353
|
+
},
|
|
8354
|
+
heroAccentBar: {
|
|
8355
|
+
position: "absolute",
|
|
8356
|
+
bottom: 0,
|
|
8357
|
+
left: 0,
|
|
8358
|
+
width: "60%",
|
|
8359
|
+
height: 2,
|
|
8360
|
+
backgroundColor: "#22c55e"
|
|
8361
|
+
},
|
|
8362
|
+
// Info row
|
|
8363
|
+
infoRow: {
|
|
8364
|
+
flexDirection: "row",
|
|
8365
|
+
gap: 8,
|
|
8366
|
+
marginTop: 12
|
|
8367
|
+
},
|
|
8368
|
+
infoCard: {
|
|
8369
|
+
flex: 1,
|
|
8370
|
+
borderRadius: 12,
|
|
8371
|
+
borderWidth: 1,
|
|
8372
|
+
borderColor: "#1e1e2a",
|
|
8373
|
+
backgroundColor: "#0c0c14",
|
|
8374
|
+
padding: 12
|
|
8375
|
+
},
|
|
8376
|
+
infoCardLabel: {
|
|
8377
|
+
fontSize: 9,
|
|
8378
|
+
fontWeight: "600",
|
|
8379
|
+
color: "#6b6b6b",
|
|
8380
|
+
letterSpacing: 2,
|
|
8381
|
+
marginBottom: 4
|
|
8382
|
+
},
|
|
8383
|
+
infoCardValue: {
|
|
8384
|
+
fontSize: 18,
|
|
8385
|
+
fontWeight: "700",
|
|
8386
|
+
color: "#FFFFFF"
|
|
8387
|
+
},
|
|
8388
|
+
// Players section
|
|
8389
|
+
playersSection: {
|
|
8390
|
+
marginTop: 16,
|
|
8391
|
+
borderRadius: 16,
|
|
8392
|
+
borderWidth: 1,
|
|
8393
|
+
borderColor: "#1e1e2a",
|
|
8394
|
+
backgroundColor: "rgba(139, 92, 246, 0.03)",
|
|
8395
|
+
padding: 12,
|
|
8396
|
+
overflow: "hidden"
|
|
8397
|
+
},
|
|
8398
|
+
playersSectionHeader: {
|
|
8399
|
+
flexDirection: "row",
|
|
8400
|
+
alignItems: "center",
|
|
8401
|
+
justifyContent: "space-between",
|
|
8402
|
+
marginBottom: 12
|
|
8403
|
+
},
|
|
8404
|
+
playersSectionTitle: {
|
|
8405
|
+
fontSize: 13,
|
|
8406
|
+
fontWeight: "600",
|
|
8407
|
+
color: "#a0a0a0"
|
|
8408
|
+
},
|
|
8409
|
+
playersBadge: {
|
|
8410
|
+
flexDirection: "row",
|
|
8411
|
+
alignItems: "center",
|
|
8412
|
+
gap: 6,
|
|
8413
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)",
|
|
8414
|
+
paddingHorizontal: 8,
|
|
8415
|
+
paddingVertical: 3,
|
|
8416
|
+
borderRadius: 100
|
|
8417
|
+
},
|
|
8418
|
+
playersBadgeDot: {
|
|
8419
|
+
width: 6,
|
|
8420
|
+
height: 6,
|
|
8421
|
+
borderRadius: 3,
|
|
8422
|
+
backgroundColor: "#22c55e"
|
|
8423
|
+
},
|
|
8424
|
+
playersBadgeText: {
|
|
8425
|
+
fontSize: 11,
|
|
8426
|
+
fontWeight: "700",
|
|
8427
|
+
color: "#22c55e"
|
|
8428
|
+
},
|
|
8429
|
+
playersListContent: {
|
|
8430
|
+
paddingRight: 4
|
|
8431
|
+
},
|
|
8432
|
+
// Player cards (carousel items)
|
|
8433
|
+
playerCard: {
|
|
8434
|
+
width: 110,
|
|
8435
|
+
borderRadius: 12,
|
|
8436
|
+
borderWidth: 1.5,
|
|
8437
|
+
borderColor: "rgba(139, 92, 246, 0.4)",
|
|
8438
|
+
backgroundColor: "rgba(139, 92, 246, 0.08)",
|
|
8439
|
+
padding: 12,
|
|
8440
|
+
alignItems: "center",
|
|
8441
|
+
gap: 6
|
|
8442
|
+
},
|
|
8443
|
+
playerAvatar: {
|
|
8444
|
+
width: 48,
|
|
8445
|
+
height: 48,
|
|
8446
|
+
borderRadius: 24,
|
|
8447
|
+
borderWidth: 2,
|
|
8448
|
+
borderColor: "#8b5cf6",
|
|
8449
|
+
backgroundColor: "rgba(139, 92, 246, 0.15)",
|
|
8450
|
+
alignItems: "center",
|
|
8451
|
+
justifyContent: "center"
|
|
8452
|
+
},
|
|
8453
|
+
playerAvatarText: {
|
|
8454
|
+
fontSize: 16,
|
|
8455
|
+
fontWeight: "700",
|
|
8456
|
+
color: "#a78bfa"
|
|
8457
|
+
},
|
|
8458
|
+
playerUsername: {
|
|
8459
|
+
fontSize: 11,
|
|
8460
|
+
fontWeight: "500",
|
|
8461
|
+
color: "#a0a0a0",
|
|
8462
|
+
textAlign: "center"
|
|
8463
|
+
},
|
|
8464
|
+
playerWagerRow: {
|
|
8465
|
+
flexDirection: "row",
|
|
8466
|
+
alignItems: "center",
|
|
8467
|
+
gap: 4
|
|
8468
|
+
},
|
|
8469
|
+
playerWagerAmount: {
|
|
8470
|
+
fontSize: 13,
|
|
8471
|
+
fontWeight: "600",
|
|
8472
|
+
color: "#a78bfa"
|
|
8473
|
+
},
|
|
8474
|
+
playerOdds: {
|
|
8475
|
+
fontSize: 11,
|
|
8476
|
+
fontWeight: "700",
|
|
8477
|
+
color: "#22c55e"
|
|
8478
|
+
},
|
|
8479
|
+
// Empty state
|
|
8480
|
+
emptyState: {
|
|
8481
|
+
marginTop: 16,
|
|
8482
|
+
alignItems: "center",
|
|
8483
|
+
paddingVertical: 24,
|
|
8484
|
+
borderRadius: 16,
|
|
8485
|
+
borderWidth: 1,
|
|
8486
|
+
borderColor: "#1e1e2a",
|
|
8487
|
+
backgroundColor: "#0c0c14"
|
|
8488
|
+
},
|
|
8489
|
+
emptyEmoji: { fontSize: 40, marginBottom: 8 },
|
|
8490
|
+
emptyTitle: { fontSize: 16, fontWeight: "600", color: "#FFFFFF" },
|
|
8491
|
+
emptySubtitle: { fontSize: 13, color: "#6b6b6b", marginTop: 4 },
|
|
8492
|
+
// Bet section
|
|
8493
|
+
betSection: {
|
|
8494
|
+
marginTop: 16
|
|
8495
|
+
},
|
|
8496
|
+
betLabel: {
|
|
8497
|
+
fontSize: 13,
|
|
8498
|
+
fontWeight: "500",
|
|
8499
|
+
color: "#6b6b6b",
|
|
8500
|
+
marginBottom: 8
|
|
8501
|
+
},
|
|
8502
|
+
betInputRow: {
|
|
8503
|
+
flexDirection: "row",
|
|
8504
|
+
alignItems: "center",
|
|
8505
|
+
gap: 8,
|
|
8506
|
+
backgroundColor: "#08080e",
|
|
8507
|
+
borderWidth: 1,
|
|
8508
|
+
borderColor: "#2a2a3a",
|
|
8509
|
+
borderRadius: 12,
|
|
8510
|
+
paddingHorizontal: 14,
|
|
8511
|
+
paddingVertical: import_react_native28.Platform.OS === "ios" ? 14 : 10
|
|
8512
|
+
},
|
|
8513
|
+
solIcon: {
|
|
8514
|
+
width: 32,
|
|
8515
|
+
height: 32,
|
|
8516
|
+
borderRadius: 16,
|
|
8517
|
+
backgroundColor: "rgba(139, 92, 246, 0.15)",
|
|
8518
|
+
alignItems: "center",
|
|
8519
|
+
justifyContent: "center"
|
|
8520
|
+
},
|
|
8521
|
+
solIconText: {
|
|
8522
|
+
fontSize: 18,
|
|
8523
|
+
color: "#a78bfa",
|
|
8524
|
+
fontWeight: "700"
|
|
8525
|
+
},
|
|
8526
|
+
betInput: {
|
|
8527
|
+
flex: 1,
|
|
8528
|
+
fontSize: 24,
|
|
8529
|
+
fontWeight: "700",
|
|
8530
|
+
color: "#FFFFFF",
|
|
8531
|
+
padding: 0
|
|
8532
|
+
},
|
|
8533
|
+
betInputSuffix: {
|
|
8534
|
+
fontSize: 14,
|
|
8535
|
+
fontWeight: "500",
|
|
8536
|
+
color: "#6b6b6b"
|
|
8537
|
+
},
|
|
8538
|
+
quickBetRow: {
|
|
8539
|
+
flexDirection: "row",
|
|
8540
|
+
gap: 8,
|
|
8541
|
+
marginTop: 10
|
|
8542
|
+
},
|
|
8543
|
+
quickBetBtn: {
|
|
8544
|
+
flex: 1,
|
|
8545
|
+
paddingVertical: 12,
|
|
8546
|
+
borderRadius: 10,
|
|
8547
|
+
borderWidth: 1,
|
|
8548
|
+
borderColor: "#2a2a3a",
|
|
8549
|
+
backgroundColor: "#08080e",
|
|
8550
|
+
alignItems: "center"
|
|
8551
|
+
},
|
|
8552
|
+
quickBetText: {
|
|
8553
|
+
fontSize: 13,
|
|
8554
|
+
fontWeight: "600",
|
|
8555
|
+
color: "#FFFFFF"
|
|
8556
|
+
},
|
|
8557
|
+
// Error
|
|
8558
|
+
errorBox: {
|
|
8559
|
+
marginTop: 12,
|
|
8560
|
+
borderRadius: 12,
|
|
8561
|
+
borderWidth: 1,
|
|
8562
|
+
borderColor: "#3A1515",
|
|
8563
|
+
backgroundColor: "#1A0A0A",
|
|
8564
|
+
padding: 12
|
|
8565
|
+
},
|
|
8566
|
+
errorText: { fontSize: 13, fontWeight: "500", color: "#F87171" },
|
|
8567
|
+
// Place Bet CTA
|
|
8568
|
+
placeBetBtn: {
|
|
8569
|
+
marginTop: 16,
|
|
8570
|
+
height: 56,
|
|
8571
|
+
borderRadius: 14,
|
|
8572
|
+
justifyContent: "center",
|
|
8573
|
+
alignItems: "center",
|
|
8574
|
+
backgroundColor: "#22c55e",
|
|
8575
|
+
shadowColor: "#22c55e",
|
|
8576
|
+
shadowOffset: { width: 0, height: 4 },
|
|
8577
|
+
shadowOpacity: 0.25,
|
|
8578
|
+
shadowRadius: 12,
|
|
8579
|
+
elevation: 6
|
|
8580
|
+
},
|
|
8581
|
+
placeBetBtnDisabled: {
|
|
8582
|
+
backgroundColor: "#1e1e2a",
|
|
8583
|
+
shadowOpacity: 0,
|
|
8584
|
+
elevation: 0
|
|
8585
|
+
},
|
|
8586
|
+
placeBetBtnSuccess: {
|
|
8587
|
+
backgroundColor: "#16a34a"
|
|
8588
|
+
},
|
|
8589
|
+
placeBetText: { color: "#FFFFFF", fontSize: 16, fontWeight: "700" },
|
|
8590
|
+
placeBetLoading: { flexDirection: "row", alignItems: "center", gap: 10 },
|
|
8591
|
+
// Last winner
|
|
8592
|
+
lastWinnerSection: {
|
|
8593
|
+
marginTop: 14,
|
|
8594
|
+
paddingTop: 14,
|
|
8595
|
+
borderTopWidth: 1,
|
|
8596
|
+
borderTopColor: "#1e1e2a"
|
|
8597
|
+
},
|
|
8598
|
+
lastWinnerLabel: {
|
|
8599
|
+
fontSize: 11,
|
|
8600
|
+
fontWeight: "600",
|
|
8601
|
+
color: "#6b6b6b",
|
|
8602
|
+
letterSpacing: 1,
|
|
8603
|
+
textTransform: "uppercase",
|
|
8604
|
+
marginBottom: 4
|
|
8605
|
+
},
|
|
8606
|
+
lastWinnerRow: {
|
|
8607
|
+
flexDirection: "row",
|
|
8608
|
+
alignItems: "center",
|
|
8609
|
+
gap: 6
|
|
8610
|
+
},
|
|
8611
|
+
lastWinnerWallet: {
|
|
8612
|
+
fontSize: 13,
|
|
8613
|
+
fontWeight: "500",
|
|
8614
|
+
color: "#a0a0a0"
|
|
8615
|
+
},
|
|
8616
|
+
lastWinnerAmount: {
|
|
8617
|
+
fontSize: 13,
|
|
8618
|
+
fontWeight: "600",
|
|
8619
|
+
color: "#22c55e"
|
|
8620
|
+
}
|
|
8621
|
+
});
|
|
8622
|
+
|
|
8623
|
+
// src/ui/jackpot/JackpotWidget.tsx
|
|
8624
|
+
var import_react48 = require("react");
|
|
8625
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
8626
|
+
function JackpotWidget({
|
|
8627
|
+
style,
|
|
8628
|
+
minEntry,
|
|
8629
|
+
maxEntry,
|
|
8630
|
+
onEntry,
|
|
8631
|
+
onError
|
|
8632
|
+
}) {
|
|
8633
|
+
const [sheetVisible, setSheetVisible] = (0, import_react48.useState)(false);
|
|
8634
|
+
const { round, lastWinner } = useJackpot();
|
|
8635
|
+
const { client } = useDubs();
|
|
8636
|
+
const [entries, setEntries] = (0, import_react48.useState)([]);
|
|
8637
|
+
(0, import_react48.useEffect)(() => {
|
|
8638
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8639
|
+
});
|
|
8640
|
+
}, [client, round?.entryCount]);
|
|
8641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
8642
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
8643
|
+
JackpotCard,
|
|
8644
|
+
{
|
|
8645
|
+
round,
|
|
8646
|
+
lastWinner,
|
|
8647
|
+
entries,
|
|
8648
|
+
onPress: () => setSheetVisible(true),
|
|
8649
|
+
style
|
|
8650
|
+
}
|
|
8651
|
+
),
|
|
8652
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
8653
|
+
JackpotSheet,
|
|
8654
|
+
{
|
|
8655
|
+
visible: sheetVisible,
|
|
8656
|
+
onDismiss: () => setSheetVisible(false),
|
|
8657
|
+
onSuccess: (result) => {
|
|
8658
|
+
onEntry?.(result);
|
|
8659
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8660
|
+
});
|
|
8661
|
+
},
|
|
8662
|
+
onError,
|
|
8663
|
+
minEntry,
|
|
8664
|
+
maxEntry
|
|
8665
|
+
}
|
|
8666
|
+
)
|
|
8667
|
+
] });
|
|
8668
|
+
}
|
|
8669
|
+
|
|
8670
|
+
// src/chat/provider.tsx
|
|
8671
|
+
var import_react49 = require("react");
|
|
8672
|
+
var import_react_native29 = require("react-native");
|
|
8673
|
+
|
|
8674
|
+
// src/chat/socket.ts
|
|
8675
|
+
var import_socket = require("socket.io-client");
|
|
8676
|
+
var ChatSocket = class {
|
|
8677
|
+
constructor() {
|
|
8678
|
+
this.socket = null;
|
|
8679
|
+
this.listeners = {};
|
|
8680
|
+
}
|
|
8681
|
+
/** Set event listeners. Call before or after connect. */
|
|
8682
|
+
setListeners(listeners) {
|
|
8683
|
+
this.listeners = listeners;
|
|
8684
|
+
}
|
|
8685
|
+
/** Connect to the /chat namespace */
|
|
8686
|
+
connect(config) {
|
|
8687
|
+
if (this.socket?.connected) {
|
|
8688
|
+
console.log("[Dubs:ChatSocket] Already connected");
|
|
8689
|
+
return;
|
|
8690
|
+
}
|
|
8691
|
+
this.listeners.onConnectionChange?.("connecting");
|
|
8692
|
+
console.log(`[Dubs:ChatSocket] Connecting to ${config.host}/chat`);
|
|
8693
|
+
this.socket = (0, import_socket.io)(`${config.host}/chat`, {
|
|
8694
|
+
auth: { token: config.token },
|
|
8695
|
+
transports: ["websocket"],
|
|
8696
|
+
reconnection: true,
|
|
8697
|
+
reconnectionDelay: 1e3,
|
|
8698
|
+
reconnectionAttempts: 10
|
|
8699
|
+
});
|
|
8700
|
+
this.socket.on("connect", () => {
|
|
8701
|
+
console.log("[Dubs:ChatSocket] Connected");
|
|
8702
|
+
this.listeners.onConnectionChange?.("connected");
|
|
8703
|
+
});
|
|
8704
|
+
this.socket.on("disconnect", (reason) => {
|
|
8705
|
+
console.log("[Dubs:ChatSocket] Disconnected:", reason);
|
|
8706
|
+
this.listeners.onConnectionChange?.("disconnected");
|
|
8707
|
+
});
|
|
8708
|
+
this.socket.on("connect_error", (error) => {
|
|
8709
|
+
console.error("[Dubs:ChatSocket] Connection error:", error.message);
|
|
8710
|
+
this.listeners.onConnectionChange?.("error");
|
|
8711
|
+
});
|
|
8712
|
+
this.socket.on("new_message", (msg) => this.listeners.onNewMessage?.(msg));
|
|
8713
|
+
this.socket.on("online_users", (users) => this.listeners.onOnlineUsers?.(users));
|
|
8714
|
+
this.socket.on("online_count", (count) => this.listeners.onOnlineCount?.(count));
|
|
8715
|
+
this.socket.on("user_typing", (data) => this.listeners.onTyping?.(data));
|
|
8716
|
+
this.socket.on("reaction_added", (data) => this.listeners.onReactionAdded?.(data));
|
|
8717
|
+
this.socket.on("reaction_removed", (data) => this.listeners.onReactionRemoved?.(data));
|
|
8718
|
+
this.socket.on("notification", (n) => this.listeners.onNotification?.(n));
|
|
8719
|
+
this.socket.on("unread_count", (count) => this.listeners.onUnreadCount?.(count));
|
|
8720
|
+
this.socket.on("dm:new_message", (msg) => this.listeners.onDMNewMessage?.(msg));
|
|
8721
|
+
this.socket.on("dm:message_sent", (msg) => this.listeners.onDMMessageSent?.(msg));
|
|
8722
|
+
this.socket.on("dm:notification", (data) => this.listeners.onDMNotification?.(data));
|
|
8723
|
+
this.socket.on("dm:messages_read", (data) => this.listeners.onDMMessagesRead?.(data));
|
|
8724
|
+
this.socket.on("friend_request_accepted", (data) => this.listeners.onFriendRequestAccepted?.(data));
|
|
8725
|
+
this.socket.on("friend_request_declined", (data) => this.listeners.onFriendRequestDeclined?.(data));
|
|
8726
|
+
this.socket.on("friend_removed", (data) => this.listeners.onFriendRemoved?.(data));
|
|
8727
|
+
this.socket.on("error", (err) => this.listeners.onError?.(err));
|
|
8728
|
+
}
|
|
8729
|
+
/** Disconnect from the chat namespace */
|
|
8730
|
+
disconnect() {
|
|
8731
|
+
if (this.socket) {
|
|
8732
|
+
console.log("[Dubs:ChatSocket] Disconnecting");
|
|
8733
|
+
this.socket.removeAllListeners();
|
|
8734
|
+
this.socket.disconnect();
|
|
8735
|
+
this.socket = null;
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8738
|
+
/** Whether the socket is currently connected */
|
|
8739
|
+
isConnected() {
|
|
8740
|
+
return this.socket?.connected ?? false;
|
|
8741
|
+
}
|
|
8742
|
+
// ── Global Chat Actions ──
|
|
8743
|
+
/** Send a message to global chat */
|
|
8744
|
+
sendMessage(params) {
|
|
8745
|
+
this.socket?.emit("send_message", params);
|
|
8746
|
+
}
|
|
8747
|
+
/** Emit typing indicator */
|
|
8748
|
+
sendTyping(isTyping) {
|
|
8749
|
+
this.socket?.emit("typing", isTyping);
|
|
8750
|
+
}
|
|
8751
|
+
/** Add an emoji reaction to a message */
|
|
8752
|
+
addReaction(messageId, reaction) {
|
|
8753
|
+
this.socket?.emit("add_reaction", { messageId, reaction });
|
|
8754
|
+
}
|
|
8755
|
+
/** Remove an emoji reaction from a message */
|
|
8756
|
+
removeReaction(messageId, reaction) {
|
|
8757
|
+
this.socket?.emit("remove_reaction", { messageId, reaction });
|
|
8758
|
+
}
|
|
8759
|
+
// ── DM Actions ──
|
|
8760
|
+
/** Join a DM room to receive messages in real-time */
|
|
8761
|
+
joinDM(recipientWallet) {
|
|
8762
|
+
this.socket?.emit("dm:join", { recipientWallet });
|
|
8763
|
+
}
|
|
8764
|
+
/** Leave a DM room */
|
|
8765
|
+
leaveDM(recipientWallet) {
|
|
8766
|
+
this.socket?.emit("dm:leave", { recipientWallet });
|
|
8767
|
+
}
|
|
8768
|
+
/** Send a direct message via socket */
|
|
8769
|
+
sendDM(params) {
|
|
8770
|
+
this.socket?.emit("dm:send", params);
|
|
8771
|
+
}
|
|
8772
|
+
/** Mark DMs from a sender as read */
|
|
8773
|
+
markDMRead(senderWallet) {
|
|
8774
|
+
this.socket?.emit("dm:mark_read", { senderWallet });
|
|
8775
|
+
}
|
|
8776
|
+
};
|
|
8777
|
+
|
|
8778
|
+
// src/chat/provider.tsx
|
|
8779
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
8780
|
+
var ChatContext = (0, import_react49.createContext)(null);
|
|
8781
|
+
function ChatProvider({ children, autoConnect = true }) {
|
|
8782
|
+
const { client } = useDubs();
|
|
8783
|
+
const socketRef = (0, import_react49.useRef)(new ChatSocket());
|
|
8784
|
+
const [status, setStatus] = (0, import_react49.useState)("disconnected");
|
|
8785
|
+
const [messages, setMessages] = (0, import_react49.useState)([]);
|
|
8786
|
+
const [onlineUsers, setOnlineUsers] = (0, import_react49.useState)([]);
|
|
8787
|
+
const [onlineCount, setOnlineCount] = (0, import_react49.useState)(0);
|
|
8788
|
+
const [unreadCount, setUnreadCount] = (0, import_react49.useState)(0);
|
|
8789
|
+
const [conversations, setConversations] = (0, import_react49.useState)([]);
|
|
8790
|
+
const [friends, setFriends] = (0, import_react49.useState)([]);
|
|
8791
|
+
const [pendingRequests, setPendingRequests] = (0, import_react49.useState)([]);
|
|
8792
|
+
const refreshMessages = (0, import_react49.useCallback)(async () => {
|
|
8793
|
+
try {
|
|
8794
|
+
const res = await client.getChatMessages({ limit: 30 });
|
|
8795
|
+
setMessages(res.messages);
|
|
8796
|
+
} catch (err) {
|
|
8797
|
+
console.error("[Dubs:ChatProvider] Failed to load messages:", err);
|
|
8798
|
+
}
|
|
8799
|
+
}, [client]);
|
|
8800
|
+
const refreshConversations = (0, import_react49.useCallback)(async () => {
|
|
8801
|
+
try {
|
|
8802
|
+
const res = await client.getConversations();
|
|
8803
|
+
setConversations(res.conversations);
|
|
8804
|
+
} catch (_) {
|
|
8805
|
+
}
|
|
8806
|
+
}, [client]);
|
|
8807
|
+
const refreshFriends = (0, import_react49.useCallback)(async () => {
|
|
8808
|
+
try {
|
|
8809
|
+
const res = await client.getFriends();
|
|
8810
|
+
setFriends(res.friends);
|
|
8811
|
+
} catch (_) {
|
|
8812
|
+
}
|
|
8813
|
+
}, [client]);
|
|
8814
|
+
const refreshPendingRequests = (0, import_react49.useCallback)(async () => {
|
|
8815
|
+
try {
|
|
8816
|
+
const res = await client.getPendingFriendRequests();
|
|
8817
|
+
setPendingRequests(res.requests);
|
|
8818
|
+
} catch (_) {
|
|
8819
|
+
}
|
|
8820
|
+
}, [client]);
|
|
8821
|
+
(0, import_react49.useEffect)(() => {
|
|
8822
|
+
const token = client.getToken();
|
|
8823
|
+
if (!autoConnect || !token) return;
|
|
8824
|
+
const chatSocket = socketRef.current;
|
|
8825
|
+
const baseUrl = client.baseUrl;
|
|
8826
|
+
const host = new URL(baseUrl).origin;
|
|
8827
|
+
chatSocket.setListeners({
|
|
8828
|
+
onConnectionChange: setStatus,
|
|
8829
|
+
// Global chat
|
|
8830
|
+
onNewMessage: (msg) => {
|
|
8831
|
+
setMessages((prev) => {
|
|
8832
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
8833
|
+
return [msg, ...prev];
|
|
8834
|
+
});
|
|
8835
|
+
},
|
|
8836
|
+
onOnlineUsers: setOnlineUsers,
|
|
8837
|
+
onOnlineCount: setOnlineCount,
|
|
8838
|
+
onUnreadCount: setUnreadCount,
|
|
8839
|
+
// Notifications trigger conversation refresh
|
|
8840
|
+
onDMNotification: () => {
|
|
8841
|
+
refreshConversations();
|
|
8842
|
+
},
|
|
8843
|
+
onNotification: (n) => {
|
|
8844
|
+
setUnreadCount((prev) => prev + 1);
|
|
8845
|
+
if (n.type === "friend_request") refreshPendingRequests();
|
|
8846
|
+
if (n.type === "friend_request_accepted") refreshFriends();
|
|
8847
|
+
},
|
|
8848
|
+
onFriendRequestAccepted: () => refreshFriends(),
|
|
8849
|
+
onFriendRemoved: () => refreshFriends()
|
|
8850
|
+
});
|
|
8851
|
+
chatSocket.connect({ host, token });
|
|
8852
|
+
refreshMessages();
|
|
8853
|
+
refreshFriends().catch(() => {
|
|
8854
|
+
});
|
|
8855
|
+
refreshPendingRequests().catch(() => {
|
|
8856
|
+
});
|
|
8857
|
+
return () => {
|
|
8858
|
+
chatSocket.disconnect();
|
|
8859
|
+
};
|
|
8860
|
+
}, [client, autoConnect, refreshMessages, refreshConversations, refreshFriends, refreshPendingRequests]);
|
|
8861
|
+
(0, import_react49.useEffect)(() => {
|
|
8862
|
+
const handleAppState = (nextState) => {
|
|
8863
|
+
if (nextState === "active") {
|
|
8864
|
+
const chatSocket = socketRef.current;
|
|
8865
|
+
if (!chatSocket.isConnected()) {
|
|
8866
|
+
const token = client.getToken();
|
|
8867
|
+
if (token) {
|
|
8868
|
+
const baseUrl = client.baseUrl;
|
|
8869
|
+
const host = new URL(baseUrl).origin;
|
|
8870
|
+
chatSocket.connect({ host, token });
|
|
8871
|
+
}
|
|
8872
|
+
}
|
|
8873
|
+
refreshMessages();
|
|
8874
|
+
}
|
|
8875
|
+
};
|
|
8876
|
+
const sub = import_react_native29.AppState.addEventListener("change", handleAppState);
|
|
8877
|
+
return () => sub.remove();
|
|
8878
|
+
}, [client, refreshMessages, refreshConversations]);
|
|
8879
|
+
const value = (0, import_react49.useMemo)(
|
|
8880
|
+
() => ({
|
|
8881
|
+
socket: socketRef.current,
|
|
8882
|
+
status,
|
|
8883
|
+
messages,
|
|
8884
|
+
onlineUsers,
|
|
8885
|
+
onlineCount,
|
|
8886
|
+
unreadCount,
|
|
8887
|
+
conversations,
|
|
8888
|
+
friends,
|
|
8889
|
+
pendingRequests,
|
|
8890
|
+
refreshMessages,
|
|
8891
|
+
refreshConversations,
|
|
8892
|
+
refreshFriends,
|
|
8893
|
+
refreshPendingRequests
|
|
8894
|
+
}),
|
|
8895
|
+
[status, messages, onlineUsers, onlineCount, unreadCount, conversations, friends, pendingRequests, refreshMessages, refreshConversations, refreshFriends, refreshPendingRequests]
|
|
8896
|
+
);
|
|
8897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatContext.Provider, { value, children });
|
|
8898
|
+
}
|
|
8899
|
+
function useChatContext() {
|
|
8900
|
+
const ctx = (0, import_react49.useContext)(ChatContext);
|
|
8901
|
+
if (!ctx) {
|
|
8902
|
+
throw new Error("useChatContext must be used inside a <ChatProvider>");
|
|
8903
|
+
}
|
|
8904
|
+
return ctx;
|
|
8905
|
+
}
|
|
8906
|
+
|
|
8907
|
+
// src/chat/hooks.ts
|
|
8908
|
+
var import_react50 = require("react");
|
|
8909
|
+
function useChatStatus() {
|
|
8910
|
+
return useChatContext().status;
|
|
8911
|
+
}
|
|
8912
|
+
function useChatMessages() {
|
|
8913
|
+
const { messages, refreshMessages } = useChatContext();
|
|
8914
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
8915
|
+
const refetch = (0, import_react50.useCallback)(async () => {
|
|
8916
|
+
setLoading(true);
|
|
8917
|
+
await refreshMessages();
|
|
8918
|
+
setLoading(false);
|
|
8919
|
+
}, [refreshMessages]);
|
|
8920
|
+
return { messages, loading, refetch };
|
|
8921
|
+
}
|
|
8922
|
+
function useSendMessage() {
|
|
8923
|
+
const { socket } = useChatContext();
|
|
8924
|
+
const { client } = useDubs();
|
|
8925
|
+
const send = (0, import_react50.useCallback)(
|
|
8926
|
+
(params) => {
|
|
8927
|
+
socket.sendMessage(params);
|
|
8928
|
+
},
|
|
8929
|
+
[socket]
|
|
8930
|
+
);
|
|
8931
|
+
const sendViaREST = (0, import_react50.useCallback)(
|
|
8932
|
+
async (params) => {
|
|
8933
|
+
await client.sendChatMessage(params);
|
|
8934
|
+
},
|
|
8935
|
+
[client]
|
|
8936
|
+
);
|
|
8937
|
+
return { send, sendViaREST };
|
|
8938
|
+
}
|
|
8939
|
+
function useOnlineUsers() {
|
|
8940
|
+
const { onlineUsers, onlineCount } = useChatContext();
|
|
8941
|
+
return { users: onlineUsers, count: onlineCount };
|
|
8942
|
+
}
|
|
8943
|
+
function useUnreadCount() {
|
|
8944
|
+
return useChatContext().unreadCount;
|
|
8945
|
+
}
|
|
8946
|
+
function useConversations() {
|
|
8947
|
+
const { conversations, refreshConversations } = useChatContext();
|
|
8948
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
8949
|
+
const refetch = (0, import_react50.useCallback)(async () => {
|
|
8950
|
+
setLoading(true);
|
|
8951
|
+
await refreshConversations();
|
|
8952
|
+
setLoading(false);
|
|
8953
|
+
}, [refreshConversations]);
|
|
8954
|
+
return { conversations, loading, refetch };
|
|
8955
|
+
}
|
|
8956
|
+
function useDirectMessages(recipientWallet) {
|
|
8957
|
+
const { client } = useDubs();
|
|
8958
|
+
const { socket, refreshConversations } = useChatContext();
|
|
8959
|
+
const [messages, setMessages] = (0, import_react50.useState)([]);
|
|
8960
|
+
const [otherUser, setOtherUser] = (0, import_react50.useState)(null);
|
|
8961
|
+
const [loading, setLoading] = (0, import_react50.useState)(true);
|
|
8962
|
+
const refetch = (0, import_react50.useCallback)(async () => {
|
|
8963
|
+
try {
|
|
8964
|
+
setLoading(true);
|
|
8965
|
+
const res = await client.getConversation(recipientWallet);
|
|
8966
|
+
setMessages(res.messages);
|
|
8967
|
+
setOtherUser(res.otherUser);
|
|
8968
|
+
} catch (err) {
|
|
8969
|
+
console.error("[Dubs:useDirectMessages] Error loading:", err);
|
|
8970
|
+
} finally {
|
|
8971
|
+
setLoading(false);
|
|
8972
|
+
}
|
|
8973
|
+
}, [client, recipientWallet]);
|
|
8974
|
+
(0, import_react50.useEffect)(() => {
|
|
8975
|
+
refetch();
|
|
8976
|
+
socket.joinDM(recipientWallet);
|
|
8977
|
+
return () => {
|
|
8978
|
+
socket.leaveDM(recipientWallet);
|
|
8979
|
+
};
|
|
8980
|
+
}, [recipientWallet, refetch, socket]);
|
|
8981
|
+
const socketRef = (0, import_react50.useRef)(socket);
|
|
8982
|
+
socketRef.current = socket;
|
|
8983
|
+
(0, import_react50.useEffect)(() => {
|
|
8984
|
+
const currentSocket = socketRef.current;
|
|
8985
|
+
const prevListeners = currentSocket.listeners;
|
|
8986
|
+
const originalOnDMNew = prevListeners?.onDMNewMessage;
|
|
8987
|
+
currentSocket.setListeners({
|
|
8988
|
+
...prevListeners,
|
|
8989
|
+
onDMNewMessage: (msg) => {
|
|
8990
|
+
originalOnDMNew?.(msg);
|
|
8991
|
+
if (msg.senderWallet === recipientWallet || msg.isOwn) {
|
|
8992
|
+
setMessages((prev) => {
|
|
8993
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
8994
|
+
return [...prev, msg];
|
|
8995
|
+
});
|
|
8996
|
+
}
|
|
8997
|
+
},
|
|
8998
|
+
onDMMessageSent: (msg) => {
|
|
8999
|
+
setMessages((prev) => {
|
|
9000
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
9001
|
+
return [...prev, { ...msg, isOwn: true }];
|
|
9002
|
+
});
|
|
9003
|
+
}
|
|
9004
|
+
});
|
|
9005
|
+
}, [recipientWallet]);
|
|
9006
|
+
const send = (0, import_react50.useCallback)(
|
|
9007
|
+
(message) => {
|
|
9008
|
+
socket.sendDM({ recipientWallet, message });
|
|
9009
|
+
},
|
|
9010
|
+
[socket, recipientWallet]
|
|
9011
|
+
);
|
|
9012
|
+
const sendViaREST = (0, import_react50.useCallback)(
|
|
9013
|
+
async (message) => {
|
|
9014
|
+
await client.sendDirectMessage({ recipientWallet, message });
|
|
9015
|
+
await refetch();
|
|
9016
|
+
await refreshConversations();
|
|
9017
|
+
},
|
|
9018
|
+
[client, recipientWallet, refetch, refreshConversations]
|
|
9019
|
+
);
|
|
9020
|
+
const markRead = (0, import_react50.useCallback)(() => {
|
|
9021
|
+
socket.markDMRead(recipientWallet);
|
|
9022
|
+
}, [socket, recipientWallet]);
|
|
9023
|
+
return { messages, loading, otherUser, send, sendViaREST, markRead, refetch };
|
|
9024
|
+
}
|
|
9025
|
+
function useFriends() {
|
|
9026
|
+
const { friends, refreshFriends } = useChatContext();
|
|
9027
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
9028
|
+
const refetch = (0, import_react50.useCallback)(async () => {
|
|
9029
|
+
setLoading(true);
|
|
9030
|
+
await refreshFriends();
|
|
9031
|
+
setLoading(false);
|
|
9032
|
+
}, [refreshFriends]);
|
|
9033
|
+
return { friends, loading, refetch };
|
|
9034
|
+
}
|
|
9035
|
+
function useFriendRequests() {
|
|
9036
|
+
const { pendingRequests, refreshPendingRequests } = useChatContext();
|
|
9037
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
9038
|
+
const refetch = (0, import_react50.useCallback)(async () => {
|
|
9039
|
+
setLoading(true);
|
|
9040
|
+
await refreshPendingRequests();
|
|
9041
|
+
setLoading(false);
|
|
9042
|
+
}, [refreshPendingRequests]);
|
|
9043
|
+
return { requests: pendingRequests, loading, refetch };
|
|
9044
|
+
}
|
|
9045
|
+
function useSearchUsers() {
|
|
9046
|
+
const { client } = useDubs();
|
|
9047
|
+
const [results, setResults] = (0, import_react50.useState)([]);
|
|
9048
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
9049
|
+
const search = (0, import_react50.useCallback)(
|
|
9050
|
+
async (query) => {
|
|
9051
|
+
setLoading(true);
|
|
9052
|
+
try {
|
|
9053
|
+
const res = await client.searchUsers(query);
|
|
9054
|
+
setResults(res.results);
|
|
9055
|
+
} catch (err) {
|
|
9056
|
+
console.error("[Dubs:useSearchUsers] Error:", err);
|
|
9057
|
+
} finally {
|
|
9058
|
+
setLoading(false);
|
|
9059
|
+
}
|
|
9060
|
+
},
|
|
9061
|
+
[client]
|
|
9062
|
+
);
|
|
9063
|
+
const clear = (0, import_react50.useCallback)(() => setResults([]), []);
|
|
9064
|
+
return { results, loading, search, clear };
|
|
9065
|
+
}
|
|
9066
|
+
function useSendFriendRequest() {
|
|
9067
|
+
const { client } = useDubs();
|
|
9068
|
+
const { refreshPendingRequests } = useChatContext();
|
|
9069
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
9070
|
+
const send = (0, import_react50.useCallback)(
|
|
9071
|
+
async (targetUserId) => {
|
|
9072
|
+
setLoading(true);
|
|
9073
|
+
try {
|
|
9074
|
+
await client.sendFriendRequest(targetUserId);
|
|
9075
|
+
} finally {
|
|
9076
|
+
setLoading(false);
|
|
9077
|
+
}
|
|
9078
|
+
},
|
|
9079
|
+
[client, refreshPendingRequests]
|
|
9080
|
+
);
|
|
9081
|
+
return { send, loading };
|
|
9082
|
+
}
|
|
9083
|
+
function useRespondToFriendRequest() {
|
|
9084
|
+
const { client } = useDubs();
|
|
9085
|
+
const { refreshFriends, refreshPendingRequests } = useChatContext();
|
|
9086
|
+
const [loading, setLoading] = (0, import_react50.useState)(false);
|
|
9087
|
+
const accept = (0, import_react50.useCallback)(
|
|
9088
|
+
async (requestId) => {
|
|
9089
|
+
setLoading(true);
|
|
9090
|
+
try {
|
|
9091
|
+
await client.acceptFriendRequest(requestId);
|
|
9092
|
+
await Promise.all([refreshFriends(), refreshPendingRequests()]);
|
|
9093
|
+
} finally {
|
|
9094
|
+
setLoading(false);
|
|
9095
|
+
}
|
|
9096
|
+
},
|
|
9097
|
+
[client, refreshFriends, refreshPendingRequests]
|
|
9098
|
+
);
|
|
9099
|
+
const reject = (0, import_react50.useCallback)(
|
|
9100
|
+
async (requestId) => {
|
|
9101
|
+
setLoading(true);
|
|
9102
|
+
try {
|
|
9103
|
+
await client.rejectFriendRequest(requestId);
|
|
9104
|
+
await refreshPendingRequests();
|
|
9105
|
+
} finally {
|
|
9106
|
+
setLoading(false);
|
|
9107
|
+
}
|
|
9108
|
+
},
|
|
9109
|
+
[client, refreshPendingRequests]
|
|
9110
|
+
);
|
|
9111
|
+
return { accept, reject, loading };
|
|
9112
|
+
}
|
|
7202
9113
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7203
9114
|
0 && (module.exports = {
|
|
7204
9115
|
ArcadeLeaderboardSheet,
|
|
7205
9116
|
AuthGate,
|
|
9117
|
+
ChatProvider,
|
|
9118
|
+
ChatSocket,
|
|
7206
9119
|
ClaimButton,
|
|
7207
9120
|
ClaimPrizeSheet,
|
|
7208
9121
|
ConnectWalletButton,
|
|
@@ -7216,6 +9129,9 @@ var styles20 = import_react_native26.StyleSheet.create({
|
|
|
7216
9129
|
DubsProvider,
|
|
7217
9130
|
EnterArcadePoolSheet,
|
|
7218
9131
|
GamePoster,
|
|
9132
|
+
JackpotCard,
|
|
9133
|
+
JackpotSheet,
|
|
9134
|
+
JackpotWidget,
|
|
7219
9135
|
JoinGameButton,
|
|
7220
9136
|
JoinGameSheet,
|
|
7221
9137
|
LivePoolsCard,
|
|
@@ -7244,22 +9160,38 @@ var styles20 = import_react_native26.StyleSheet.create({
|
|
|
7244
9160
|
useArcadePool,
|
|
7245
9161
|
useArcadePools,
|
|
7246
9162
|
useAuth,
|
|
9163
|
+
useChatContext,
|
|
9164
|
+
useChatMessages,
|
|
9165
|
+
useChatStatus,
|
|
7247
9166
|
useClaim,
|
|
9167
|
+
useConversations,
|
|
7248
9168
|
useCreateCustomGame,
|
|
7249
9169
|
useCreateGame,
|
|
9170
|
+
useDirectMessages,
|
|
7250
9171
|
useDubs,
|
|
7251
9172
|
useDubsTheme,
|
|
7252
9173
|
useEnterArcadePool,
|
|
9174
|
+
useEnterJackpot,
|
|
7253
9175
|
useEvents,
|
|
9176
|
+
useFriendRequests,
|
|
9177
|
+
useFriends,
|
|
7254
9178
|
useGame,
|
|
7255
9179
|
useGames,
|
|
7256
9180
|
useHasClaimed,
|
|
7257
9181
|
useHighlights,
|
|
9182
|
+
useJackpot,
|
|
9183
|
+
useJackpotHistory,
|
|
7258
9184
|
useJoinGame,
|
|
7259
9185
|
useNetworkGames,
|
|
9186
|
+
useOnlineUsers,
|
|
7260
9187
|
usePushNotifications,
|
|
9188
|
+
useRespondToFriendRequest,
|
|
9189
|
+
useSearchUsers,
|
|
9190
|
+
useSendFriendRequest,
|
|
9191
|
+
useSendMessage,
|
|
7261
9192
|
useShorts,
|
|
7262
9193
|
useUFCFightCard,
|
|
7263
|
-
useUFCFighterDetail
|
|
9194
|
+
useUFCFighterDetail,
|
|
9195
|
+
useUnreadCount
|
|
7264
9196
|
});
|
|
7265
9197
|
//# sourceMappingURL=index.js.map
|