@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.cjs
CHANGED
|
@@ -214,6 +214,7 @@ __export(index_exports, {
|
|
|
214
214
|
MIN_TRANSFER_AMOUNT: () => MIN_TRANSFER_AMOUNT,
|
|
215
215
|
Markets: () => Markets,
|
|
216
216
|
NodeStorage: () => NodeStorage,
|
|
217
|
+
NoopAnalyticsClient: () => NoopAnalyticsClient,
|
|
217
218
|
Referrals: () => Referrals,
|
|
218
219
|
Reports: () => Reports,
|
|
219
220
|
SDK: () => SDK,
|
|
@@ -748,6 +749,16 @@ var Auth = class {
|
|
|
748
749
|
this.logger.debug("Token stored in storage", { tokenKey: TOKEN_KEY });
|
|
749
750
|
return response;
|
|
750
751
|
}
|
|
752
|
+
async loginWithExternalSignature(address, signedMessage, options) {
|
|
753
|
+
const response = await this.http.post("/auth/login-wallet", {
|
|
754
|
+
signedMessage,
|
|
755
|
+
address,
|
|
756
|
+
referralCode: options?.referralCode,
|
|
757
|
+
walletMeta: options?.walletMeta
|
|
758
|
+
});
|
|
759
|
+
this.storage.set(TOKEN_KEY, response.access_token);
|
|
760
|
+
return response;
|
|
761
|
+
}
|
|
751
762
|
logout() {
|
|
752
763
|
this.logger.debug("Auth.logout called");
|
|
753
764
|
const hadToken = this.storage.get(TOKEN_KEY) !== null;
|
|
@@ -761,6 +772,10 @@ var Auth = class {
|
|
|
761
772
|
});
|
|
762
773
|
return isAuth;
|
|
763
774
|
}
|
|
775
|
+
async getSessionStats() {
|
|
776
|
+
this.logger.debug("Auth.getSessionStats called");
|
|
777
|
+
return this.http.get("/auth/sessions/stats");
|
|
778
|
+
}
|
|
764
779
|
async getLatestSessions(limit) {
|
|
765
780
|
this.logger.debug("Auth.getLatestSessions called", { limit });
|
|
766
781
|
const params = new URLSearchParams();
|
|
@@ -988,11 +1003,25 @@ var Users = class {
|
|
|
988
1003
|
async removeFriend(userId) {
|
|
989
1004
|
return this.http.delete(`/friends/${userId}`);
|
|
990
1005
|
}
|
|
991
|
-
async getIncomingFriendRequests() {
|
|
992
|
-
|
|
1006
|
+
async getIncomingFriendRequests(opts) {
|
|
1007
|
+
const params = new URLSearchParams();
|
|
1008
|
+
if (opts?.limit !== void 0)
|
|
1009
|
+
params.append("limit", opts.limit.toString());
|
|
1010
|
+
if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
|
|
1011
|
+
const qs = params.toString();
|
|
1012
|
+
return this.http.get(
|
|
1013
|
+
qs ? `/friends/requests/incoming?${qs}` : "/friends/requests/incoming"
|
|
1014
|
+
);
|
|
993
1015
|
}
|
|
994
|
-
async getOutgoingFriendRequests() {
|
|
995
|
-
|
|
1016
|
+
async getOutgoingFriendRequests(opts) {
|
|
1017
|
+
const params = new URLSearchParams();
|
|
1018
|
+
if (opts?.limit !== void 0)
|
|
1019
|
+
params.append("limit", opts.limit.toString());
|
|
1020
|
+
if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
|
|
1021
|
+
const qs = params.toString();
|
|
1022
|
+
return this.http.get(
|
|
1023
|
+
qs ? `/friends/requests/outgoing?${qs}` : "/friends/requests/outgoing"
|
|
1024
|
+
);
|
|
996
1025
|
}
|
|
997
1026
|
async acceptFriendRequest(userId) {
|
|
998
1027
|
return this.http.post(
|
|
@@ -1081,6 +1110,9 @@ var FeatureFlags = class {
|
|
|
1081
1110
|
this.loaded = true;
|
|
1082
1111
|
return this.flags;
|
|
1083
1112
|
}
|
|
1113
|
+
async getAdminFeatureFlags() {
|
|
1114
|
+
return this.http.get("/feature-flags/admin");
|
|
1115
|
+
}
|
|
1084
1116
|
isEnabledFlag(name) {
|
|
1085
1117
|
const flag = this.flags.find((f) => f.name === name);
|
|
1086
1118
|
return flag?.enabled ?? false;
|
|
@@ -1100,10 +1132,11 @@ var FeatureFlags = class {
|
|
|
1100
1132
|
}
|
|
1101
1133
|
return flag;
|
|
1102
1134
|
}
|
|
1103
|
-
async createFeatureFlag(name, enabled) {
|
|
1135
|
+
async createFeatureFlag(name, enabled, description) {
|
|
1104
1136
|
const flag = await this.http.post("/feature-flags", {
|
|
1105
1137
|
name,
|
|
1106
|
-
enabled
|
|
1138
|
+
enabled,
|
|
1139
|
+
...description !== void 0 && { description }
|
|
1107
1140
|
});
|
|
1108
1141
|
this.flags.push(flag);
|
|
1109
1142
|
return flag;
|
|
@@ -1116,11 +1149,17 @@ var Lobbies = class {
|
|
|
1116
1149
|
this.http = http;
|
|
1117
1150
|
this.logger = logger2;
|
|
1118
1151
|
}
|
|
1152
|
+
/** Called by SDK after the store is created so mutations can update state directly. */
|
|
1153
|
+
setLobbyStore(store) {
|
|
1154
|
+
this.lobbyStore = store;
|
|
1155
|
+
}
|
|
1119
1156
|
async createLobby(gameType, betAmount) {
|
|
1120
1157
|
return this.http.post("/lobbies", { gameType, betAmount });
|
|
1121
1158
|
}
|
|
1122
1159
|
async getLobby(lobbyId) {
|
|
1123
|
-
|
|
1160
|
+
const lobby = await this.http.get(`/lobbies/${lobbyId}`);
|
|
1161
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1162
|
+
return lobby;
|
|
1124
1163
|
}
|
|
1125
1164
|
async inviteFriend(lobbyId, friendId) {
|
|
1126
1165
|
return this.http.post(`/lobbies/${lobbyId}/invite`, {
|
|
@@ -1131,7 +1170,9 @@ var Lobbies = class {
|
|
|
1131
1170
|
return this.http.post(`/lobbies/${lobbyId}/accept-invite`, {});
|
|
1132
1171
|
}
|
|
1133
1172
|
async joinLobby(lobbyId) {
|
|
1134
|
-
|
|
1173
|
+
const lobby = await this.http.post(`/lobbies/${lobbyId}/join`, {});
|
|
1174
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1175
|
+
return lobby;
|
|
1135
1176
|
}
|
|
1136
1177
|
async removePlayer(lobbyId, userId) {
|
|
1137
1178
|
return this.http.delete(
|
|
@@ -1148,12 +1189,17 @@ var Lobbies = class {
|
|
|
1148
1189
|
return this.http.post(`/lobbies/${lobbyId}/join-queue`, {});
|
|
1149
1190
|
}
|
|
1150
1191
|
async cancelQueue(lobbyId) {
|
|
1151
|
-
|
|
1192
|
+
const lobby = await this.http.delete(`/lobbies/${lobbyId}/queue`);
|
|
1193
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1194
|
+
return lobby;
|
|
1152
1195
|
}
|
|
1153
1196
|
async updateBetAmount(lobbyId, betAmount) {
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1197
|
+
const lobby = await this.http.patch(
|
|
1198
|
+
`/lobbies/${lobbyId}/bet-amount`,
|
|
1199
|
+
{ betAmount }
|
|
1200
|
+
);
|
|
1201
|
+
this.lobbyStore?.setBaseState([lobby]);
|
|
1202
|
+
return lobby;
|
|
1157
1203
|
}
|
|
1158
1204
|
async playSound(lobbyId, sound) {
|
|
1159
1205
|
return this.http.post(`/lobbies/${lobbyId}/sound`, {
|
|
@@ -1188,13 +1234,18 @@ var Lobbies = class {
|
|
|
1188
1234
|
};
|
|
1189
1235
|
|
|
1190
1236
|
// src/games.ts
|
|
1191
|
-
var import_web32 = require("@solana/web3.js");
|
|
1192
1237
|
var Games = class {
|
|
1193
1238
|
constructor(http, wallet, logger2) {
|
|
1194
1239
|
this.http = http;
|
|
1195
1240
|
this.wallet = wallet;
|
|
1196
1241
|
this.logger = logger2;
|
|
1197
1242
|
}
|
|
1243
|
+
setGameStore(store) {
|
|
1244
|
+
this.gameStore = store;
|
|
1245
|
+
}
|
|
1246
|
+
setGameActionsStore(store) {
|
|
1247
|
+
this.gameActionsStore = store;
|
|
1248
|
+
}
|
|
1198
1249
|
async getAvailableGames() {
|
|
1199
1250
|
return this.http.get("/games/available");
|
|
1200
1251
|
}
|
|
@@ -1207,7 +1258,11 @@ var Games = class {
|
|
|
1207
1258
|
return this.http.get("/games/metrics");
|
|
1208
1259
|
}
|
|
1209
1260
|
async getGame(gameId) {
|
|
1210
|
-
|
|
1261
|
+
const existing = this.gameStore?.store.getState().gamesById[gameId];
|
|
1262
|
+
if (existing?.status === "completed") return existing;
|
|
1263
|
+
const game = await this.http.get(`/games/${gameId}`);
|
|
1264
|
+
this.gameStore?.setBaseState([game]);
|
|
1265
|
+
return game;
|
|
1211
1266
|
}
|
|
1212
1267
|
/**
|
|
1213
1268
|
* Get list of currently active (live) games. Public endpoint for spectating.
|
|
@@ -1234,7 +1289,13 @@ var Games = class {
|
|
|
1234
1289
|
* Get current game state with timer information
|
|
1235
1290
|
*/
|
|
1236
1291
|
async getGameState(gameId) {
|
|
1237
|
-
|
|
1292
|
+
const existing = this.gameActionsStore?.store.getState().statesByGameId[gameId];
|
|
1293
|
+
if (existing?.status === "completed") return existing;
|
|
1294
|
+
const state = await this.http.get(
|
|
1295
|
+
`/games/${gameId}/state`
|
|
1296
|
+
);
|
|
1297
|
+
this.gameActionsStore?.setBaseState(gameId, state);
|
|
1298
|
+
return state;
|
|
1238
1299
|
}
|
|
1239
1300
|
/**
|
|
1240
1301
|
* Request a rematch for a completed game
|
|
@@ -1270,8 +1331,18 @@ var Games = class {
|
|
|
1270
1331
|
{ amountMinor, signedTransaction }
|
|
1271
1332
|
);
|
|
1272
1333
|
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Confirm a donation that was already sent by the client (signAndSendTransaction path).
|
|
1336
|
+
*/
|
|
1337
|
+
async confirmGameDonationSignature(gameId, amountMinor, signature) {
|
|
1338
|
+
return this.http.post(
|
|
1339
|
+
`/games/${gameId}/donate/confirm-signature`,
|
|
1340
|
+
{ amountMinor, signature }
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1273
1343
|
/**
|
|
1274
1344
|
* One-call donation flow: prepare -> sign -> submit.
|
|
1345
|
+
* Automatically uses the right signing path (embedded vs injected wallet).
|
|
1275
1346
|
*/
|
|
1276
1347
|
async sendDonation(gameId, amountMinor) {
|
|
1277
1348
|
if (!this.wallet.hasSigner()) {
|
|
@@ -1280,16 +1351,10 @@ var Games = class {
|
|
|
1280
1351
|
);
|
|
1281
1352
|
}
|
|
1282
1353
|
const prepared = await this.prepareGameDonation(gameId, amountMinor);
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
);
|
|
1288
|
-
const result = await this.donateToGame(
|
|
1289
|
-
gameId,
|
|
1290
|
-
amountMinor,
|
|
1291
|
-
signedTransaction
|
|
1292
|
-
);
|
|
1354
|
+
const result = await this.wallet.signAndDispatch(prepared.transaction, {
|
|
1355
|
+
onSigned: (signedTxBase64) => this.donateToGame(gameId, amountMinor, signedTxBase64),
|
|
1356
|
+
onSignedAndSent: (sig) => this.confirmGameDonationSignature(gameId, amountMinor, sig)
|
|
1357
|
+
});
|
|
1293
1358
|
return {
|
|
1294
1359
|
...result,
|
|
1295
1360
|
escrowAddress: prepared.escrowAddress,
|
|
@@ -1388,6 +1453,9 @@ var Chat = class {
|
|
|
1388
1453
|
this.logger = logger2;
|
|
1389
1454
|
this.retryOptions = { ...DEFAULT_RETRY_OPTIONS, ...retryOptions };
|
|
1390
1455
|
}
|
|
1456
|
+
setDmThreadsStore(store) {
|
|
1457
|
+
this.dmThreadsStore = store;
|
|
1458
|
+
}
|
|
1391
1459
|
encodeContextId(id) {
|
|
1392
1460
|
return encodeURIComponent(id);
|
|
1393
1461
|
}
|
|
@@ -1469,7 +1537,9 @@ var Chat = class {
|
|
|
1469
1537
|
return response;
|
|
1470
1538
|
}
|
|
1471
1539
|
async listDmThreads() {
|
|
1472
|
-
|
|
1540
|
+
const threads = await this.http.get("/chat/dm/threads");
|
|
1541
|
+
this.dmThreadsStore?.setBaseState(threads);
|
|
1542
|
+
return threads;
|
|
1473
1543
|
}
|
|
1474
1544
|
async getDmThread(dmKey) {
|
|
1475
1545
|
return this.http.get(
|
|
@@ -1535,7 +1605,6 @@ var Challenges = class {
|
|
|
1535
1605
|
};
|
|
1536
1606
|
|
|
1537
1607
|
// src/tips.ts
|
|
1538
|
-
var import_web33 = require("@solana/web3.js");
|
|
1539
1608
|
var Tips = class {
|
|
1540
1609
|
constructor(http, wallet, chat, logger2) {
|
|
1541
1610
|
this.http = http;
|
|
@@ -1562,21 +1631,32 @@ var Tips = class {
|
|
|
1562
1631
|
);
|
|
1563
1632
|
}
|
|
1564
1633
|
const { publicKey: senderAddress } = await this.wallet.loadWallet();
|
|
1565
|
-
const
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
);
|
|
1571
|
-
const transfer = await this.wallet.
|
|
1572
|
-
signedTxBase64
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1634
|
+
const supportsPresign = !this.wallet.isSignAndSendMode();
|
|
1635
|
+
const prepared = await this.prepare({
|
|
1636
|
+
recipientUsername,
|
|
1637
|
+
amount,
|
|
1638
|
+
supportsPresign
|
|
1639
|
+
});
|
|
1640
|
+
const transfer = await this.wallet.signAndDispatch(prepared.transaction, {
|
|
1641
|
+
onSigned: (signedTxBase64) => this.wallet.submitTransfer(
|
|
1642
|
+
signedTxBase64,
|
|
1643
|
+
senderAddress,
|
|
1644
|
+
prepared.recipientAddress,
|
|
1645
|
+
prepared.amount,
|
|
1646
|
+
"USDC",
|
|
1647
|
+
false,
|
|
1648
|
+
prepared.recipientUsername
|
|
1649
|
+
),
|
|
1650
|
+
onSignedAndSent: (sig) => this.wallet.confirmTransferSignature(
|
|
1651
|
+
sig,
|
|
1652
|
+
senderAddress,
|
|
1653
|
+
prepared.recipientAddress,
|
|
1654
|
+
prepared.amount,
|
|
1655
|
+
"USDC",
|
|
1656
|
+
false,
|
|
1657
|
+
prepared.recipientUsername
|
|
1658
|
+
)
|
|
1659
|
+
});
|
|
1580
1660
|
const message = await this.chat.broadcastGlobalTip(
|
|
1581
1661
|
prepared.recipientUserId,
|
|
1582
1662
|
prepared.amount
|
|
@@ -1688,7 +1768,7 @@ var Achievements = class {
|
|
|
1688
1768
|
};
|
|
1689
1769
|
|
|
1690
1770
|
// src/wallet.ts
|
|
1691
|
-
var
|
|
1771
|
+
var import_web32 = require("@solana/web3.js");
|
|
1692
1772
|
var TRANSFER_FEE_MINOR = 1e4;
|
|
1693
1773
|
var MIN_TRANSFER_AMOUNT = 5e4;
|
|
1694
1774
|
var MIN_SOL_TRANSFER_AMOUNT = 1e6;
|
|
@@ -1905,13 +1985,15 @@ var Wallet = class {
|
|
|
1905
1985
|
);
|
|
1906
1986
|
}
|
|
1907
1987
|
try {
|
|
1988
|
+
const supportsPresign = !this.isSignAndSendMode();
|
|
1908
1989
|
const response = await this.http.post(
|
|
1909
1990
|
"/wallets/transfer/prepare",
|
|
1910
1991
|
{
|
|
1911
1992
|
senderAddress,
|
|
1912
1993
|
recipient,
|
|
1913
1994
|
amount: amountMinor,
|
|
1914
|
-
token
|
|
1995
|
+
token,
|
|
1996
|
+
supportsPresign
|
|
1915
1997
|
}
|
|
1916
1998
|
);
|
|
1917
1999
|
this.logger.debug("Transfer prepared", {
|
|
@@ -1995,6 +2077,29 @@ var Wallet = class {
|
|
|
1995
2077
|
throw error;
|
|
1996
2078
|
}
|
|
1997
2079
|
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Sign a prepared transaction and invoke the appropriate backend callback
|
|
2082
|
+
* based on the configured signer — without exposing the mode decision to callers.
|
|
2083
|
+
* - Embedded wallet (signAndSend): signs+sends, calls onSignedAndSent(signature)
|
|
2084
|
+
* - Injected wallet (signTransaction): signs locally, calls onSigned(signedTxBase64)
|
|
2085
|
+
*/
|
|
2086
|
+
async signAndDispatch(unsignedTxBase64, handlers) {
|
|
2087
|
+
if (!this.signer) {
|
|
2088
|
+
throw new Error(
|
|
2089
|
+
"No signer configured. Call setSigner() with a WalletSigner implementation first."
|
|
2090
|
+
);
|
|
2091
|
+
}
|
|
2092
|
+
const unsignedTx = import_web32.Transaction.from(base64ToBytes(unsignedTxBase64));
|
|
2093
|
+
if (this.isSignAndSendMode()) {
|
|
2094
|
+
const sig = await this.signAndSendTransaction(unsignedTx);
|
|
2095
|
+
return handlers.onSignedAndSent(sig);
|
|
2096
|
+
}
|
|
2097
|
+
const signedTx = await this.signTransaction(unsignedTx);
|
|
2098
|
+
const signedBase64 = bytesToBase64(
|
|
2099
|
+
signedTx.serialize({ requireAllSignatures: false })
|
|
2100
|
+
);
|
|
2101
|
+
return handlers.onSigned(signedBase64);
|
|
2102
|
+
}
|
|
1998
2103
|
/**
|
|
1999
2104
|
* Full transfer flow in one call: prepare -> sign -> submit
|
|
2000
2105
|
* Recipient can be username, .sol domain, or Solana address (resolved by backend).
|
|
@@ -2011,7 +2116,7 @@ var Wallet = class {
|
|
|
2011
2116
|
amount,
|
|
2012
2117
|
token
|
|
2013
2118
|
);
|
|
2014
|
-
const unsignedTx =
|
|
2119
|
+
const unsignedTx = import_web32.Transaction.from(base64ToBytes(prepared.transaction));
|
|
2015
2120
|
let submitted;
|
|
2016
2121
|
if (this.isSignAndSendMode()) {
|
|
2017
2122
|
const signature = await this.signAndSendTransaction(unsignedTx);
|
|
@@ -2051,7 +2156,7 @@ var Wallet = class {
|
|
|
2051
2156
|
};
|
|
2052
2157
|
|
|
2053
2158
|
// src/escrow.ts
|
|
2054
|
-
var
|
|
2159
|
+
var import_web33 = require("@solana/web3.js");
|
|
2055
2160
|
var Escrow = class {
|
|
2056
2161
|
constructor(http, wallet, logger2) {
|
|
2057
2162
|
this.http = http;
|
|
@@ -2079,12 +2184,32 @@ var Escrow = class {
|
|
|
2079
2184
|
* initializes depositStatus, and prepares the unsigned transaction in one call.
|
|
2080
2185
|
* Eliminates one HTTP round-trip vs startDeposits() + prepareDepositTransaction().
|
|
2081
2186
|
*/
|
|
2082
|
-
async prepareAndStartDeposit(lobbyId) {
|
|
2187
|
+
async prepareAndStartDeposit(lobbyId, supportsPresign) {
|
|
2188
|
+
const presign = supportsPresign ?? !this.wallet.isSignAndSendMode();
|
|
2083
2189
|
return this.http.post(
|
|
2084
2190
|
`/escrow/lobby/${lobbyId}/deposit/prepare-and-start`,
|
|
2085
|
-
{}
|
|
2191
|
+
{ supportsPresign: presign }
|
|
2086
2192
|
);
|
|
2087
2193
|
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Sign and submit a prepared (unsigned) deposit transaction using the
|
|
2196
|
+
* configured signer. Automatically picks the right path:
|
|
2197
|
+
* - Embedded wallet: signAndSendTransaction → confirmDepositSignature
|
|
2198
|
+
* - Injected wallet: signTransaction → submitDeposit
|
|
2199
|
+
* Returns the on-chain signature.
|
|
2200
|
+
*/
|
|
2201
|
+
async signAndSubmitPreparedDeposit(lobbyId, unsignedTxBase64) {
|
|
2202
|
+
return this.wallet.signAndDispatch(unsignedTxBase64, {
|
|
2203
|
+
onSigned: async (signedTxBase64) => {
|
|
2204
|
+
const result = await this.submitDeposit(lobbyId, signedTxBase64);
|
|
2205
|
+
return result.signature;
|
|
2206
|
+
},
|
|
2207
|
+
onSignedAndSent: async (signature) => {
|
|
2208
|
+
await this.confirmDepositSignature(lobbyId, signature);
|
|
2209
|
+
return signature;
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2088
2213
|
/**
|
|
2089
2214
|
* Submit a signed deposit transaction
|
|
2090
2215
|
* The transaction will be submitted to the Solana network and confirmed
|
|
@@ -2127,8 +2252,12 @@ var Escrow = class {
|
|
|
2127
2252
|
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2128
2253
|
);
|
|
2129
2254
|
}
|
|
2130
|
-
const
|
|
2131
|
-
const
|
|
2255
|
+
const supportsPresign = !this.wallet.isSignAndSendMode();
|
|
2256
|
+
const { transaction } = await this.prepareAndStartDeposit(
|
|
2257
|
+
lobbyId,
|
|
2258
|
+
supportsPresign
|
|
2259
|
+
);
|
|
2260
|
+
const unsignedTx = import_web33.Transaction.from(base64ToBytes(transaction));
|
|
2132
2261
|
let signature;
|
|
2133
2262
|
if (this.wallet.isSignAndSendMode()) {
|
|
2134
2263
|
signature = await this.wallet.signAndSendTransaction(unsignedTx);
|
|
@@ -2162,8 +2291,13 @@ var Escrow = class {
|
|
|
2162
2291
|
};
|
|
2163
2292
|
}
|
|
2164
2293
|
/**
|
|
2165
|
-
*
|
|
2166
|
-
*
|
|
2294
|
+
* Deposit for a lobby and wait until the calling user's own deposit is confirmed.
|
|
2295
|
+
* Ideal for agents: returns as soon as your deposit is on-chain without waiting
|
|
2296
|
+
* for the other player. The server auto-joins the queue when all players deposit.
|
|
2297
|
+
*
|
|
2298
|
+
* Confirmation is handled asynchronously by the transaction queue processor.
|
|
2299
|
+
* This method polls the deposit status endpoint until the signature appears as
|
|
2300
|
+
* confirmed (up to 60 seconds).
|
|
2167
2301
|
*
|
|
2168
2302
|
* Automatically uses signAndSendTransaction or signTransaction based on signer capability.
|
|
2169
2303
|
*/
|
|
@@ -2173,26 +2307,45 @@ var Escrow = class {
|
|
|
2173
2307
|
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2174
2308
|
);
|
|
2175
2309
|
}
|
|
2176
|
-
const
|
|
2177
|
-
const
|
|
2310
|
+
const supportsPresign2 = !this.wallet.isSignAndSendMode();
|
|
2311
|
+
const { transaction } = await this.prepareAndStartDeposit(
|
|
2312
|
+
lobbyId,
|
|
2313
|
+
supportsPresign2
|
|
2314
|
+
);
|
|
2315
|
+
const unsignedTx = import_web33.Transaction.from(base64ToBytes(transaction));
|
|
2178
2316
|
let signature;
|
|
2179
2317
|
if (this.wallet.isSignAndSendMode()) {
|
|
2180
2318
|
signature = await this.wallet.signAndSendTransaction(unsignedTx);
|
|
2181
|
-
await this.
|
|
2182
|
-
`/escrow/lobby/${lobbyId}/deposit/confirm-signature?awaitConfirmation=true`,
|
|
2183
|
-
{ signature }
|
|
2184
|
-
);
|
|
2319
|
+
await this.confirmDepositSignature(lobbyId, signature);
|
|
2185
2320
|
} else {
|
|
2186
2321
|
const signedTx = await this.wallet.signTransaction(unsignedTx);
|
|
2187
2322
|
const signedBase64 = bytesToBase64(
|
|
2188
2323
|
signedTx.serialize({ requireAllSignatures: false })
|
|
2189
2324
|
);
|
|
2190
|
-
const
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2325
|
+
const submitResult = await this.submitDeposit(lobbyId, signedBase64);
|
|
2326
|
+
signature = submitResult.signature;
|
|
2327
|
+
}
|
|
2328
|
+
const MAX_WAIT_MS = 6e4;
|
|
2329
|
+
const POLL_INTERVAL_MS = 1e3;
|
|
2330
|
+
const startTime = Date.now();
|
|
2331
|
+
while (Date.now() - startTime < MAX_WAIT_MS) {
|
|
2332
|
+
const status = await this.getDepositStatus(lobbyId);
|
|
2333
|
+
const myDeposit = status.deposits.find(
|
|
2334
|
+
(d) => d.transactionHash === signature
|
|
2335
|
+
);
|
|
2336
|
+
if (myDeposit?.status === "confirmed") {
|
|
2337
|
+
return {
|
|
2338
|
+
signature,
|
|
2339
|
+
status: "confirmed",
|
|
2340
|
+
canProceedToQueue: status.canProceedToQueue
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
if (status.allConfirmed && status.canProceedToQueue) {
|
|
2344
|
+
return { signature, status: "confirmed", canProceedToQueue: true };
|
|
2345
|
+
}
|
|
2346
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
2194
2347
|
}
|
|
2195
|
-
return { signature, status: "
|
|
2348
|
+
return { signature, status: "pending", canProceedToQueue: false };
|
|
2196
2349
|
}
|
|
2197
2350
|
async claimLobbyDepositRefund(lobbyId, depositSignature) {
|
|
2198
2351
|
return this.http.post(
|
|
@@ -2548,9 +2701,10 @@ var Support = class {
|
|
|
2548
2701
|
|
|
2549
2702
|
// src/markets.ts
|
|
2550
2703
|
var Markets = class {
|
|
2551
|
-
constructor(http, logger2) {
|
|
2704
|
+
constructor(http, logger2, wallet) {
|
|
2552
2705
|
this.http = http;
|
|
2553
2706
|
this.logger = logger2;
|
|
2707
|
+
this.wallet = wallet;
|
|
2554
2708
|
}
|
|
2555
2709
|
/**
|
|
2556
2710
|
* Get the prediction market state for a game.
|
|
@@ -2592,6 +2746,35 @@ var Markets = class {
|
|
|
2592
2746
|
{ signedTransaction, outcomeId, amountMinor }
|
|
2593
2747
|
);
|
|
2594
2748
|
}
|
|
2749
|
+
/**
|
|
2750
|
+
* Confirm a buy order that was already broadcast by the client (signAndSendTransaction path).
|
|
2751
|
+
*/
|
|
2752
|
+
async confirmBuyOrderSignature(gameId, depositSignature, outcomeId, amountMinor) {
|
|
2753
|
+
return this.http.post(
|
|
2754
|
+
`/games/${gameId}/market/orders/buy/confirm-signature`,
|
|
2755
|
+
{ depositSignature, outcomeId, amountMinor }
|
|
2756
|
+
);
|
|
2757
|
+
}
|
|
2758
|
+
/**
|
|
2759
|
+
* One-call buy order: prepare → sign → submit, automatically choosing
|
|
2760
|
+
* the right signing path (embedded vs injected wallet).
|
|
2761
|
+
*/
|
|
2762
|
+
async buy(gameId, outcomeId, amountMinor) {
|
|
2763
|
+
if (!this.wallet?.hasSigner()) {
|
|
2764
|
+
throw new Error(
|
|
2765
|
+
"No signer configured. Use sdk.wallet.setSigner(...) first."
|
|
2766
|
+
);
|
|
2767
|
+
}
|
|
2768
|
+
const { transaction } = await this.prepareBuyOrder(
|
|
2769
|
+
gameId,
|
|
2770
|
+
outcomeId,
|
|
2771
|
+
amountMinor
|
|
2772
|
+
);
|
|
2773
|
+
return this.wallet.signAndDispatch(transaction, {
|
|
2774
|
+
onSigned: (signedTxBase64) => this.submitBuyOrder(gameId, signedTxBase64, outcomeId, amountMinor),
|
|
2775
|
+
onSignedAndSent: (sig) => this.confirmBuyOrderSignature(gameId, sig, outcomeId, amountMinor)
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2595
2778
|
/**
|
|
2596
2779
|
* Sell shares back to the AMM pool.
|
|
2597
2780
|
* @param gameId - The game ID
|
|
@@ -2641,6 +2824,22 @@ var Markets = class {
|
|
|
2641
2824
|
}
|
|
2642
2825
|
};
|
|
2643
2826
|
|
|
2827
|
+
// src/analytics.ts
|
|
2828
|
+
var NoopAnalyticsClient = class {
|
|
2829
|
+
userLoggedIn(_user, _meta) {
|
|
2830
|
+
}
|
|
2831
|
+
userLoggedOut() {
|
|
2832
|
+
}
|
|
2833
|
+
sessionRestored(_user) {
|
|
2834
|
+
}
|
|
2835
|
+
track(_event, _properties) {
|
|
2836
|
+
}
|
|
2837
|
+
setUserProperties(_properties) {
|
|
2838
|
+
}
|
|
2839
|
+
group(_groupType, _groupKey, _properties) {
|
|
2840
|
+
}
|
|
2841
|
+
};
|
|
2842
|
+
|
|
2644
2843
|
// src/ws/standalone-transport.ts
|
|
2645
2844
|
var import_socket = require("socket.io-client");
|
|
2646
2845
|
|
|
@@ -2734,22 +2933,35 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2734
2933
|
this.accessToken = null;
|
|
2735
2934
|
this.reconnectAttempts = 0;
|
|
2736
2935
|
this.reconnectTimer = null;
|
|
2737
|
-
this.
|
|
2738
|
-
this.
|
|
2739
|
-
this.reconnectDelay = 1e3;
|
|
2740
|
-
this.reconnectDelayMax = 3e4;
|
|
2741
|
-
// 5 minutes
|
|
2936
|
+
this.needsReconnect = false;
|
|
2937
|
+
this.visibilityHandler = null;
|
|
2742
2938
|
this.wildcardHandlers = /* @__PURE__ */ new Set();
|
|
2743
2939
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
2744
2940
|
this.registeredEvents = /* @__PURE__ */ new Set();
|
|
2745
2941
|
this.wildcardRegistered = false;
|
|
2746
2942
|
this.url = url;
|
|
2943
|
+
if (typeof document !== "undefined") {
|
|
2944
|
+
this.visibilityHandler = () => {
|
|
2945
|
+
if (document.visibilityState === "visible" && !this.connectionState.connected) {
|
|
2946
|
+
this.reconnectImmediately();
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
2950
|
+
}
|
|
2747
2951
|
}
|
|
2748
2952
|
connect() {
|
|
2953
|
+
if (this.reconnectTimer !== null) {
|
|
2954
|
+
clearTimeout(this.reconnectTimer);
|
|
2955
|
+
this.reconnectTimer = null;
|
|
2956
|
+
}
|
|
2957
|
+
this.reconnectAttempts = 0;
|
|
2749
2958
|
this.ensureSocket();
|
|
2750
2959
|
}
|
|
2751
2960
|
disconnect() {
|
|
2752
|
-
this.
|
|
2961
|
+
if (this.visibilityHandler && typeof document !== "undefined") {
|
|
2962
|
+
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
2963
|
+
this.visibilityHandler = null;
|
|
2964
|
+
}
|
|
2753
2965
|
if (!this.socket) return;
|
|
2754
2966
|
this.socket.disconnect();
|
|
2755
2967
|
this.socket = null;
|
|
@@ -2848,13 +3060,13 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2848
3060
|
reconnection: false
|
|
2849
3061
|
});
|
|
2850
3062
|
socket.on("connect", () => {
|
|
2851
|
-
this.clearPeriodicReconnect();
|
|
2852
3063
|
this.updateConnectionState({
|
|
2853
3064
|
connected: true,
|
|
2854
3065
|
connecting: false,
|
|
2855
3066
|
error: null
|
|
2856
3067
|
});
|
|
2857
|
-
const wasReconnect = this.
|
|
3068
|
+
const wasReconnect = this.needsReconnect;
|
|
3069
|
+
this.needsReconnect = false;
|
|
2858
3070
|
this.reconnectAttempts = 0;
|
|
2859
3071
|
this.onReconnect();
|
|
2860
3072
|
if (wasReconnect) {
|
|
@@ -2865,6 +3077,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2865
3077
|
});
|
|
2866
3078
|
socket.on("disconnect", (reason) => {
|
|
2867
3079
|
this.updateConnectionState({ connected: false, connecting: false });
|
|
3080
|
+
this.needsReconnect = true;
|
|
2868
3081
|
this.clearSocketForReconnect();
|
|
2869
3082
|
if (reason === "io server disconnect") {
|
|
2870
3083
|
this.handleAuthFailure("io server disconnect");
|
|
@@ -2874,6 +3087,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2874
3087
|
});
|
|
2875
3088
|
socket.on("connect_error", (error) => {
|
|
2876
3089
|
const message = error?.message || "connect_error";
|
|
3090
|
+
this.needsReconnect = true;
|
|
2877
3091
|
this.clearSocketForReconnect();
|
|
2878
3092
|
if (message.includes("unauthorized") || message.includes("401")) {
|
|
2879
3093
|
this.handleAuthFailure(message);
|
|
@@ -2901,31 +3115,31 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2901
3115
|
this.socket.removeAllListeners();
|
|
2902
3116
|
this.socket = null;
|
|
2903
3117
|
}
|
|
2904
|
-
|
|
2905
|
-
if (this.
|
|
2906
|
-
|
|
2907
|
-
this.
|
|
3118
|
+
reconnectImmediately() {
|
|
3119
|
+
if (this.reconnectTimer !== null) {
|
|
3120
|
+
clearTimeout(this.reconnectTimer);
|
|
3121
|
+
this.reconnectTimer = null;
|
|
2908
3122
|
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
if (this.periodicReconnectInterval !== null) return;
|
|
2912
|
-
this.periodicReconnectInterval = setInterval(() => {
|
|
2913
|
-
if (this.connectionState.connected) return;
|
|
2914
|
-
this.reconnectAttempts = 0;
|
|
2915
|
-
this.ensureSocket();
|
|
2916
|
-
}, _StandaloneWsTransport.PERIODIC_RECONNECT_MS);
|
|
3123
|
+
this.reconnectAttempts = 0;
|
|
3124
|
+
this.ensureSocket();
|
|
2917
3125
|
}
|
|
2918
3126
|
scheduleReconnect() {
|
|
2919
3127
|
if (this.reconnectTimer !== null) return;
|
|
2920
|
-
|
|
2921
|
-
this.startPeriodicReconnect();
|
|
2922
|
-
return;
|
|
2923
|
-
}
|
|
2924
|
-
const delay = Math.min(
|
|
2925
|
-
this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
|
|
2926
|
-
this.reconnectDelayMax
|
|
2927
|
-
);
|
|
3128
|
+
const attempt = this.reconnectAttempts;
|
|
2928
3129
|
this.reconnectAttempts += 1;
|
|
3130
|
+
let delay;
|
|
3131
|
+
if (attempt < _StandaloneWsTransport.FAST_RETRY_LIMIT) {
|
|
3132
|
+
delay = _StandaloneWsTransport.FAST_RETRY_DELAY_MS;
|
|
3133
|
+
} else {
|
|
3134
|
+
const backoffAttempt = attempt - _StandaloneWsTransport.FAST_RETRY_LIMIT;
|
|
3135
|
+
delay = Math.min(
|
|
3136
|
+
_StandaloneWsTransport.FAST_RETRY_DELAY_MS * Math.pow(2, backoffAttempt),
|
|
3137
|
+
_StandaloneWsTransport.MAX_BACKOFF_MS
|
|
3138
|
+
);
|
|
3139
|
+
if (attempt === _StandaloneWsTransport.FAST_RETRY_LIMIT) {
|
|
3140
|
+
this.dispatchEvent("connection:slow-retry", { timestamp: Date.now() });
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
2929
3143
|
this.reconnectTimer = setTimeout(() => {
|
|
2930
3144
|
this.reconnectTimer = null;
|
|
2931
3145
|
this.ensureSocket();
|
|
@@ -2986,7 +3200,9 @@ var _StandaloneWsTransport = class _StandaloneWsTransport extends BaseWsTranspor
|
|
|
2986
3200
|
this.wildcardRegistered = true;
|
|
2987
3201
|
}
|
|
2988
3202
|
};
|
|
2989
|
-
_StandaloneWsTransport.
|
|
3203
|
+
_StandaloneWsTransport.FAST_RETRY_LIMIT = 60;
|
|
3204
|
+
_StandaloneWsTransport.FAST_RETRY_DELAY_MS = 1e3;
|
|
3205
|
+
_StandaloneWsTransport.MAX_BACKOFF_MS = 3e4;
|
|
2990
3206
|
var StandaloneWsTransport = _StandaloneWsTransport;
|
|
2991
3207
|
|
|
2992
3208
|
// src/stores/store-utils.ts
|
|
@@ -3013,14 +3229,16 @@ function createLobbyStore(transport) {
|
|
|
3013
3229
|
depositStatusByLobbyId: {}
|
|
3014
3230
|
});
|
|
3015
3231
|
const setBaseState = (lobbies) => {
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3232
|
+
store.updateState((state) => {
|
|
3233
|
+
const lobbiesById = { ...state.lobbiesById };
|
|
3234
|
+
for (const lobby of lobbies) {
|
|
3235
|
+
const existing = lobbiesById[lobby.id];
|
|
3236
|
+
if (!existing || lobby.updatedAt >= existing.updatedAt) {
|
|
3237
|
+
lobbiesById[lobby.id] = lobby;
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
return { ...state, lobbiesById };
|
|
3241
|
+
});
|
|
3024
3242
|
};
|
|
3025
3243
|
const applyWsEvent = (event) => {
|
|
3026
3244
|
switch (event.event) {
|
|
@@ -3152,12 +3370,23 @@ function createGameStore(transport) {
|
|
|
3152
3370
|
gamesById: {},
|
|
3153
3371
|
spectatorCounts: {}
|
|
3154
3372
|
});
|
|
3373
|
+
const STATUS_RANK = {
|
|
3374
|
+
active: 0,
|
|
3375
|
+
completed: 1,
|
|
3376
|
+
abandoned: 1
|
|
3377
|
+
};
|
|
3155
3378
|
const setBaseState = (games) => {
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3379
|
+
store.updateState((state) => {
|
|
3380
|
+
const gamesById = { ...state.gamesById };
|
|
3381
|
+
for (const game of games) {
|
|
3382
|
+
const existing = gamesById[game.gameId];
|
|
3383
|
+
if (existing && STATUS_RANK[existing.status] > STATUS_RANK[game.status]) {
|
|
3384
|
+
continue;
|
|
3385
|
+
}
|
|
3386
|
+
gamesById[game.gameId] = game;
|
|
3387
|
+
}
|
|
3388
|
+
return { ...state, gamesById };
|
|
3389
|
+
});
|
|
3161
3390
|
};
|
|
3162
3391
|
const applyWsEvent = (event) => {
|
|
3163
3392
|
switch (event.event) {
|
|
@@ -3903,7 +4132,38 @@ function createNotificationsStore() {
|
|
|
3903
4132
|
appNotifications: []
|
|
3904
4133
|
}));
|
|
3905
4134
|
};
|
|
3906
|
-
|
|
4135
|
+
const markAsRead = (id) => {
|
|
4136
|
+
store.updateState((state) => ({
|
|
4137
|
+
...state,
|
|
4138
|
+
appNotifications: state.appNotifications.map(
|
|
4139
|
+
(n) => n.id === id ? { ...n, read: true } : n
|
|
4140
|
+
)
|
|
4141
|
+
}));
|
|
4142
|
+
};
|
|
4143
|
+
const markAllAsRead = () => {
|
|
4144
|
+
store.updateState((state) => ({
|
|
4145
|
+
...state,
|
|
4146
|
+
appNotifications: state.appNotifications.map((n) => ({
|
|
4147
|
+
...n,
|
|
4148
|
+
read: true
|
|
4149
|
+
}))
|
|
4150
|
+
}));
|
|
4151
|
+
};
|
|
4152
|
+
const dismiss = (id) => {
|
|
4153
|
+
store.updateState((state) => ({
|
|
4154
|
+
...state,
|
|
4155
|
+
appNotifications: state.appNotifications.filter((n) => n.id !== id)
|
|
4156
|
+
}));
|
|
4157
|
+
};
|
|
4158
|
+
return {
|
|
4159
|
+
store,
|
|
4160
|
+
applyWsEvent,
|
|
4161
|
+
setListFromApi,
|
|
4162
|
+
clear,
|
|
4163
|
+
markAsRead,
|
|
4164
|
+
markAllAsRead,
|
|
4165
|
+
dismiss
|
|
4166
|
+
};
|
|
3907
4167
|
}
|
|
3908
4168
|
|
|
3909
4169
|
// src/stores/friends-store.ts
|
|
@@ -4260,6 +4520,7 @@ var SDK = class {
|
|
|
4260
4520
|
constructor(config) {
|
|
4261
4521
|
const baseUrl = config.baseUrl || "http://localhost:3000";
|
|
4262
4522
|
const logger2 = config.logger || logger;
|
|
4523
|
+
this.analytics = config.analytics ?? new NoopAnalyticsClient();
|
|
4263
4524
|
this.http = config.httpClient || new HttpClient(
|
|
4264
4525
|
baseUrl,
|
|
4265
4526
|
config.storage,
|
|
@@ -4292,14 +4553,18 @@ var SDK = class {
|
|
|
4292
4553
|
this.referrals = new Referrals(this.http, logger2);
|
|
4293
4554
|
this.reports = new Reports(this.http, logger2);
|
|
4294
4555
|
this.support = new Support(this.http, logger2);
|
|
4295
|
-
this.markets = new Markets(this.http, logger2);
|
|
4556
|
+
this.markets = new Markets(this.http, logger2, this.wallet);
|
|
4296
4557
|
this.wsTransport = config.wsTransport || new StandaloneWsTransport(baseUrl);
|
|
4297
4558
|
this.wsTransport.setAppId(config.appId);
|
|
4298
4559
|
this.lobbyStore = createLobbyStore(this.wsTransport);
|
|
4560
|
+
this.lobbies.setLobbyStore(this.lobbyStore);
|
|
4299
4561
|
this.gameStore = createGameStore(this.wsTransport);
|
|
4562
|
+
this.games.setGameStore(this.gameStore);
|
|
4300
4563
|
this.gameActionsStore = createGameActionsStore(this.wsTransport);
|
|
4564
|
+
this.games.setGameActionsStore(this.gameActionsStore);
|
|
4301
4565
|
this.chatStore = createChatStore(this.wsTransport);
|
|
4302
4566
|
this.dmThreadsStore = createDmThreadsStore();
|
|
4567
|
+
this.chat.setDmThreadsStore(this.dmThreadsStore);
|
|
4303
4568
|
this.notificationsStore = createNotificationsStore();
|
|
4304
4569
|
this.friendsStore = createFriendsStore();
|
|
4305
4570
|
this.notifications = new Notifications(
|
|
@@ -4329,6 +4594,29 @@ var SDK = class {
|
|
|
4329
4594
|
this.wsTransport.connect();
|
|
4330
4595
|
await this.wsTransport.waitUntilConnected(timeoutMs);
|
|
4331
4596
|
}
|
|
4597
|
+
/**
|
|
4598
|
+
* Handle the full deposit-to-queue lifecycle for a lobby.
|
|
4599
|
+
*
|
|
4600
|
+
* After the deposit is confirmed, the backend may not have processed the
|
|
4601
|
+
* `lobby.deposit.allConfirmed` event yet, so the lobby can still be in
|
|
4602
|
+
* 'preparing' status. This method re-fetches the lobby and explicitly
|
|
4603
|
+
* joins the queue if needed, then pushes the latest state to the store
|
|
4604
|
+
* so the UI transitions immediately.
|
|
4605
|
+
*/
|
|
4606
|
+
async depositAndJoinQueue(lobbyId) {
|
|
4607
|
+
const result = await this.escrow.depositForLobby(lobbyId);
|
|
4608
|
+
if (!result.canProceedToQueue) {
|
|
4609
|
+
const lobby2 = await this.lobbies.getLobby(lobbyId);
|
|
4610
|
+
this.lobbyStore.setBaseState([lobby2]);
|
|
4611
|
+
return { ...result, lobby: lobby2 };
|
|
4612
|
+
}
|
|
4613
|
+
let lobby = await this.lobbies.getLobby(lobbyId);
|
|
4614
|
+
if (lobby.status === "preparing") {
|
|
4615
|
+
lobby = await this.lobbies.joinQueue(lobbyId);
|
|
4616
|
+
}
|
|
4617
|
+
this.lobbyStore.setBaseState([lobby]);
|
|
4618
|
+
return { ...result, lobby };
|
|
4619
|
+
}
|
|
4332
4620
|
};
|
|
4333
4621
|
|
|
4334
4622
|
// ../ws-shared-worker/dist/protocol.js
|
|
@@ -4436,6 +4724,26 @@ var SharedWorkerClient = class {
|
|
|
4436
4724
|
}
|
|
4437
4725
|
}
|
|
4438
4726
|
}
|
|
4727
|
+
/**
|
|
4728
|
+
* Dispatch a synthetic local event directly to all registered handlers for
|
|
4729
|
+
* that event name (and wildcard handlers), without sending anything over the
|
|
4730
|
+
* wire. Used by SharedWorkerTransport to fire synthetic events like
|
|
4731
|
+
* `connection:reconnected` that originate from transport-layer logic rather
|
|
4732
|
+
* than from the server.
|
|
4733
|
+
*/
|
|
4734
|
+
dispatchLocalEvent(eventName, payload) {
|
|
4735
|
+
const handlers = this.eventHandlers.get(eventName);
|
|
4736
|
+
if (handlers) {
|
|
4737
|
+
for (const handler of handlers) {
|
|
4738
|
+
handler(payload);
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
if (this.wildcardHandlers.size > 0) {
|
|
4742
|
+
for (const handler of this.wildcardHandlers) {
|
|
4743
|
+
handler(eventName, payload);
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4439
4747
|
postMessage(command) {
|
|
4440
4748
|
this.port.postMessage(command);
|
|
4441
4749
|
}
|
|
@@ -4445,6 +4753,10 @@ var SharedWorkerClient = class {
|
|
|
4445
4753
|
var SharedWorkerTransport = class extends BaseWsTransport {
|
|
4446
4754
|
constructor(workerUrl, socketUrl) {
|
|
4447
4755
|
super();
|
|
4756
|
+
/** Tracks whether a successful connection has been established at least once,
|
|
4757
|
+
* so that subsequent ws_open events are treated as reconnects and the
|
|
4758
|
+
* `connection:reconnected` event is dispatched to subscribers. */
|
|
4759
|
+
this.hasConnectedBefore = false;
|
|
4448
4760
|
this.client = new SharedWorkerClient(workerUrl);
|
|
4449
4761
|
this.url = socketUrl;
|
|
4450
4762
|
this.client.onMessage((event) => this.handleWorkerMessage(event));
|
|
@@ -4485,14 +4797,22 @@ var SharedWorkerTransport = class extends BaseWsTransport {
|
|
|
4485
4797
|
}
|
|
4486
4798
|
handleWorkerMessage(event) {
|
|
4487
4799
|
switch (event.type) {
|
|
4488
|
-
case "ws_open":
|
|
4800
|
+
case "ws_open": {
|
|
4801
|
+
const wasReconnect = this.hasConnectedBefore;
|
|
4802
|
+
this.hasConnectedBefore = true;
|
|
4489
4803
|
this.updateConnectionState({
|
|
4490
4804
|
connected: true,
|
|
4491
4805
|
connecting: false,
|
|
4492
4806
|
error: null
|
|
4493
4807
|
});
|
|
4494
4808
|
this.onReconnect();
|
|
4809
|
+
if (wasReconnect) {
|
|
4810
|
+
this.client.dispatchLocalEvent("connection:reconnected", {
|
|
4811
|
+
timestamp: Date.now()
|
|
4812
|
+
});
|
|
4813
|
+
}
|
|
4495
4814
|
break;
|
|
4815
|
+
}
|
|
4496
4816
|
case "ws_close":
|
|
4497
4817
|
this.updateConnectionState({
|
|
4498
4818
|
connected: false,
|
|
@@ -4529,6 +4849,7 @@ var import_utils = __toESM(require_dist(), 1);
|
|
|
4529
4849
|
MIN_TRANSFER_AMOUNT,
|
|
4530
4850
|
Markets,
|
|
4531
4851
|
NodeStorage,
|
|
4852
|
+
NoopAnalyticsClient,
|
|
4532
4853
|
Referrals,
|
|
4533
4854
|
Reports,
|
|
4534
4855
|
SDK,
|