@dimcool/sdk 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -7
- package/dist/index.cjs +430 -109
- package/dist/index.d.cts +610 -447
- package/dist/index.d.ts +610 -447
- package/dist/index.js +429 -109
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -696,6 +696,16 @@ var Auth = class {
|
|
|
696
696
|
this.logger.debug("Token stored in storage", { tokenKey: TOKEN_KEY });
|
|
697
697
|
return response;
|
|
698
698
|
}
|
|
699
|
+
async loginWithExternalSignature(address, signedMessage, options) {
|
|
700
|
+
const response = await this.http.post("/auth/login-wallet", {
|
|
701
|
+
signedMessage,
|
|
702
|
+
address,
|
|
703
|
+
referralCode: options?.referralCode,
|
|
704
|
+
walletMeta: options?.walletMeta
|
|
705
|
+
});
|
|
706
|
+
this.storage.set(TOKEN_KEY, response.access_token);
|
|
707
|
+
return response;
|
|
708
|
+
}
|
|
699
709
|
logout() {
|
|
700
710
|
this.logger.debug("Auth.logout called");
|
|
701
711
|
const hadToken = this.storage.get(TOKEN_KEY) !== null;
|
|
@@ -709,6 +719,10 @@ var Auth = class {
|
|
|
709
719
|
});
|
|
710
720
|
return isAuth;
|
|
711
721
|
}
|
|
722
|
+
async getSessionStats() {
|
|
723
|
+
this.logger.debug("Auth.getSessionStats called");
|
|
724
|
+
return this.http.get("/auth/sessions/stats");
|
|
725
|
+
}
|
|
712
726
|
async getLatestSessions(limit) {
|
|
713
727
|
this.logger.debug("Auth.getLatestSessions called", { limit });
|
|
714
728
|
const params = new URLSearchParams();
|
|
@@ -936,11 +950,25 @@ var Users = class {
|
|
|
936
950
|
async removeFriend(userId) {
|
|
937
951
|
return this.http.delete(`/friends/${userId}`);
|
|
938
952
|
}
|
|
939
|
-
async getIncomingFriendRequests() {
|
|
940
|
-
|
|
953
|
+
async getIncomingFriendRequests(opts) {
|
|
954
|
+
const params = new URLSearchParams();
|
|
955
|
+
if (opts?.limit !== void 0)
|
|
956
|
+
params.append("limit", opts.limit.toString());
|
|
957
|
+
if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
|
|
958
|
+
const qs = params.toString();
|
|
959
|
+
return this.http.get(
|
|
960
|
+
qs ? `/friends/requests/incoming?${qs}` : "/friends/requests/incoming"
|
|
961
|
+
);
|
|
941
962
|
}
|
|
942
|
-
async getOutgoingFriendRequests() {
|
|
943
|
-
|
|
963
|
+
async getOutgoingFriendRequests(opts) {
|
|
964
|
+
const params = new URLSearchParams();
|
|
965
|
+
if (opts?.limit !== void 0)
|
|
966
|
+
params.append("limit", opts.limit.toString());
|
|
967
|
+
if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
|
|
968
|
+
const qs = params.toString();
|
|
969
|
+
return this.http.get(
|
|
970
|
+
qs ? `/friends/requests/outgoing?${qs}` : "/friends/requests/outgoing"
|
|
971
|
+
);
|
|
944
972
|
}
|
|
945
973
|
async acceptFriendRequest(userId) {
|
|
946
974
|
return this.http.post(
|
|
@@ -1029,6 +1057,9 @@ var FeatureFlags = class {
|
|
|
1029
1057
|
this.loaded = true;
|
|
1030
1058
|
return this.flags;
|
|
1031
1059
|
}
|
|
1060
|
+
async getAdminFeatureFlags() {
|
|
1061
|
+
return this.http.get("/feature-flags/admin");
|
|
1062
|
+
}
|
|
1032
1063
|
isEnabledFlag(name) {
|
|
1033
1064
|
const flag = this.flags.find((f) => f.name === name);
|
|
1034
1065
|
return flag?.enabled ?? false;
|
|
@@ -1048,10 +1079,11 @@ var FeatureFlags = class {
|
|
|
1048
1079
|
}
|
|
1049
1080
|
return flag;
|
|
1050
1081
|
}
|
|
1051
|
-
async createFeatureFlag(name, enabled) {
|
|
1082
|
+
async createFeatureFlag(name, enabled, description) {
|
|
1052
1083
|
const flag = await this.http.post("/feature-flags", {
|
|
1053
1084
|
name,
|
|
1054
|
-
enabled
|
|
1085
|
+
enabled,
|
|
1086
|
+
...description !== void 0 && { description }
|
|
1055
1087
|
});
|
|
1056
1088
|
this.flags.push(flag);
|
|
1057
1089
|
return flag;
|
|
@@ -1064,11 +1096,17 @@ var Lobbies = class {
|
|
|
1064
1096
|
this.http = http;
|
|
1065
1097
|
this.logger = logger2;
|
|
1066
1098
|
}
|
|
1099
|
+
/** Called by SDK after the store is created so mutations can update state directly. */
|
|
1100
|
+
setLobbyStore(store) {
|
|
1101
|
+
this.lobbyStore = store;
|
|
1102
|
+
}
|
|
1067
1103
|
async createLobby(gameType, betAmount) {
|
|
1068
1104
|
return this.http.post("/lobbies", { gameType, betAmount });
|
|
1069
1105
|
}
|
|
1070
1106
|
async getLobby(lobbyId) {
|
|
1071
|
-
|
|
1107
|
+
const lobby = await this.http.get(`/lobbies/${lobbyId}`);
|
|
1108
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1109
|
+
return lobby;
|
|
1072
1110
|
}
|
|
1073
1111
|
async inviteFriend(lobbyId, friendId) {
|
|
1074
1112
|
return this.http.post(`/lobbies/${lobbyId}/invite`, {
|
|
@@ -1079,7 +1117,9 @@ var Lobbies = class {
|
|
|
1079
1117
|
return this.http.post(`/lobbies/${lobbyId}/accept-invite`, {});
|
|
1080
1118
|
}
|
|
1081
1119
|
async joinLobby(lobbyId) {
|
|
1082
|
-
|
|
1120
|
+
const lobby = await this.http.post(`/lobbies/${lobbyId}/join`, {});
|
|
1121
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1122
|
+
return lobby;
|
|
1083
1123
|
}
|
|
1084
1124
|
async removePlayer(lobbyId, userId) {
|
|
1085
1125
|
return this.http.delete(
|
|
@@ -1096,12 +1136,17 @@ var Lobbies = class {
|
|
|
1096
1136
|
return this.http.post(`/lobbies/${lobbyId}/join-queue`, {});
|
|
1097
1137
|
}
|
|
1098
1138
|
async cancelQueue(lobbyId) {
|
|
1099
|
-
|
|
1139
|
+
const lobby = await this.http.delete(`/lobbies/${lobbyId}/queue`);
|
|
1140
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1141
|
+
return lobby;
|
|
1100
1142
|
}
|
|
1101
1143
|
async updateBetAmount(lobbyId, betAmount) {
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1144
|
+
const lobby = await this.http.patch(
|
|
1145
|
+
`/lobbies/${lobbyId}/bet-amount`,
|
|
1146
|
+
{ betAmount }
|
|
1147
|
+
);
|
|
1148
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1149
|
+
return lobby;
|
|
1105
1150
|
}
|
|
1106
1151
|
async playSound(lobbyId, sound) {
|
|
1107
1152
|
return this.http.post(`/lobbies/${lobbyId}/sound`, {
|
|
@@ -1136,13 +1181,18 @@ var Lobbies = class {
|
|
|
1136
1181
|
};
|
|
1137
1182
|
|
|
1138
1183
|
// src/games.ts
|
|
1139
|
-
import { Transaction as Transaction2 } from "@solana/web3.js";
|
|
1140
1184
|
var Games = class {
|
|
1141
1185
|
constructor(http, wallet, logger2) {
|
|
1142
1186
|
this.http = http;
|
|
1143
1187
|
this.wallet = wallet;
|
|
1144
1188
|
this.logger = logger2;
|
|
1145
1189
|
}
|
|
1190
|
+
setGameStore(store) {
|
|
1191
|
+
this.gameStore = store;
|
|
1192
|
+
}
|
|
1193
|
+
setGameActionsStore(store) {
|
|
1194
|
+
this.gameActionsStore = store;
|
|
1195
|
+
}
|
|
1146
1196
|
async getAvailableGames() {
|
|
1147
1197
|
return this.http.get("/games/available");
|
|
1148
1198
|
}
|
|
@@ -1155,7 +1205,11 @@ var Games = class {
|
|
|
1155
1205
|
return this.http.get("/games/metrics");
|
|
1156
1206
|
}
|
|
1157
1207
|
async getGame(gameId) {
|
|
1158
|
-
|
|
1208
|
+
const existing = this.gameStore?.store.getState().gamesById[gameId];
|
|
1209
|
+
if (existing?.status === "completed") return existing;
|
|
1210
|
+
const game = await this.http.get(`/games/${gameId}`);
|
|
1211
|
+
this.gameStore?.setBaseState([game]);
|
|
1212
|
+
return game;
|
|
1159
1213
|
}
|
|
1160
1214
|
/**
|
|
1161
1215
|
* Get list of currently active (live) games. Public endpoint for spectating.
|
|
@@ -1182,7 +1236,13 @@ var Games = class {
|
|
|
1182
1236
|
* Get current game state with timer information
|
|
1183
1237
|
*/
|
|
1184
1238
|
async getGameState(gameId) {
|
|
1185
|
-
|
|
1239
|
+
const existing = this.gameActionsStore?.store.getState().statesByGameId[gameId];
|
|
1240
|
+
if (existing?.status === "completed") return existing;
|
|
1241
|
+
const state = await this.http.get(
|
|
1242
|
+
`/games/${gameId}/state`
|
|
1243
|
+
);
|
|
1244
|
+
this.gameActionsStore?.setBaseState(gameId, state);
|
|
1245
|
+
return state;
|
|
1186
1246
|
}
|
|
1187
1247
|
/**
|
|
1188
1248
|
* Request a rematch for a completed game
|
|
@@ -1218,8 +1278,18 @@ var Games = class {
|
|
|
1218
1278
|
{ amountMinor, signedTransaction }
|
|
1219
1279
|
);
|
|
1220
1280
|
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Confirm a donation that was already sent by the client (signAndSendTransaction path).
|
|
1283
|
+
*/
|
|
1284
|
+
async confirmGameDonationSignature(gameId, amountMinor, signature) {
|
|
1285
|
+
return this.http.post(
|
|
1286
|
+
`/games/${gameId}/donate/confirm-signature`,
|
|
1287
|
+
{ amountMinor, signature }
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1221
1290
|
/**
|
|
1222
1291
|
* One-call donation flow: prepare -> sign -> submit.
|
|
1292
|
+
* Automatically uses the right signing path (embedded vs injected wallet).
|
|
1223
1293
|
*/
|
|
1224
1294
|
async sendDonation(gameId, amountMinor) {
|
|
1225
1295
|
if (!this.wallet.hasSigner()) {
|
|
@@ -1228,16 +1298,10 @@ var Games = class {
|
|
|
1228
1298
|
);
|
|
1229
1299
|
}
|
|
1230
1300
|
const prepared = await this.prepareGameDonation(gameId, amountMinor);
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
);
|
|
1236
|
-
const result = await this.donateToGame(
|
|
1237
|
-
gameId,
|
|
1238
|
-
amountMinor,
|
|
1239
|
-
signedTransaction
|
|
1240
|
-
);
|
|
1301
|
+
const result = await this.wallet.signAndDispatch(prepared.transaction, {
|
|
1302
|
+
onSigned: (signedTxBase64) => this.donateToGame(gameId, amountMinor, signedTxBase64),
|
|
1303
|
+
onSignedAndSent: (sig) => this.confirmGameDonationSignature(gameId, amountMinor, sig)
|
|
1304
|
+
});
|
|
1241
1305
|
return {
|
|
1242
1306
|
...result,
|
|
1243
1307
|
escrowAddress: prepared.escrowAddress,
|
|
@@ -1336,6 +1400,9 @@ var Chat = class {
|
|
|
1336
1400
|
this.logger = logger2;
|
|
1337
1401
|
this.retryOptions = { ...DEFAULT_RETRY_OPTIONS, ...retryOptions };
|
|
1338
1402
|
}
|
|
1403
|
+
setDmThreadsStore(store) {
|
|
1404
|
+
this.dmThreadsStore = store;
|
|
1405
|
+
}
|
|
1339
1406
|
encodeContextId(id) {
|
|
1340
1407
|
return encodeURIComponent(id);
|
|
1341
1408
|
}
|
|
@@ -1417,7 +1484,9 @@ var Chat = class {
|
|
|
1417
1484
|
return response;
|
|
1418
1485
|
}
|
|
1419
1486
|
async listDmThreads() {
|
|
1420
|
-
|
|
1487
|
+
const threads = await this.http.get("/chat/dm/threads");
|
|
1488
|
+
this.dmThreadsStore?.setBaseState(threads);
|
|
1489
|
+
return threads;
|
|
1421
1490
|
}
|
|
1422
1491
|
async getDmThread(dmKey) {
|
|
1423
1492
|
return this.http.get(
|
|
@@ -1483,7 +1552,6 @@ var Challenges = class {
|
|
|
1483
1552
|
};
|
|
1484
1553
|
|
|
1485
1554
|
// src/tips.ts
|
|
1486
|
-
import { Transaction as Transaction3 } from "@solana/web3.js";
|
|
1487
1555
|
var Tips = class {
|
|
1488
1556
|
constructor(http, wallet, chat, logger2) {
|
|
1489
1557
|
this.http = http;
|
|
@@ -1510,21 +1578,32 @@ var Tips = class {
|
|
|
1510
1578
|
);
|
|
1511
1579
|
}
|
|
1512
1580
|
const { publicKey: senderAddress } = await this.wallet.loadWallet();
|
|
1513
|
-
const
|
|
1514
|
-
const
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
);
|
|
1519
|
-
const transfer = await this.wallet.
|
|
1520
|
-
signedTxBase64
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1581
|
+
const supportsPresign = !this.wallet.isSignAndSendMode();
|
|
1582
|
+
const prepared = await this.prepare({
|
|
1583
|
+
recipientUsername,
|
|
1584
|
+
amount,
|
|
1585
|
+
supportsPresign
|
|
1586
|
+
});
|
|
1587
|
+
const transfer = await this.wallet.signAndDispatch(prepared.transaction, {
|
|
1588
|
+
onSigned: (signedTxBase64) => this.wallet.submitTransfer(
|
|
1589
|
+
signedTxBase64,
|
|
1590
|
+
senderAddress,
|
|
1591
|
+
prepared.recipientAddress,
|
|
1592
|
+
prepared.amount,
|
|
1593
|
+
"USDC",
|
|
1594
|
+
false,
|
|
1595
|
+
prepared.recipientUsername
|
|
1596
|
+
),
|
|
1597
|
+
onSignedAndSent: (sig) => this.wallet.confirmTransferSignature(
|
|
1598
|
+
sig,
|
|
1599
|
+
senderAddress,
|
|
1600
|
+
prepared.recipientAddress,
|
|
1601
|
+
prepared.amount,
|
|
1602
|
+
"USDC",
|
|
1603
|
+
false,
|
|
1604
|
+
prepared.recipientUsername
|
|
1605
|
+
)
|
|
1606
|
+
});
|
|
1528
1607
|
const message = await this.chat.broadcastGlobalTip(
|
|
1529
1608
|
prepared.recipientUserId,
|
|
1530
1609
|
prepared.amount
|
|
@@ -1636,7 +1715,7 @@ var Achievements = class {
|
|
|
1636
1715
|
};
|
|
1637
1716
|
|
|
1638
1717
|
// src/wallet.ts
|
|
1639
|
-
import { Transaction as
|
|
1718
|
+
import { Transaction as Transaction2 } from "@solana/web3.js";
|
|
1640
1719
|
var TRANSFER_FEE_MINOR = 1e4;
|
|
1641
1720
|
var MIN_TRANSFER_AMOUNT = 5e4;
|
|
1642
1721
|
var MIN_SOL_TRANSFER_AMOUNT = 1e6;
|
|
@@ -1853,13 +1932,15 @@ var Wallet = class {
|
|
|
1853
1932
|
);
|
|
1854
1933
|
}
|
|
1855
1934
|
try {
|
|
1935
|
+
const supportsPresign = !this.isSignAndSendMode();
|
|
1856
1936
|
const response = await this.http.post(
|
|
1857
1937
|
"/wallets/transfer/prepare",
|
|
1858
1938
|
{
|
|
1859
1939
|
senderAddress,
|
|
1860
1940
|
recipient,
|
|
1861
1941
|
amount: amountMinor,
|
|
1862
|
-
token
|
|
1942
|
+
token,
|
|
1943
|
+
supportsPresign
|
|
1863
1944
|
}
|
|
1864
1945
|
);
|
|
1865
1946
|
this.logger.debug("Transfer prepared", {
|
|
@@ -1943,6 +2024,29 @@ var Wallet = class {
|
|
|
1943
2024
|
throw error;
|
|
1944
2025
|
}
|
|
1945
2026
|
}
|
|
2027
|
+
/**
|
|
2028
|
+
* Sign a prepared transaction and invoke the appropriate backend callback
|
|
2029
|
+
* based on the configured signer — without exposing the mode decision to callers.
|
|
2030
|
+
* - Embedded wallet (signAndSend): signs+sends, calls onSignedAndSent(signature)
|
|
2031
|
+
* - Injected wallet (signTransaction): signs locally, calls onSigned(signedTxBase64)
|
|
2032
|
+
*/
|
|
2033
|
+
async signAndDispatch(unsignedTxBase64, handlers) {
|
|
2034
|
+
if (!this.signer) {
|
|
2035
|
+
throw new Error(
|
|
2036
|
+
"No signer configured. Call setSigner() with a WalletSigner implementation first."
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
const unsignedTx = Transaction2.from(base64ToBytes(unsignedTxBase64));
|
|
2040
|
+
if (this.isSignAndSendMode()) {
|
|
2041
|
+
const sig = await this.signAndSendTransaction(unsignedTx);
|
|
2042
|
+
return handlers.onSignedAndSent(sig);
|
|
2043
|
+
}
|
|
2044
|
+
const signedTx = await this.signTransaction(unsignedTx);
|
|
2045
|
+
const signedBase64 = bytesToBase64(
|
|
2046
|
+
signedTx.serialize({ requireAllSignatures: false })
|
|
2047
|
+
);
|
|
2048
|
+
return handlers.onSigned(signedBase64);
|
|
2049
|
+
}
|
|
1946
2050
|
/**
|
|
1947
2051
|
* Full transfer flow in one call: prepare -> sign -> submit
|
|
1948
2052
|
* Recipient can be username, .sol domain, or Solana address (resolved by backend).
|
|
@@ -1959,7 +2063,7 @@ var Wallet = class {
|
|
|
1959
2063
|
amount,
|
|
1960
2064
|
token
|
|
1961
2065
|
);
|
|
1962
|
-
const unsignedTx =
|
|
2066
|
+
const unsignedTx = Transaction2.from(base64ToBytes(prepared.transaction));
|
|
1963
2067
|
let submitted;
|
|
1964
2068
|
if (this.isSignAndSendMode()) {
|
|
1965
2069
|
const signature = await this.signAndSendTransaction(unsignedTx);
|
|
@@ -1999,7 +2103,7 @@ var Wallet = class {
|
|
|
1999
2103
|
};
|
|
2000
2104
|
|
|
2001
2105
|
// src/escrow.ts
|
|
2002
|
-
import { Transaction as
|
|
2106
|
+
import { Transaction as Transaction3 } from "@solana/web3.js";
|
|
2003
2107
|
var Escrow = class {
|
|
2004
2108
|
constructor(http, wallet, logger2) {
|
|
2005
2109
|
this.http = http;
|
|
@@ -2027,12 +2131,32 @@ var Escrow = class {
|
|
|
2027
2131
|
* initializes depositStatus, and prepares the unsigned transaction in one call.
|
|
2028
2132
|
* Eliminates one HTTP round-trip vs startDeposits() + prepareDepositTransaction().
|
|
2029
2133
|
*/
|
|
2030
|
-
async prepareAndStartDeposit(lobbyId) {
|
|
2134
|
+
async prepareAndStartDeposit(lobbyId, supportsPresign) {
|
|
2135
|
+
const presign = supportsPresign ?? !this.wallet.isSignAndSendMode();
|
|
2031
2136
|
return this.http.post(
|
|
2032
2137
|
`/escrow/lobby/${lobbyId}/deposit/prepare-and-start`,
|
|
2033
|
-
{}
|
|
2138
|
+
{ supportsPresign: presign }
|
|
2034
2139
|
);
|
|
2035
2140
|
}
|
|
2141
|
+
/**
|
|
2142
|
+
* Sign and submit a prepared (unsigned) deposit transaction using the
|
|
2143
|
+
* configured signer. Automatically picks the right path:
|
|
2144
|
+
* - Embedded wallet: signAndSendTransaction → confirmDepositSignature
|
|
2145
|
+
* - Injected wallet: signTransaction → submitDeposit
|
|
2146
|
+
* Returns the on-chain signature.
|
|
2147
|
+
*/
|
|
2148
|
+
async signAndSubmitPreparedDeposit(lobbyId, unsignedTxBase64) {
|
|
2149
|
+
return this.wallet.signAndDispatch(unsignedTxBase64, {
|
|
2150
|
+
onSigned: async (signedTxBase64) => {
|
|
2151
|
+
const result = await this.submitDeposit(lobbyId, signedTxBase64);
|
|
2152
|
+
return result.signature;
|
|
2153
|
+
},
|
|
2154
|
+
onSignedAndSent: async (signature) => {
|
|
2155
|
+
await this.confirmDepositSignature(lobbyId, signature);
|
|
2156
|
+
return signature;
|
|
2157
|
+
}
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2036
2160
|
/**
|
|
2037
2161
|
* Submit a signed deposit transaction
|
|
2038
2162
|
* The transaction will be submitted to the Solana network and confirmed
|
|
@@ -2075,8 +2199,12 @@ var Escrow = class {
|
|
|
2075
2199
|
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2076
2200
|
);
|
|
2077
2201
|
}
|
|
2078
|
-
const
|
|
2079
|
-
const
|
|
2202
|
+
const supportsPresign = !this.wallet.isSignAndSendMode();
|
|
2203
|
+
const { transaction } = await this.prepareAndStartDeposit(
|
|
2204
|
+
lobbyId,
|
|
2205
|
+
supportsPresign
|
|
2206
|
+
);
|
|
2207
|
+
const unsignedTx = Transaction3.from(base64ToBytes(transaction));
|
|
2080
2208
|
let signature;
|
|
2081
2209
|
if (this.wallet.isSignAndSendMode()) {
|
|
2082
2210
|
signature = await this.wallet.signAndSendTransaction(unsignedTx);
|
|
@@ -2110,8 +2238,13 @@ var Escrow = class {
|
|
|
2110
2238
|
};
|
|
2111
2239
|
}
|
|
2112
2240
|
/**
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2241
|
+
* Deposit for a lobby and wait until the calling user's own deposit is confirmed.
|
|
2242
|
+
* Ideal for agents: returns as soon as your deposit is on-chain without waiting
|
|
2243
|
+
* for the other player. The server auto-joins the queue when all players deposit.
|
|
2244
|
+
*
|
|
2245
|
+
* Confirmation is handled asynchronously by the transaction queue processor.
|
|
2246
|
+
* This method polls the deposit status endpoint until the signature appears as
|
|
2247
|
+
* confirmed (up to 60 seconds).
|
|
2115
2248
|
*
|
|
2116
2249
|
* Automatically uses signAndSendTransaction or signTransaction based on signer capability.
|
|
2117
2250
|
*/
|
|
@@ -2121,26 +2254,45 @@ var Escrow = class {
|
|
|
2121
2254
|
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2122
2255
|
);
|
|
2123
2256
|
}
|
|
2124
|
-
const
|
|
2125
|
-
const
|
|
2257
|
+
const supportsPresign2 = !this.wallet.isSignAndSendMode();
|
|
2258
|
+
const { transaction } = await this.prepareAndStartDeposit(
|
|
2259
|
+
lobbyId,
|
|
2260
|
+
supportsPresign2
|
|
2261
|
+
);
|
|
2262
|
+
const unsignedTx = Transaction3.from(base64ToBytes(transaction));
|
|
2126
2263
|
let signature;
|
|
2127
2264
|
if (this.wallet.isSignAndSendMode()) {
|
|
2128
2265
|
signature = await this.wallet.signAndSendTransaction(unsignedTx);
|
|
2129
|
-
await this.
|
|
2130
|
-
`/escrow/lobby/${lobbyId}/deposit/confirm-signature?awaitConfirmation=true`,
|
|
2131
|
-
{ signature }
|
|
2132
|
-
);
|
|
2266
|
+
await this.confirmDepositSignature(lobbyId, signature);
|
|
2133
2267
|
} else {
|
|
2134
2268
|
const signedTx = await this.wallet.signTransaction(unsignedTx);
|
|
2135
2269
|
const signedBase64 = bytesToBase64(
|
|
2136
2270
|
signedTx.serialize({ requireAllSignatures: false })
|
|
2137
2271
|
);
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2272
|
+
const submitResult = await this.submitDeposit(lobbyId, signedBase64);
|
|
2273
|
+
signature = submitResult.signature;
|
|
2274
|
+
}
|
|
2275
|
+
const MAX_WAIT_MS = 6e4;
|
|
2276
|
+
const POLL_INTERVAL_MS = 1e3;
|
|
2277
|
+
const startTime = Date.now();
|
|
2278
|
+
while (Date.now() - startTime < MAX_WAIT_MS) {
|
|
2279
|
+
const status = await this.getDepositStatus(lobbyId);
|
|
2280
|
+
const myDeposit = status.deposits.find(
|
|
2281
|
+
(d) => d.transactionHash === signature
|
|
2282
|
+
);
|
|
2283
|
+
if (myDeposit?.status === "confirmed") {
|
|
2284
|
+
return {
|
|
2285
|
+
signature,
|
|
2286
|
+
status: "confirmed",
|
|
2287
|
+
canProceedToQueue: status.canProceedToQueue
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
if (status.allConfirmed && status.canProceedToQueue) {
|
|
2291
|
+
return { signature, status: "confirmed", canProceedToQueue: true };
|
|
2292
|
+
}
|
|
2293
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
2142
2294
|
}
|
|
2143
|
-
return { signature, status: "
|
|
2295
|
+
return { signature, status: "pending", canProceedToQueue: false };
|
|
2144
2296
|
}
|
|
2145
2297
|
async claimLobbyDepositRefund(lobbyId, depositSignature) {
|
|
2146
2298
|
return this.http.post(
|
|
@@ -2496,9 +2648,10 @@ var Support = class {
|
|
|
2496
2648
|
|
|
2497
2649
|
// src/markets.ts
|
|
2498
2650
|
var Markets = class {
|
|
2499
|
-
constructor(http, logger2) {
|
|
2651
|
+
constructor(http, logger2, wallet) {
|
|
2500
2652
|
this.http = http;
|
|
2501
2653
|
this.logger = logger2;
|
|
2654
|
+
this.wallet = wallet;
|
|
2502
2655
|
}
|
|
2503
2656
|
/**
|
|
2504
2657
|
* Get the prediction market state for a game.
|
|
@@ -2540,6 +2693,35 @@ var Markets = class {
|
|
|
2540
2693
|
{ signedTransaction, outcomeId, amountMinor }
|
|
2541
2694
|
);
|
|
2542
2695
|
}
|
|
2696
|
+
/**
|
|
2697
|
+
* Confirm a buy order that was already broadcast by the client (signAndSendTransaction path).
|
|
2698
|
+
*/
|
|
2699
|
+
async confirmBuyOrderSignature(gameId, depositSignature, outcomeId, amountMinor) {
|
|
2700
|
+
return this.http.post(
|
|
2701
|
+
`/games/${gameId}/market/orders/buy/confirm-signature`,
|
|
2702
|
+
{ depositSignature, outcomeId, amountMinor }
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* One-call buy order: prepare → sign → submit, automatically choosing
|
|
2707
|
+
* the right signing path (embedded vs injected wallet).
|
|
2708
|
+
*/
|
|
2709
|
+
async buy(gameId, outcomeId, amountMinor) {
|
|
2710
|
+
if (!this.wallet?.hasSigner()) {
|
|
2711
|
+
throw new Error(
|
|
2712
|
+
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
const { transaction } = await this.prepareBuyOrder(
|
|
2716
|
+
gameId,
|
|
2717
|
+
outcomeId,
|
|
2718
|
+
amountMinor
|
|
2719
|
+
);
|
|
2720
|
+
return this.wallet.signAndDispatch(transaction, {
|
|
2721
|
+
onSigned: (signedTxBase64) => this.submitBuyOrder(gameId, signedTxBase64, outcomeId, amountMinor),
|
|
2722
|
+
onSignedAndSent: (sig) => this.confirmBuyOrderSignature(gameId, sig, outcomeId, amountMinor)
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2543
2725
|
/**
|
|
2544
2726
|
* Sell shares back to the AMM pool.
|
|
2545
2727
|
* @param gameId - The game ID
|
|
@@ -2589,6 +2771,22 @@ var Markets = class {
|
|
|
2589
2771
|
}
|
|
2590
2772
|
};
|
|
2591
2773
|
|
|
2774
|
+
// src/analytics.ts
|
|
2775
|
+
var NoopAnalyticsClient = class {
|
|
2776
|
+
userLoggedIn(_user, _meta) {
|
|
2777
|
+
}
|
|
2778
|
+
userLoggedOut() {
|
|
2779
|
+
}
|
|
2780
|
+
sessionRestored(_user) {
|
|
2781
|
+
}
|
|
2782
|
+
track(_event, _properties) {
|
|
2783
|
+
}
|
|
2784
|
+
setUserProperties(_properties) {
|
|
2785
|
+
}
|
|
2786
|
+
group(_groupType, _groupKey, _properties) {
|
|
2787
|
+
}
|
|
2788
|
+
};
|
|
2789
|
+
|
|
2592
2790
|
// src/ws/standalone-transport.ts
|
|
2593
2791
|
import { io } from "socket.io-client";
|
|
2594
2792
|
|
|
@@ -2682,22 +2880,35 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2682
2880
|
this.accessToken = null;
|
|
2683
2881
|
this.reconnectAttempts = 0;
|
|
2684
2882
|
this.reconnectTimer = null;
|
|
2685
|
-
this.
|
|
2686
|
-
this.
|
|
2687
|
-
this.reconnectDelay = 1e3;
|
|
2688
|
-
this.reconnectDelayMax = 3e4;
|
|
2689
|
-
// 5 minutes
|
|
2883
|
+
this.needsReconnect = false;
|
|
2884
|
+
this.visibilityHandler = null;
|
|
2690
2885
|
this.wildcardHandlers = /* @__PURE__ */ new Set();
|
|
2691
2886
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
2692
2887
|
this.registeredEvents = /* @__PURE__ */ new Set();
|
|
2693
2888
|
this.wildcardRegistered = false;
|
|
2694
2889
|
this.url = url;
|
|
2890
|
+
if (typeof document !== "undefined") {
|
|
2891
|
+
this.visibilityHandler = () => {
|
|
2892
|
+
if (document.visibilityState === "visible" && !this.connectionState.connected) {
|
|
2893
|
+
this.reconnectImmediately();
|
|
2894
|
+
}
|
|
2895
|
+
};
|
|
2896
|
+
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
2897
|
+
}
|
|
2695
2898
|
}
|
|
2696
2899
|
connect() {
|
|
2900
|
+
if (this.reconnectTimer !== null) {
|
|
2901
|
+
clearTimeout(this.reconnectTimer);
|
|
2902
|
+
this.reconnectTimer = null;
|
|
2903
|
+
}
|
|
2904
|
+
this.reconnectAttempts = 0;
|
|
2697
2905
|
this.ensureSocket();
|
|
2698
2906
|
}
|
|
2699
2907
|
disconnect() {
|
|
2700
|
-
this.
|
|
2908
|
+
if (this.visibilityHandler && typeof document !== "undefined") {
|
|
2909
|
+
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
2910
|
+
this.visibilityHandler = null;
|
|
2911
|
+
}
|
|
2701
2912
|
if (!this.socket) return;
|
|
2702
2913
|
this.socket.disconnect();
|
|
2703
2914
|
this.socket = null;
|
|
@@ -2796,13 +3007,13 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2796
3007
|
reconnection: false
|
|
2797
3008
|
});
|
|
2798
3009
|
socket.on("connect", () => {
|
|
2799
|
-
this.clearPeriodicReconnect();
|
|
2800
3010
|
this.updateConnectionState({
|
|
2801
3011
|
connected: true,
|
|
2802
3012
|
connecting: false,
|
|
2803
3013
|
error: null
|
|
2804
3014
|
});
|
|
2805
|
-
const wasReconnect = this.
|
|
3015
|
+
const wasReconnect = this.needsReconnect;
|
|
3016
|
+
this.needsReconnect = false;
|
|
2806
3017
|
this.reconnectAttempts = 0;
|
|
2807
3018
|
this.onReconnect();
|
|
2808
3019
|
if (wasReconnect) {
|
|
@@ -2813,6 +3024,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2813
3024
|
});
|
|
2814
3025
|
socket.on("disconnect", (reason) => {
|
|
2815
3026
|
this.updateConnectionState({ connected: false, connecting: false });
|
|
3027
|
+
this.needsReconnect = true;
|
|
2816
3028
|
this.clearSocketForReconnect();
|
|
2817
3029
|
if (reason === "io server disconnect") {
|
|
2818
3030
|
this.handleAuthFailure("io server disconnect");
|
|
@@ -2822,6 +3034,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2822
3034
|
});
|
|
2823
3035
|
socket.on("connect_error", (error) => {
|
|
2824
3036
|
const message = error?.message || "connect_error";
|
|
3037
|
+
this.needsReconnect = true;
|
|
2825
3038
|
this.clearSocketForReconnect();
|
|
2826
3039
|
if (message.includes("unauthorized") || message.includes("401")) {
|
|
2827
3040
|
this.handleAuthFailure(message);
|
|
@@ -2849,31 +3062,31 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2849
3062
|
this.socket.removeAllListeners();
|
|
2850
3063
|
this.socket = null;
|
|
2851
3064
|
}
|
|
2852
|
-
|
|
2853
|
-
if (this.
|
|
2854
|
-
|
|
2855
|
-
this.
|
|
3065
|
+
reconnectImmediately() {
|
|
3066
|
+
if (this.reconnectTimer !== null) {
|
|
3067
|
+
clearTimeout(this.reconnectTimer);
|
|
3068
|
+
this.reconnectTimer = null;
|
|
2856
3069
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
if (this.periodicReconnectInterval !== null) return;
|
|
2860
|
-
this.periodicReconnectInterval = setInterval(() => {
|
|
2861
|
-
if (this.connectionState.connected) return;
|
|
2862
|
-
this.reconnectAttempts = 0;
|
|
2863
|
-
this.ensureSocket();
|
|
2864
|
-
}, _StandaloneWsTransport.PERIODIC_RECONNECT_MS);
|
|
3070
|
+
this.reconnectAttempts = 0;
|
|
3071
|
+
this.ensureSocket();
|
|
2865
3072
|
}
|
|
2866
3073
|
scheduleReconnect() {
|
|
2867
3074
|
if (this.reconnectTimer !== null) return;
|
|
2868
|
-
|
|
2869
|
-
this.startPeriodicReconnect();
|
|
2870
|
-
return;
|
|
2871
|
-
}
|
|
2872
|
-
const delay = Math.min(
|
|
2873
|
-
this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
|
|
2874
|
-
this.reconnectDelayMax
|
|
2875
|
-
);
|
|
3075
|
+
const attempt = this.reconnectAttempts;
|
|
2876
3076
|
this.reconnectAttempts += 1;
|
|
3077
|
+
let delay;
|
|
3078
|
+
if (attempt < _StandaloneWsTransport.FAST_RETRY_LIMIT) {
|
|
3079
|
+
delay = _StandaloneWsTransport.FAST_RETRY_DELAY_MS;
|
|
3080
|
+
} else {
|
|
3081
|
+
const backoffAttempt = attempt - _StandaloneWsTransport.FAST_RETRY_LIMIT;
|
|
3082
|
+
delay = Math.min(
|
|
3083
|
+
_StandaloneWsTransport.FAST_RETRY_DELAY_MS * Math.pow(2, backoffAttempt),
|
|
3084
|
+
_StandaloneWsTransport.MAX_BACKOFF_MS
|
|
3085
|
+
);
|
|
3086
|
+
if (attempt === _StandaloneWsTransport.FAST_RETRY_LIMIT) {
|
|
3087
|
+
this.dispatchEvent("connection:slow-retry", { timestamp: Date.now() });
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
2877
3090
|
this.reconnectTimer = setTimeout(() => {
|
|
2878
3091
|
this.reconnectTimer = null;
|
|
2879
3092
|
this.ensureSocket();
|
|
@@ -2934,7 +3147,9 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2934
3147
|
this.wildcardRegistered = true;
|
|
2935
3148
|
}
|
|
2936
3149
|
};
|
|
2937
|
-
_StandaloneWsTransport.
|
|
3150
|
+
_StandaloneWsTransport.FAST_RETRY_LIMIT = 60;
|
|
3151
|
+
_StandaloneWsTransport.FAST_RETRY_DELAY_MS = 1e3;
|
|
3152
|
+
_StandaloneWsTransport.MAX_BACKOFF_MS = 3e4;
|
|
2938
3153
|
var StandaloneWsTransport = _StandaloneWsTransport;
|
|
2939
3154
|
|
|
2940
3155
|
// src/stores/store-utils.ts
|
|
@@ -2961,14 +3176,16 @@ function createLobbyStore(transport) {
|
|
|
2961
3176
|
depositStatusByLobbyId: {}
|
|
2962
3177
|
});
|
|
2963
3178
|
const setBaseState = (lobbies) => {
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
3179
|
+
store.updateState((state) => {
|
|
3180
|
+
const lobbiesById = { ...state.lobbiesById };
|
|
3181
|
+
for (const lobby of lobbies) {
|
|
3182
|
+
const existing = lobbiesById[lobby.id];
|
|
3183
|
+
if (!existing || lobby.updatedAt >= existing.updatedAt) {
|
|
3184
|
+
lobbiesById[lobby.id] = lobby;
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
return { ...state, lobbiesById };
|
|
3188
|
+
});
|
|
2972
3189
|
};
|
|
2973
3190
|
const applyWsEvent = (event) => {
|
|
2974
3191
|
switch (event.event) {
|
|
@@ -3100,12 +3317,23 @@ function createGameStore(transport) {
|
|
|
3100
3317
|
gamesById: {},
|
|
3101
3318
|
spectatorCounts: {}
|
|
3102
3319
|
});
|
|
3320
|
+
const STATUS_RANK = {
|
|
3321
|
+
active: 0,
|
|
3322
|
+
completed: 1,
|
|
3323
|
+
abandoned: 1
|
|
3324
|
+
};
|
|
3103
3325
|
const setBaseState = (games) => {
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3326
|
+
store.updateState((state) => {
|
|
3327
|
+
const gamesById = { ...state.gamesById };
|
|
3328
|
+
for (const game of games) {
|
|
3329
|
+
const existing = gamesById[game.gameId];
|
|
3330
|
+
if (existing && STATUS_RANK[existing.status] > STATUS_RANK[game.status]) {
|
|
3331
|
+
continue;
|
|
3332
|
+
}
|
|
3333
|
+
gamesById[game.gameId] = game;
|
|
3334
|
+
}
|
|
3335
|
+
return { ...state, gamesById };
|
|
3336
|
+
});
|
|
3109
3337
|
};
|
|
3110
3338
|
const applyWsEvent = (event) => {
|
|
3111
3339
|
switch (event.event) {
|
|
@@ -3851,7 +4079,38 @@ function createNotificationsStore() {
|
|
|
3851
4079
|
appNotifications: []
|
|
3852
4080
|
}));
|
|
3853
4081
|
};
|
|
3854
|
-
|
|
4082
|
+
const markAsRead = (id) => {
|
|
4083
|
+
store.updateState((state) => ({
|
|
4084
|
+
...state,
|
|
4085
|
+
appNotifications: state.appNotifications.map(
|
|
4086
|
+
(n) => n.id === id ? { ...n, read: true } : n
|
|
4087
|
+
)
|
|
4088
|
+
}));
|
|
4089
|
+
};
|
|
4090
|
+
const markAllAsRead = () => {
|
|
4091
|
+
store.updateState((state) => ({
|
|
4092
|
+
...state,
|
|
4093
|
+
appNotifications: state.appNotifications.map((n) => ({
|
|
4094
|
+
...n,
|
|
4095
|
+
read: true
|
|
4096
|
+
}))
|
|
4097
|
+
}));
|
|
4098
|
+
};
|
|
4099
|
+
const dismiss = (id) => {
|
|
4100
|
+
store.updateState((state) => ({
|
|
4101
|
+
...state,
|
|
4102
|
+
appNotifications: state.appNotifications.filter((n) => n.id !== id)
|
|
4103
|
+
}));
|
|
4104
|
+
};
|
|
4105
|
+
return {
|
|
4106
|
+
store,
|
|
4107
|
+
applyWsEvent,
|
|
4108
|
+
setListFromApi,
|
|
4109
|
+
clear,
|
|
4110
|
+
markAsRead,
|
|
4111
|
+
markAllAsRead,
|
|
4112
|
+
dismiss
|
|
4113
|
+
};
|
|
3855
4114
|
}
|
|
3856
4115
|
|
|
3857
4116
|
// src/stores/friends-store.ts
|
|
@@ -4208,6 +4467,7 @@ var SDK = class {
|
|
|
4208
4467
|
constructor(config) {
|
|
4209
4468
|
const baseUrl = config.baseUrl || "http://localhost:3000";
|
|
4210
4469
|
const logger2 = config.logger || logger;
|
|
4470
|
+
this.analytics = config.analytics ?? new NoopAnalyticsClient();
|
|
4211
4471
|
this.http = config.httpClient || new HttpClient(
|
|
4212
4472
|
baseUrl,
|
|
4213
4473
|
config.storage,
|
|
@@ -4240,14 +4500,18 @@ var SDK = class {
|
|
|
4240
4500
|
this.referrals = new Referrals(this.http, logger2);
|
|
4241
4501
|
this.reports = new Reports(this.http, logger2);
|
|
4242
4502
|
this.support = new Support(this.http, logger2);
|
|
4243
|
-
this.markets = new Markets(this.http, logger2);
|
|
4503
|
+
this.markets = new Markets(this.http, logger2, this.wallet);
|
|
4244
4504
|
this.wsTransport = config.wsTransport || new StandaloneWsTransport(baseUrl);
|
|
4245
4505
|
this.wsTransport.setAppId(config.appId);
|
|
4246
4506
|
this.lobbyStore = createLobbyStore(this.wsTransport);
|
|
4507
|
+
this.lobbies.setLobbyStore(this.lobbyStore);
|
|
4247
4508
|
this.gameStore = createGameStore(this.wsTransport);
|
|
4509
|
+
this.games.setGameStore(this.gameStore);
|
|
4248
4510
|
this.gameActionsStore = createGameActionsStore(this.wsTransport);
|
|
4511
|
+
this.games.setGameActionsStore(this.gameActionsStore);
|
|
4249
4512
|
this.chatStore = createChatStore(this.wsTransport);
|
|
4250
4513
|
this.dmThreadsStore = createDmThreadsStore();
|
|
4514
|
+
this.chat.setDmThreadsStore(this.dmThreadsStore);
|
|
4251
4515
|
this.notificationsStore = createNotificationsStore();
|
|
4252
4516
|
this.friendsStore = createFriendsStore();
|
|
4253
4517
|
this.notifications = new Notifications(
|
|
@@ -4277,6 +4541,29 @@ var SDK = class {
|
|
|
4277
4541
|
this.wsTransport.connect();
|
|
4278
4542
|
await this.wsTransport.waitUntilConnected(timeoutMs);
|
|
4279
4543
|
}
|
|
4544
|
+
/**
|
|
4545
|
+
* Handle the full deposit-to-queue lifecycle for a lobby.
|
|
4546
|
+
*
|
|
4547
|
+
* After the deposit is confirmed, the backend may not have processed the
|
|
4548
|
+
* `lobby.deposit.allConfirmed` event yet, so the lobby can still be in
|
|
4549
|
+
* 'preparing' status. This method re-fetches the lobby and explicitly
|
|
4550
|
+
* joins the queue if needed, then pushes the latest state to the store
|
|
4551
|
+
* so the UI transitions immediately.
|
|
4552
|
+
*/
|
|
4553
|
+
async depositAndJoinQueue(lobbyId) {
|
|
4554
|
+
const result = await this.escrow.depositForLobby(lobbyId);
|
|
4555
|
+
if (!result.canProceedToQueue) {
|
|
4556
|
+
const lobby2 = await this.lobbies.getLobby(lobbyId);
|
|
4557
|
+
this.lobbyStore.setBaseState([lobby2]);
|
|
4558
|
+
return { ...result, lobby: lobby2 };
|
|
4559
|
+
}
|
|
4560
|
+
let lobby = await this.lobbies.getLobby(lobbyId);
|
|
4561
|
+
if (lobby.status === "preparing") {
|
|
4562
|
+
lobby = await this.lobbies.joinQueue(lobbyId);
|
|
4563
|
+
}
|
|
4564
|
+
this.lobbyStore.setBaseState([lobby]);
|
|
4565
|
+
return { ...result, lobby };
|
|
4566
|
+
}
|
|
4280
4567
|
};
|
|
4281
4568
|
|
|
4282
4569
|
// ../ws-shared-worker/dist/protocol.js
|
|
@@ -4384,6 +4671,26 @@ var SharedWorkerClient = class {
|
|
|
4384
4671
|
}
|
|
4385
4672
|
}
|
|
4386
4673
|
}
|
|
4674
|
+
/**
|
|
4675
|
+
* Dispatch a synthetic local event directly to all registered handlers for
|
|
4676
|
+
* that event name (and wildcard handlers), without sending anything over the
|
|
4677
|
+
* wire. Used by SharedWorkerTransport to fire synthetic events like
|
|
4678
|
+
* `connection:reconnected` that originate from transport-layer logic rather
|
|
4679
|
+
* than from the server.
|
|
4680
|
+
*/
|
|
4681
|
+
dispatchLocalEvent(eventName, payload) {
|
|
4682
|
+
const handlers = this.eventHandlers.get(eventName);
|
|
4683
|
+
if (handlers) {
|
|
4684
|
+
for (const handler of handlers) {
|
|
4685
|
+
handler(payload);
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
if (this.wildcardHandlers.size > 0) {
|
|
4689
|
+
for (const handler of this.wildcardHandlers) {
|
|
4690
|
+
handler(eventName, payload);
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4387
4694
|
postMessage(command) {
|
|
4388
4695
|
this.port.postMessage(command);
|
|
4389
4696
|
}
|
|
@@ -4393,6 +4700,10 @@ var SharedWorkerClient = class {
|
|
|
4393
4700
|
var SharedWorkerTransport = class extends BaseWsTransport {
|
|
4394
4701
|
constructor(workerUrl, socketUrl) {
|
|
4395
4702
|
super();
|
|
4703
|
+
/** Tracks whether a successful connection has been established at least once,
|
|
4704
|
+
* so that subsequent ws_open events are treated as reconnects and the
|
|
4705
|
+
* `connection:reconnected` event is dispatched to subscribers. */
|
|
4706
|
+
this.hasConnectedBefore = false;
|
|
4396
4707
|
this.client = new SharedWorkerClient(workerUrl);
|
|
4397
4708
|
this.url = socketUrl;
|
|
4398
4709
|
this.client.onMessage((event) => this.handleWorkerMessage(event));
|
|
@@ -4433,14 +4744,22 @@ var SharedWorkerTransport = class extends BaseWsTransport {
|
|
|
4433
4744
|
}
|
|
4434
4745
|
handleWorkerMessage(event) {
|
|
4435
4746
|
switch (event.type) {
|
|
4436
|
-
case "ws_open":
|
|
4747
|
+
case "ws_open": {
|
|
4748
|
+
const wasReconnect = this.hasConnectedBefore;
|
|
4749
|
+
this.hasConnectedBefore = true;
|
|
4437
4750
|
this.updateConnectionState({
|
|
4438
4751
|
connected: true,
|
|
4439
4752
|
connecting: false,
|
|
4440
4753
|
error: null
|
|
4441
4754
|
});
|
|
4442
4755
|
this.onReconnect();
|
|
4756
|
+
if (wasReconnect) {
|
|
4757
|
+
this.client.dispatchLocalEvent("connection:reconnected", {
|
|
4758
|
+
timestamp: Date.now()
|
|
4759
|
+
});
|
|
4760
|
+
}
|
|
4443
4761
|
break;
|
|
4762
|
+
}
|
|
4444
4763
|
case "ws_close":
|
|
4445
4764
|
this.updateConnectionState({
|
|
4446
4765
|
connected: false,
|
|
@@ -4479,6 +4798,7 @@ export {
|
|
|
4479
4798
|
MIN_TRANSFER_AMOUNT,
|
|
4480
4799
|
Markets,
|
|
4481
4800
|
NodeStorage,
|
|
4801
|
+
NoopAnalyticsClient,
|
|
4482
4802
|
Referrals,
|
|
4483
4803
|
Reports,
|
|
4484
4804
|
SDK,
|