@dimcool/mcp 0.1.29 → 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.
Files changed (3) hide show
  1. package/README.md +22 -12
  2. package/dist/index.js +945 -127
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7328,8 +7328,6 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7328
7328
  import { Transaction } from "@solana/web3.js";
7329
7329
  import { Transaction as Transaction2 } from "@solana/web3.js";
7330
7330
  import { Transaction as Transaction3 } from "@solana/web3.js";
7331
- import { Transaction as Transaction4 } from "@solana/web3.js";
7332
- import { Transaction as Transaction5 } from "@solana/web3.js";
7333
7331
 
7334
7332
  // ../../node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.node.js
7335
7333
  var XMLHttpRequestModule = __toESM(require_XMLHttpRequest(), 1);
@@ -11587,6 +11585,16 @@ var Auth = class {
11587
11585
  this.logger.debug("Token stored in storage", { tokenKey: TOKEN_KEY });
11588
11586
  return response;
11589
11587
  }
11588
+ async loginWithExternalSignature(address, signedMessage, options) {
11589
+ const response = await this.http.post("/auth/login-wallet", {
11590
+ signedMessage,
11591
+ address,
11592
+ referralCode: options?.referralCode,
11593
+ walletMeta: options?.walletMeta
11594
+ });
11595
+ this.storage.set(TOKEN_KEY, response.access_token);
11596
+ return response;
11597
+ }
11590
11598
  logout() {
11591
11599
  this.logger.debug("Auth.logout called");
11592
11600
  const hadToken = this.storage.get(TOKEN_KEY) !== null;
@@ -11600,6 +11608,10 @@ var Auth = class {
11600
11608
  });
11601
11609
  return isAuth;
11602
11610
  }
11611
+ async getSessionStats() {
11612
+ this.logger.debug("Auth.getSessionStats called");
11613
+ return this.http.get("/auth/sessions/stats");
11614
+ }
11603
11615
  async getLatestSessions(limit) {
11604
11616
  this.logger.debug("Auth.getLatestSessions called", { limit });
11605
11617
  const params = new URLSearchParams();
@@ -11823,11 +11835,25 @@ var Users = class {
11823
11835
  async removeFriend(userId) {
11824
11836
  return this.http.delete(`/friends/${userId}`);
11825
11837
  }
11826
- async getIncomingFriendRequests() {
11827
- return this.http.get("/friends/requests/incoming");
11838
+ async getIncomingFriendRequests(opts) {
11839
+ const params = new URLSearchParams();
11840
+ if (opts?.limit !== void 0)
11841
+ params.append("limit", opts.limit.toString());
11842
+ if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
11843
+ const qs = params.toString();
11844
+ return this.http.get(
11845
+ qs ? `/friends/requests/incoming?${qs}` : "/friends/requests/incoming"
11846
+ );
11828
11847
  }
11829
- async getOutgoingFriendRequests() {
11830
- return this.http.get("/friends/requests/outgoing");
11848
+ async getOutgoingFriendRequests(opts) {
11849
+ const params = new URLSearchParams();
11850
+ if (opts?.limit !== void 0)
11851
+ params.append("limit", opts.limit.toString());
11852
+ if (opts?.cursor !== void 0) params.append("cursor", opts.cursor);
11853
+ const qs = params.toString();
11854
+ return this.http.get(
11855
+ qs ? `/friends/requests/outgoing?${qs}` : "/friends/requests/outgoing"
11856
+ );
11831
11857
  }
11832
11858
  async acceptFriendRequest(userId) {
11833
11859
  return this.http.post(
@@ -11914,6 +11940,9 @@ var FeatureFlags = class {
11914
11940
  this.loaded = true;
11915
11941
  return this.flags;
11916
11942
  }
11943
+ async getAdminFeatureFlags() {
11944
+ return this.http.get("/feature-flags/admin");
11945
+ }
11917
11946
  isEnabledFlag(name) {
11918
11947
  const flag = this.flags.find((f) => f.name === name);
11919
11948
  return flag?.enabled ?? false;
@@ -11933,10 +11962,11 @@ var FeatureFlags = class {
11933
11962
  }
11934
11963
  return flag;
11935
11964
  }
11936
- async createFeatureFlag(name, enabled) {
11965
+ async createFeatureFlag(name, enabled, description) {
11937
11966
  const flag = await this.http.post("/feature-flags", {
11938
11967
  name,
11939
- enabled
11968
+ enabled,
11969
+ ...description !== void 0 && { description }
11940
11970
  });
11941
11971
  this.flags.push(flag);
11942
11972
  return flag;
@@ -11947,11 +11977,17 @@ var Lobbies = class {
11947
11977
  this.http = http;
11948
11978
  this.logger = logger2;
11949
11979
  }
11980
+ /** Called by SDK after the store is created so mutations can update state directly. */
11981
+ setLobbyStore(store) {
11982
+ this.lobbyStore = store;
11983
+ }
11950
11984
  async createLobby(gameType, betAmount) {
11951
11985
  return this.http.post("/lobbies", { gameType, betAmount });
11952
11986
  }
11953
11987
  async getLobby(lobbyId) {
11954
- return this.http.get(`/lobbies/${lobbyId}`);
11988
+ const lobby = await this.http.get(`/lobbies/${lobbyId}`);
11989
+ this.lobbyStore?.setBaseState([lobby]);
11990
+ return lobby;
11955
11991
  }
11956
11992
  async inviteFriend(lobbyId, friendId) {
11957
11993
  return this.http.post(`/lobbies/${lobbyId}/invite`, {
@@ -11962,7 +11998,9 @@ var Lobbies = class {
11962
11998
  return this.http.post(`/lobbies/${lobbyId}/accept-invite`, {});
11963
11999
  }
11964
12000
  async joinLobby(lobbyId) {
11965
- return this.http.post(`/lobbies/${lobbyId}/join`, {});
12001
+ const lobby = await this.http.post(`/lobbies/${lobbyId}/join`, {});
12002
+ this.lobbyStore?.setBaseState([lobby]);
12003
+ return lobby;
11966
12004
  }
11967
12005
  async removePlayer(lobbyId, userId) {
11968
12006
  return this.http.delete(
@@ -11979,12 +12017,17 @@ var Lobbies = class {
11979
12017
  return this.http.post(`/lobbies/${lobbyId}/join-queue`, {});
11980
12018
  }
11981
12019
  async cancelQueue(lobbyId) {
11982
- return this.http.delete(`/lobbies/${lobbyId}/queue`);
12020
+ const lobby = await this.http.delete(`/lobbies/${lobbyId}/queue`);
12021
+ this.lobbyStore?.setBaseState([lobby]);
12022
+ return lobby;
11983
12023
  }
11984
12024
  async updateBetAmount(lobbyId, betAmount) {
11985
- return this.http.patch(`/lobbies/${lobbyId}/bet-amount`, {
11986
- betAmount
11987
- });
12025
+ const lobby = await this.http.patch(
12026
+ `/lobbies/${lobbyId}/bet-amount`,
12027
+ { betAmount }
12028
+ );
12029
+ this.lobbyStore?.setBaseState([lobby]);
12030
+ return lobby;
11988
12031
  }
11989
12032
  async playSound(lobbyId, sound) {
11990
12033
  return this.http.post(`/lobbies/${lobbyId}/sound`, {
@@ -12023,6 +12066,12 @@ var Games = class {
12023
12066
  this.wallet = wallet;
12024
12067
  this.logger = logger2;
12025
12068
  }
12069
+ setGameStore(store) {
12070
+ this.gameStore = store;
12071
+ }
12072
+ setGameActionsStore(store) {
12073
+ this.gameActionsStore = store;
12074
+ }
12026
12075
  async getAvailableGames() {
12027
12076
  return this.http.get("/games/available");
12028
12077
  }
@@ -12035,7 +12084,11 @@ var Games = class {
12035
12084
  return this.http.get("/games/metrics");
12036
12085
  }
12037
12086
  async getGame(gameId) {
12038
- return this.http.get(`/games/${gameId}`);
12087
+ const existing = this.gameStore?.store.getState().gamesById[gameId];
12088
+ if (existing?.status === "completed") return existing;
12089
+ const game = await this.http.get(`/games/${gameId}`);
12090
+ this.gameStore?.setBaseState([game]);
12091
+ return game;
12039
12092
  }
12040
12093
  /**
12041
12094
  * Get list of currently active (live) games. Public endpoint for spectating.
@@ -12062,7 +12115,13 @@ var Games = class {
12062
12115
  * Get current game state with timer information
12063
12116
  */
12064
12117
  async getGameState(gameId) {
12065
- return this.http.get(`/games/${gameId}/state`);
12118
+ const existing = this.gameActionsStore?.store.getState().statesByGameId[gameId];
12119
+ if (existing?.status === "completed") return existing;
12120
+ const state = await this.http.get(
12121
+ `/games/${gameId}/state`
12122
+ );
12123
+ this.gameActionsStore?.setBaseState(gameId, state);
12124
+ return state;
12066
12125
  }
12067
12126
  /**
12068
12127
  * Request a rematch for a completed game
@@ -12098,8 +12157,18 @@ var Games = class {
12098
12157
  { amountMinor, signedTransaction }
12099
12158
  );
12100
12159
  }
12160
+ /**
12161
+ * Confirm a donation that was already sent by the client (signAndSendTransaction path).
12162
+ */
12163
+ async confirmGameDonationSignature(gameId, amountMinor, signature) {
12164
+ return this.http.post(
12165
+ `/games/${gameId}/donate/confirm-signature`,
12166
+ { amountMinor, signature }
12167
+ );
12168
+ }
12101
12169
  /**
12102
12170
  * One-call donation flow: prepare -> sign -> submit.
12171
+ * Automatically uses the right signing path (embedded vs injected wallet).
12103
12172
  */
12104
12173
  async sendDonation(gameId, amountMinor) {
12105
12174
  if (!this.wallet.hasSigner()) {
@@ -12108,16 +12177,10 @@ var Games = class {
12108
12177
  );
12109
12178
  }
12110
12179
  const prepared = await this.prepareGameDonation(gameId, amountMinor);
12111
- const unsignedTx = Transaction2.from(base64ToBytes(prepared.transaction));
12112
- const signedTx = await this.wallet.signTransaction(unsignedTx);
12113
- const signedTransaction = bytesToBase64(
12114
- signedTx.serialize({ requireAllSignatures: false })
12115
- );
12116
- const result = await this.donateToGame(
12117
- gameId,
12118
- amountMinor,
12119
- signedTransaction
12120
- );
12180
+ const result = await this.wallet.signAndDispatch(prepared.transaction, {
12181
+ onSigned: (signedTxBase64) => this.donateToGame(gameId, amountMinor, signedTxBase64),
12182
+ onSignedAndSent: (sig) => this.confirmGameDonationSignature(gameId, amountMinor, sig)
12183
+ });
12121
12184
  return {
12122
12185
  ...result,
12123
12186
  escrowAddress: prepared.escrowAddress,
@@ -12210,6 +12273,9 @@ var Chat = class {
12210
12273
  this.logger = logger2;
12211
12274
  this.retryOptions = { ...DEFAULT_RETRY_OPTIONS, ...retryOptions };
12212
12275
  }
12276
+ setDmThreadsStore(store) {
12277
+ this.dmThreadsStore = store;
12278
+ }
12213
12279
  encodeContextId(id) {
12214
12280
  return encodeURIComponent(id);
12215
12281
  }
@@ -12291,7 +12357,9 @@ var Chat = class {
12291
12357
  return response;
12292
12358
  }
12293
12359
  async listDmThreads() {
12294
- return this.http.get("/chat/dm/threads");
12360
+ const threads = await this.http.get("/chat/dm/threads");
12361
+ this.dmThreadsStore?.setBaseState(threads);
12362
+ return threads;
12295
12363
  }
12296
12364
  async getDmThread(dmKey) {
12297
12365
  return this.http.get(
@@ -12379,21 +12447,32 @@ var Tips = class {
12379
12447
  );
12380
12448
  }
12381
12449
  const { publicKey: senderAddress } = await this.wallet.loadWallet();
12382
- const prepared = await this.prepare({ recipientUsername, amount });
12383
- const unsignedTx = Transaction3.from(base64ToBytes(prepared.transaction));
12384
- const signedTx = await this.wallet.signTransaction(unsignedTx);
12385
- const signedTxBase64 = bytesToBase64(
12386
- signedTx.serialize({ requireAllSignatures: false })
12387
- );
12388
- const transfer = await this.wallet.submitTransfer(
12389
- signedTxBase64,
12390
- senderAddress,
12391
- prepared.recipientAddress,
12392
- prepared.amount,
12393
- "USDC",
12394
- false,
12395
- prepared.recipientUsername
12396
- );
12450
+ const supportsPresign = !this.wallet.isSignAndSendMode();
12451
+ const prepared = await this.prepare({
12452
+ recipientUsername,
12453
+ amount,
12454
+ supportsPresign
12455
+ });
12456
+ const transfer = await this.wallet.signAndDispatch(prepared.transaction, {
12457
+ onSigned: (signedTxBase64) => this.wallet.submitTransfer(
12458
+ signedTxBase64,
12459
+ senderAddress,
12460
+ prepared.recipientAddress,
12461
+ prepared.amount,
12462
+ "USDC",
12463
+ false,
12464
+ prepared.recipientUsername
12465
+ ),
12466
+ onSignedAndSent: (sig) => this.wallet.confirmTransferSignature(
12467
+ sig,
12468
+ senderAddress,
12469
+ prepared.recipientAddress,
12470
+ prepared.amount,
12471
+ "USDC",
12472
+ false,
12473
+ prepared.recipientUsername
12474
+ )
12475
+ });
12397
12476
  const message = await this.chat.broadcastGlobalTip(
12398
12477
  prepared.recipientUserId,
12399
12478
  prepared.amount
@@ -12711,13 +12790,15 @@ var Wallet = class {
12711
12790
  );
12712
12791
  }
12713
12792
  try {
12793
+ const supportsPresign = !this.isSignAndSendMode();
12714
12794
  const response = await this.http.post(
12715
12795
  "/wallets/transfer/prepare",
12716
12796
  {
12717
12797
  senderAddress,
12718
12798
  recipient,
12719
12799
  amount: amountMinor,
12720
- token
12800
+ token,
12801
+ supportsPresign
12721
12802
  }
12722
12803
  );
12723
12804
  this.logger.debug("Transfer prepared", {
@@ -12801,6 +12882,29 @@ var Wallet = class {
12801
12882
  throw error;
12802
12883
  }
12803
12884
  }
12885
+ /**
12886
+ * Sign a prepared transaction and invoke the appropriate backend callback
12887
+ * based on the configured signer — without exposing the mode decision to callers.
12888
+ * - Embedded wallet (signAndSend): signs+sends, calls onSignedAndSent(signature)
12889
+ * - Injected wallet (signTransaction): signs locally, calls onSigned(signedTxBase64)
12890
+ */
12891
+ async signAndDispatch(unsignedTxBase64, handlers) {
12892
+ if (!this.signer) {
12893
+ throw new Error(
12894
+ "No signer configured. Call setSigner() with a WalletSigner implementation first."
12895
+ );
12896
+ }
12897
+ const unsignedTx = Transaction2.from(base64ToBytes(unsignedTxBase64));
12898
+ if (this.isSignAndSendMode()) {
12899
+ const sig = await this.signAndSendTransaction(unsignedTx);
12900
+ return handlers.onSignedAndSent(sig);
12901
+ }
12902
+ const signedTx = await this.signTransaction(unsignedTx);
12903
+ const signedBase64 = bytesToBase64(
12904
+ signedTx.serialize({ requireAllSignatures: false })
12905
+ );
12906
+ return handlers.onSigned(signedBase64);
12907
+ }
12804
12908
  /**
12805
12909
  * Full transfer flow in one call: prepare -> sign -> submit
12806
12910
  * Recipient can be username, .sol domain, or Solana address (resolved by backend).
@@ -12817,7 +12921,7 @@ var Wallet = class {
12817
12921
  amount,
12818
12922
  token
12819
12923
  );
12820
- const unsignedTx = Transaction4.from(base64ToBytes(prepared.transaction));
12924
+ const unsignedTx = Transaction2.from(base64ToBytes(prepared.transaction));
12821
12925
  let submitted;
12822
12926
  if (this.isSignAndSendMode()) {
12823
12927
  const signature = await this.signAndSendTransaction(unsignedTx);
@@ -12882,12 +12986,32 @@ var Escrow = class {
12882
12986
  * initializes depositStatus, and prepares the unsigned transaction in one call.
12883
12987
  * Eliminates one HTTP round-trip vs startDeposits() + prepareDepositTransaction().
12884
12988
  */
12885
- async prepareAndStartDeposit(lobbyId) {
12989
+ async prepareAndStartDeposit(lobbyId, supportsPresign) {
12990
+ const presign = supportsPresign ?? !this.wallet.isSignAndSendMode();
12886
12991
  return this.http.post(
12887
12992
  `/escrow/lobby/${lobbyId}/deposit/prepare-and-start`,
12888
- {}
12993
+ { supportsPresign: presign }
12889
12994
  );
12890
12995
  }
12996
+ /**
12997
+ * Sign and submit a prepared (unsigned) deposit transaction using the
12998
+ * configured signer. Automatically picks the right path:
12999
+ * - Embedded wallet: signAndSendTransaction → confirmDepositSignature
13000
+ * - Injected wallet: signTransaction → submitDeposit
13001
+ * Returns the on-chain signature.
13002
+ */
13003
+ async signAndSubmitPreparedDeposit(lobbyId, unsignedTxBase64) {
13004
+ return this.wallet.signAndDispatch(unsignedTxBase64, {
13005
+ onSigned: async (signedTxBase64) => {
13006
+ const result = await this.submitDeposit(lobbyId, signedTxBase64);
13007
+ return result.signature;
13008
+ },
13009
+ onSignedAndSent: async (signature) => {
13010
+ await this.confirmDepositSignature(lobbyId, signature);
13011
+ return signature;
13012
+ }
13013
+ });
13014
+ }
12891
13015
  /**
12892
13016
  * Submit a signed deposit transaction
12893
13017
  * The transaction will be submitted to the Solana network and confirmed
@@ -12930,8 +13054,12 @@ var Escrow = class {
12930
13054
  "No signer configured. Use sdk.wallet.setSigner(...) first."
12931
13055
  );
12932
13056
  }
12933
- const { transaction } = await this.prepareAndStartDeposit(lobbyId);
12934
- const unsignedTx = Transaction5.from(base64ToBytes(transaction));
13057
+ const supportsPresign = !this.wallet.isSignAndSendMode();
13058
+ const { transaction } = await this.prepareAndStartDeposit(
13059
+ lobbyId,
13060
+ supportsPresign
13061
+ );
13062
+ const unsignedTx = Transaction3.from(base64ToBytes(transaction));
12935
13063
  let signature;
12936
13064
  if (this.wallet.isSignAndSendMode()) {
12937
13065
  signature = await this.wallet.signAndSendTransaction(unsignedTx);
@@ -12965,8 +13093,13 @@ var Escrow = class {
12965
13093
  };
12966
13094
  }
12967
13095
  /**
12968
- * Zero-polling deposit variant using server-side awaitConfirmation.
12969
- * 2 HTTP calls total, 0 client-side polling. Ideal for agents.
13096
+ * Deposit for a lobby and wait until the calling user's own deposit is confirmed.
13097
+ * Ideal for agents: returns as soon as your deposit is on-chain without waiting
13098
+ * for the other player. The server auto-joins the queue when all players deposit.
13099
+ *
13100
+ * Confirmation is handled asynchronously by the transaction queue processor.
13101
+ * This method polls the deposit status endpoint until the signature appears as
13102
+ * confirmed (up to 60 seconds).
12970
13103
  *
12971
13104
  * Automatically uses signAndSendTransaction or signTransaction based on signer capability.
12972
13105
  */
@@ -12976,26 +13109,45 @@ var Escrow = class {
12976
13109
  "No signer configured. Use sdk.wallet.setSigner(...) first."
12977
13110
  );
12978
13111
  }
12979
- const { transaction } = await this.prepareAndStartDeposit(lobbyId);
12980
- const unsignedTx = Transaction5.from(base64ToBytes(transaction));
13112
+ const supportsPresign2 = !this.wallet.isSignAndSendMode();
13113
+ const { transaction } = await this.prepareAndStartDeposit(
13114
+ lobbyId,
13115
+ supportsPresign2
13116
+ );
13117
+ const unsignedTx = Transaction3.from(base64ToBytes(transaction));
12981
13118
  let signature;
12982
13119
  if (this.wallet.isSignAndSendMode()) {
12983
13120
  signature = await this.wallet.signAndSendTransaction(unsignedTx);
12984
- await this.http.post(
12985
- `/escrow/lobby/${lobbyId}/deposit/confirm-signature?awaitConfirmation=true`,
12986
- { signature }
12987
- );
13121
+ await this.confirmDepositSignature(lobbyId, signature);
12988
13122
  } else {
12989
13123
  const signedTx = await this.wallet.signTransaction(unsignedTx);
12990
13124
  const signedBase64 = bytesToBase64(
12991
13125
  signedTx.serialize({ requireAllSignatures: false })
12992
13126
  );
12993
- const result = await this.http.post(`/escrow/lobby/${lobbyId}/deposit/submit?awaitConfirmation=true`, {
12994
- signedTransaction: signedBase64
12995
- });
12996
- signature = result.signature;
13127
+ const submitResult = await this.submitDeposit(lobbyId, signedBase64);
13128
+ signature = submitResult.signature;
13129
+ }
13130
+ const MAX_WAIT_MS = 6e4;
13131
+ const POLL_INTERVAL_MS = 1e3;
13132
+ const startTime = Date.now();
13133
+ while (Date.now() - startTime < MAX_WAIT_MS) {
13134
+ const status = await this.getDepositStatus(lobbyId);
13135
+ const myDeposit = status.deposits.find(
13136
+ (d) => d.transactionHash === signature
13137
+ );
13138
+ if (myDeposit?.status === "confirmed") {
13139
+ return {
13140
+ signature,
13141
+ status: "confirmed",
13142
+ canProceedToQueue: status.canProceedToQueue
13143
+ };
13144
+ }
13145
+ if (status.allConfirmed && status.canProceedToQueue) {
13146
+ return { signature, status: "confirmed", canProceedToQueue: true };
13147
+ }
13148
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
12997
13149
  }
12998
- return { signature, status: "confirmed", canProceedToQueue: true };
13150
+ return { signature, status: "pending", canProceedToQueue: false };
12999
13151
  }
13000
13152
  async claimLobbyDepositRefund(lobbyId, depositSignature) {
13001
13153
  return this.http.post(
@@ -13337,9 +13489,10 @@ var Support = class {
13337
13489
  }
13338
13490
  };
13339
13491
  var Markets = class {
13340
- constructor(http, logger2) {
13492
+ constructor(http, logger2, wallet) {
13341
13493
  this.http = http;
13342
13494
  this.logger = logger2;
13495
+ this.wallet = wallet;
13343
13496
  }
13344
13497
  /**
13345
13498
  * Get the prediction market state for a game.
@@ -13381,6 +13534,35 @@ var Markets = class {
13381
13534
  { signedTransaction, outcomeId, amountMinor }
13382
13535
  );
13383
13536
  }
13537
+ /**
13538
+ * Confirm a buy order that was already broadcast by the client (signAndSendTransaction path).
13539
+ */
13540
+ async confirmBuyOrderSignature(gameId, depositSignature, outcomeId, amountMinor) {
13541
+ return this.http.post(
13542
+ `/games/${gameId}/market/orders/buy/confirm-signature`,
13543
+ { depositSignature, outcomeId, amountMinor }
13544
+ );
13545
+ }
13546
+ /**
13547
+ * One-call buy order: prepare → sign → submit, automatically choosing
13548
+ * the right signing path (embedded vs injected wallet).
13549
+ */
13550
+ async buy(gameId, outcomeId, amountMinor) {
13551
+ if (!this.wallet?.hasSigner()) {
13552
+ throw new Error(
13553
+ "No signer configured. Use sdk.wallet.setSigner(...) first."
13554
+ );
13555
+ }
13556
+ const { transaction } = await this.prepareBuyOrder(
13557
+ gameId,
13558
+ outcomeId,
13559
+ amountMinor
13560
+ );
13561
+ return this.wallet.signAndDispatch(transaction, {
13562
+ onSigned: (signedTxBase64) => this.submitBuyOrder(gameId, signedTxBase64, outcomeId, amountMinor),
13563
+ onSignedAndSent: (sig) => this.confirmBuyOrderSignature(gameId, sig, outcomeId, amountMinor)
13564
+ });
13565
+ }
13384
13566
  /**
13385
13567
  * Sell shares back to the AMM pool.
13386
13568
  * @param gameId - The game ID
@@ -13429,6 +13611,20 @@ var Markets = class {
13429
13611
  return this.http.get(`/games/admin/markets${qs ? `?${qs}` : ""}`);
13430
13612
  }
13431
13613
  };
13614
+ var NoopAnalyticsClient = class {
13615
+ userLoggedIn(_user, _meta) {
13616
+ }
13617
+ userLoggedOut() {
13618
+ }
13619
+ sessionRestored(_user) {
13620
+ }
13621
+ track(_event, _properties) {
13622
+ }
13623
+ setUserProperties(_properties) {
13624
+ }
13625
+ group(_groupType, _groupKey, _properties) {
13626
+ }
13627
+ };
13432
13628
  var BaseWsTransport = class {
13433
13629
  constructor() {
13434
13630
  this.roomRefs = /* @__PURE__ */ new Map();
@@ -13516,21 +13712,35 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13516
13712
  this.accessToken = null;
13517
13713
  this.reconnectAttempts = 0;
13518
13714
  this.reconnectTimer = null;
13519
- this.periodicReconnectInterval = null;
13520
- this.maxReconnectAttempts = 5;
13521
- this.reconnectDelay = 1e3;
13522
- this.reconnectDelayMax = 3e4;
13715
+ this.needsReconnect = false;
13716
+ this.visibilityHandler = null;
13523
13717
  this.wildcardHandlers = /* @__PURE__ */ new Set();
13524
13718
  this.eventHandlers = /* @__PURE__ */ new Map();
13525
13719
  this.registeredEvents = /* @__PURE__ */ new Set();
13526
13720
  this.wildcardRegistered = false;
13527
13721
  this.url = url2;
13722
+ if (typeof document !== "undefined") {
13723
+ this.visibilityHandler = () => {
13724
+ if (document.visibilityState === "visible" && !this.connectionState.connected) {
13725
+ this.reconnectImmediately();
13726
+ }
13727
+ };
13728
+ document.addEventListener("visibilitychange", this.visibilityHandler);
13729
+ }
13528
13730
  }
13529
13731
  connect() {
13732
+ if (this.reconnectTimer !== null) {
13733
+ clearTimeout(this.reconnectTimer);
13734
+ this.reconnectTimer = null;
13735
+ }
13736
+ this.reconnectAttempts = 0;
13530
13737
  this.ensureSocket();
13531
13738
  }
13532
13739
  disconnect() {
13533
- this.clearPeriodicReconnect();
13740
+ if (this.visibilityHandler && typeof document !== "undefined") {
13741
+ document.removeEventListener("visibilitychange", this.visibilityHandler);
13742
+ this.visibilityHandler = null;
13743
+ }
13534
13744
  if (!this.socket) return;
13535
13745
  this.socket.disconnect();
13536
13746
  this.socket = null;
@@ -13629,13 +13839,13 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13629
13839
  reconnection: false
13630
13840
  });
13631
13841
  socket.on("connect", () => {
13632
- this.clearPeriodicReconnect();
13633
13842
  this.updateConnectionState({
13634
13843
  connected: true,
13635
13844
  connecting: false,
13636
13845
  error: null
13637
13846
  });
13638
- const wasReconnect = this.reconnectAttempts > 0;
13847
+ const wasReconnect = this.needsReconnect;
13848
+ this.needsReconnect = false;
13639
13849
  this.reconnectAttempts = 0;
13640
13850
  this.onReconnect();
13641
13851
  if (wasReconnect) {
@@ -13646,6 +13856,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13646
13856
  });
13647
13857
  socket.on("disconnect", (reason) => {
13648
13858
  this.updateConnectionState({ connected: false, connecting: false });
13859
+ this.needsReconnect = true;
13649
13860
  this.clearSocketForReconnect();
13650
13861
  if (reason === "io server disconnect") {
13651
13862
  this.handleAuthFailure("io server disconnect");
@@ -13655,6 +13866,7 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13655
13866
  });
13656
13867
  socket.on("connect_error", (error) => {
13657
13868
  const message = error?.message || "connect_error";
13869
+ this.needsReconnect = true;
13658
13870
  this.clearSocketForReconnect();
13659
13871
  if (message.includes("unauthorized") || message.includes("401")) {
13660
13872
  this.handleAuthFailure(message);
@@ -13682,31 +13894,31 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13682
13894
  this.socket.removeAllListeners();
13683
13895
  this.socket = null;
13684
13896
  }
13685
- clearPeriodicReconnect() {
13686
- if (this.periodicReconnectInterval !== null) {
13687
- clearInterval(this.periodicReconnectInterval);
13688
- this.periodicReconnectInterval = null;
13897
+ reconnectImmediately() {
13898
+ if (this.reconnectTimer !== null) {
13899
+ clearTimeout(this.reconnectTimer);
13900
+ this.reconnectTimer = null;
13689
13901
  }
13690
- }
13691
- startPeriodicReconnect() {
13692
- if (this.periodicReconnectInterval !== null) return;
13693
- this.periodicReconnectInterval = setInterval(() => {
13694
- if (this.connectionState.connected) return;
13695
- this.reconnectAttempts = 0;
13696
- this.ensureSocket();
13697
- }, _StandaloneWsTransport2.PERIODIC_RECONNECT_MS);
13902
+ this.reconnectAttempts = 0;
13903
+ this.ensureSocket();
13698
13904
  }
13699
13905
  scheduleReconnect() {
13700
13906
  if (this.reconnectTimer !== null) return;
13701
- if (this.reconnectAttempts >= this.maxReconnectAttempts) {
13702
- this.startPeriodicReconnect();
13703
- return;
13704
- }
13705
- const delay = Math.min(
13706
- this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
13707
- this.reconnectDelayMax
13708
- );
13907
+ const attempt = this.reconnectAttempts;
13709
13908
  this.reconnectAttempts += 1;
13909
+ let delay;
13910
+ if (attempt < _StandaloneWsTransport2.FAST_RETRY_LIMIT) {
13911
+ delay = _StandaloneWsTransport2.FAST_RETRY_DELAY_MS;
13912
+ } else {
13913
+ const backoffAttempt = attempt - _StandaloneWsTransport2.FAST_RETRY_LIMIT;
13914
+ delay = Math.min(
13915
+ _StandaloneWsTransport2.FAST_RETRY_DELAY_MS * Math.pow(2, backoffAttempt),
13916
+ _StandaloneWsTransport2.MAX_BACKOFF_MS
13917
+ );
13918
+ if (attempt === _StandaloneWsTransport2.FAST_RETRY_LIMIT) {
13919
+ this.dispatchEvent("connection:slow-retry", { timestamp: Date.now() });
13920
+ }
13921
+ }
13710
13922
  this.reconnectTimer = setTimeout(() => {
13711
13923
  this.reconnectTimer = null;
13712
13924
  this.ensureSocket();
@@ -13767,7 +13979,9 @@ var _StandaloneWsTransport = class _StandaloneWsTransport2 extends BaseWsTranspo
13767
13979
  this.wildcardRegistered = true;
13768
13980
  }
13769
13981
  };
13770
- _StandaloneWsTransport.PERIODIC_RECONNECT_MS = 5 * 60 * 1e3;
13982
+ _StandaloneWsTransport.FAST_RETRY_LIMIT = 60;
13983
+ _StandaloneWsTransport.FAST_RETRY_DELAY_MS = 1e3;
13984
+ _StandaloneWsTransport.MAX_BACKOFF_MS = 3e4;
13771
13985
  var StandaloneWsTransport = _StandaloneWsTransport;
13772
13986
  function createSdkStore(initial) {
13773
13987
  const store = createStore()(subscribeWithSelector(() => initial));
@@ -13788,14 +14002,16 @@ function createLobbyStore(transport2) {
13788
14002
  depositStatusByLobbyId: {}
13789
14003
  });
13790
14004
  const setBaseState = (lobbies) => {
13791
- const lobbiesById = {};
13792
- for (const lobby of lobbies) {
13793
- lobbiesById[lobby.id] = lobby;
13794
- }
13795
- store.updateState((state) => ({
13796
- ...state,
13797
- lobbiesById
13798
- }));
14005
+ store.updateState((state) => {
14006
+ const lobbiesById = { ...state.lobbiesById };
14007
+ for (const lobby of lobbies) {
14008
+ const existing = lobbiesById[lobby.id];
14009
+ if (!existing || lobby.updatedAt >= existing.updatedAt) {
14010
+ lobbiesById[lobby.id] = lobby;
14011
+ }
14012
+ }
14013
+ return { ...state, lobbiesById };
14014
+ });
13799
14015
  };
13800
14016
  const applyWsEvent = (event) => {
13801
14017
  switch (event.event) {
@@ -13925,12 +14141,23 @@ function createGameStore(transport2) {
13925
14141
  gamesById: {},
13926
14142
  spectatorCounts: {}
13927
14143
  });
14144
+ const STATUS_RANK = {
14145
+ active: 0,
14146
+ completed: 1,
14147
+ abandoned: 1
14148
+ };
13928
14149
  const setBaseState = (games) => {
13929
- const gamesById = {};
13930
- for (const game of games) {
13931
- gamesById[game.gameId] = game;
13932
- }
13933
- store.updateState((state) => ({ ...state, gamesById }));
14150
+ store.updateState((state) => {
14151
+ const gamesById = { ...state.gamesById };
14152
+ for (const game of games) {
14153
+ const existing = gamesById[game.gameId];
14154
+ if (existing && STATUS_RANK[existing.status] > STATUS_RANK[game.status]) {
14155
+ continue;
14156
+ }
14157
+ gamesById[game.gameId] = game;
14158
+ }
14159
+ return { ...state, gamesById };
14160
+ });
13934
14161
  };
13935
14162
  const applyWsEvent = (event) => {
13936
14163
  switch (event.event) {
@@ -14668,7 +14895,38 @@ function createNotificationsStore() {
14668
14895
  appNotifications: []
14669
14896
  }));
14670
14897
  };
14671
- return { store, applyWsEvent, setListFromApi, clear };
14898
+ const markAsRead = (id) => {
14899
+ store.updateState((state) => ({
14900
+ ...state,
14901
+ appNotifications: state.appNotifications.map(
14902
+ (n) => n.id === id ? { ...n, read: true } : n
14903
+ )
14904
+ }));
14905
+ };
14906
+ const markAllAsRead = () => {
14907
+ store.updateState((state) => ({
14908
+ ...state,
14909
+ appNotifications: state.appNotifications.map((n) => ({
14910
+ ...n,
14911
+ read: true
14912
+ }))
14913
+ }));
14914
+ };
14915
+ const dismiss = (id) => {
14916
+ store.updateState((state) => ({
14917
+ ...state,
14918
+ appNotifications: state.appNotifications.filter((n) => n.id !== id)
14919
+ }));
14920
+ };
14921
+ return {
14922
+ store,
14923
+ applyWsEvent,
14924
+ setListFromApi,
14925
+ clear,
14926
+ markAsRead,
14927
+ markAllAsRead,
14928
+ dismiss
14929
+ };
14672
14930
  }
14673
14931
  function createFriendsStore() {
14674
14932
  const store = createSdkStore({
@@ -15015,6 +15273,7 @@ var SDK = class {
15015
15273
  constructor(config) {
15016
15274
  const baseUrl = config.baseUrl || "http://localhost:3000";
15017
15275
  const logger2 = config.logger || logger;
15276
+ this.analytics = config.analytics ?? new NoopAnalyticsClient();
15018
15277
  this.http = config.httpClient || new HttpClient(
15019
15278
  baseUrl,
15020
15279
  config.storage,
@@ -15047,14 +15306,18 @@ var SDK = class {
15047
15306
  this.referrals = new Referrals(this.http, logger2);
15048
15307
  this.reports = new Reports(this.http, logger2);
15049
15308
  this.support = new Support(this.http, logger2);
15050
- this.markets = new Markets(this.http, logger2);
15309
+ this.markets = new Markets(this.http, logger2, this.wallet);
15051
15310
  this.wsTransport = config.wsTransport || new StandaloneWsTransport(baseUrl);
15052
15311
  this.wsTransport.setAppId(config.appId);
15053
15312
  this.lobbyStore = createLobbyStore(this.wsTransport);
15313
+ this.lobbies.setLobbyStore(this.lobbyStore);
15054
15314
  this.gameStore = createGameStore(this.wsTransport);
15315
+ this.games.setGameStore(this.gameStore);
15055
15316
  this.gameActionsStore = createGameActionsStore(this.wsTransport);
15317
+ this.games.setGameActionsStore(this.gameActionsStore);
15056
15318
  this.chatStore = createChatStore(this.wsTransport);
15057
15319
  this.dmThreadsStore = createDmThreadsStore();
15320
+ this.chat.setDmThreadsStore(this.dmThreadsStore);
15058
15321
  this.notificationsStore = createNotificationsStore();
15059
15322
  this.friendsStore = createFriendsStore();
15060
15323
  this.notifications = new Notifications(
@@ -15084,6 +15347,29 @@ var SDK = class {
15084
15347
  this.wsTransport.connect();
15085
15348
  await this.wsTransport.waitUntilConnected(timeoutMs);
15086
15349
  }
15350
+ /**
15351
+ * Handle the full deposit-to-queue lifecycle for a lobby.
15352
+ *
15353
+ * After the deposit is confirmed, the backend may not have processed the
15354
+ * `lobby.deposit.allConfirmed` event yet, so the lobby can still be in
15355
+ * 'preparing' status. This method re-fetches the lobby and explicitly
15356
+ * joins the queue if needed, then pushes the latest state to the store
15357
+ * so the UI transitions immediately.
15358
+ */
15359
+ async depositAndJoinQueue(lobbyId) {
15360
+ const result = await this.escrow.depositForLobby(lobbyId);
15361
+ if (!result.canProceedToQueue) {
15362
+ const lobby2 = await this.lobbies.getLobby(lobbyId);
15363
+ this.lobbyStore.setBaseState([lobby2]);
15364
+ return { ...result, lobby: lobby2 };
15365
+ }
15366
+ let lobby = await this.lobbies.getLobby(lobbyId);
15367
+ if (lobby.status === "preparing") {
15368
+ lobby = await this.lobbies.joinQueue(lobbyId);
15369
+ }
15370
+ this.lobbyStore.setBaseState([lobby]);
15371
+ return { ...result, lobby };
15372
+ }
15087
15373
  };
15088
15374
  var import_utils = __toESM2(require_dist(), 1);
15089
15375
  var export_MICRO_UNITS = import_utils.MICRO_UNITS;
@@ -15097,7 +15383,9 @@ import bs58 from "bs58";
15097
15383
  var DimAgentClient = class {
15098
15384
  sdk;
15099
15385
  agentConfig;
15386
+ externalSignerMode;
15100
15387
  keypair;
15388
+ _externalAddress = null;
15101
15389
  config;
15102
15390
  authenticated = false;
15103
15391
  userId = null;
@@ -15111,21 +15399,26 @@ var DimAgentClient = class {
15111
15399
  constructor(config) {
15112
15400
  this.config = config;
15113
15401
  this.agentConfig = config.agentConfig;
15114
- const secretKeyBytes = bs58.decode(config.walletPrivateKey);
15115
- this.keypair = Keypair.fromSecretKey(secretKeyBytes);
15402
+ this.externalSignerMode = !config.walletPrivateKey;
15403
+ if (config.walletPrivateKey) {
15404
+ const secretKeyBytes = bs58.decode(config.walletPrivateKey);
15405
+ this.keypair = Keypair.fromSecretKey(secretKeyBytes);
15406
+ } else {
15407
+ this.keypair = null;
15408
+ }
15116
15409
  this.sdk = new SDK({
15117
15410
  appId: "dim-agents",
15118
15411
  baseUrl: config.apiUrl || "https://api.dim.cool",
15119
15412
  storage: new NodeStorage(),
15120
15413
  autoPay: {
15121
- enabled: true,
15414
+ enabled: !this.externalSignerMode,
15122
15415
  maxAmountMinor: 25e3,
15123
15416
  maxRetries: 1
15124
15417
  }
15125
15418
  });
15126
15419
  }
15127
15420
  get walletAddress() {
15128
- return this.keypair.publicKey.toBase58();
15421
+ return this.keypair?.publicKey.toBase58() ?? this._externalAddress ?? "";
15129
15422
  }
15130
15423
  get isAuthenticated() {
15131
15424
  return this.authenticated;
@@ -15134,17 +15427,23 @@ var DimAgentClient = class {
15134
15427
  return this.userId;
15135
15428
  }
15136
15429
  async authenticate() {
15430
+ if (!this.keypair) {
15431
+ throw new Error(
15432
+ "No keypair configured. Use dim_request_auth_message + dim_complete_login for external signer mode."
15433
+ );
15434
+ }
15435
+ const keypair = this.keypair;
15137
15436
  this.sdk.wallet.setSigner({
15138
15437
  address: this.walletAddress,
15139
15438
  signMessage: async (message) => {
15140
15439
  const signature = import_tweetnacl.default.sign.detached(
15141
15440
  new TextEncoder().encode(message),
15142
- this.keypair.secretKey
15441
+ keypair.secretKey
15143
15442
  );
15144
15443
  return Buffer.from(signature).toString("base64");
15145
15444
  },
15146
15445
  signTransaction: async (transaction) => {
15147
- transaction.partialSign(this.keypair);
15446
+ transaction.partialSign(keypair);
15148
15447
  return transaction;
15149
15448
  }
15150
15449
  });
@@ -15198,10 +15497,45 @@ var DimAgentClient = class {
15198
15497
  get pendingEventCount() {
15199
15498
  return this.eventQueue.length;
15200
15499
  }
15201
- /** Get the Keypair for transaction signing. */
15500
+ /** Get the Keypair for transaction signing (keypair mode only). */
15202
15501
  getKeypair() {
15502
+ if (!this.keypair) {
15503
+ throw new Error(
15504
+ "No keypair configured \u2014 running in external signer mode."
15505
+ );
15506
+ }
15203
15507
  return this.keypair;
15204
15508
  }
15509
+ /** Request the auth handshake message for a given address (external signer mode). */
15510
+ async requestAuthMessage(address) {
15511
+ return this.sdk.auth.generateHandshake(address);
15512
+ }
15513
+ /**
15514
+ * Complete authentication using an externally provided signature (external signer mode).
15515
+ * @param address - Solana wallet address (base58)
15516
+ * @param signatureBase58 - Detached ed25519 signature in base58 (from sign_solana_message)
15517
+ */
15518
+ async completeAuth(address, signatureBase58) {
15519
+ const signatureBytes = bs58.decode(signatureBase58);
15520
+ const signedMessage = Buffer.from(signatureBytes).toString("base64");
15521
+ const response = await this.sdk.auth.loginWithExternalSignature(
15522
+ address,
15523
+ signedMessage,
15524
+ {
15525
+ referralCode: this.config.referralCode,
15526
+ walletMeta: { type: "phantom-embedded", provider: "injected" }
15527
+ }
15528
+ );
15529
+ this.sdk.wsTransport.setAccessToken(response.access_token);
15530
+ this._externalAddress = address;
15531
+ this.authenticated = true;
15532
+ this.userId = response.user.id;
15533
+ return {
15534
+ userId: response.user.id,
15535
+ username: response.user.username,
15536
+ accessToken: response.access_token
15537
+ };
15538
+ }
15205
15539
  // ── Game chat cursors ────────────────────────────────────────────────
15206
15540
  /** Get the last-seen chat timestamp for a game. */
15207
15541
  getGameChatCursor(gameId) {
@@ -15329,6 +15663,77 @@ async function login(client) {
15329
15663
  };
15330
15664
  }
15331
15665
  }
15666
+ async function requestAuthMessage(client, args) {
15667
+ try {
15668
+ const { message } = await client.requestAuthMessage(args.address);
15669
+ return {
15670
+ data: {
15671
+ message,
15672
+ address: args.address,
15673
+ nextStep: 'Sign this message with sign_solana_message (networkId: "solana:mainnet"), then call dim_complete_login with the address and the base58 signature.'
15674
+ }
15675
+ };
15676
+ } catch (error) {
15677
+ return {
15678
+ error: `Failed to get auth message: ${error instanceof Error ? error.message : String(error)}`,
15679
+ isError: true
15680
+ };
15681
+ }
15682
+ }
15683
+ async function completeLogin(client, args) {
15684
+ try {
15685
+ const result = await client.completeAuth(args.address, args.signature);
15686
+ client.startEventListeners();
15687
+ const nextSteps = [];
15688
+ if (result.username == null || result.username === "") {
15689
+ nextSteps.push("No username set \u2014 call dim_set_username to claim one");
15690
+ }
15691
+ nextSteps.push("Check your balance with dim_get_balance");
15692
+ nextSteps.push("Explore available games with dim_list_games");
15693
+ try {
15694
+ const summary = await client.sdk.referrals.getSummary();
15695
+ if (!summary.hasReferrer) {
15696
+ nextSteps.push(
15697
+ "No referrer yet \u2014 call dim_apply_referral_code for 10% fee discount"
15698
+ );
15699
+ }
15700
+ if (result.username) {
15701
+ nextSteps.push(
15702
+ `Share your referral code "${result.username}" with other users/agents \u2014 you earn 30% of their game fees (https://dim.cool/?ref=${result.username})`
15703
+ );
15704
+ }
15705
+ } catch {
15706
+ }
15707
+ const response = {
15708
+ success: true,
15709
+ userId: result.userId,
15710
+ username: result.username ?? null,
15711
+ walletAddress: client.walletAddress,
15712
+ walletNote: "DIM is noncustodial. Signing is handled by your external wallet for this session.",
15713
+ safetyRules: SAFETY_RULES,
15714
+ nextSteps
15715
+ };
15716
+ const ac = client.agentConfig;
15717
+ const dailyLimit = ac?.dailySpendLimit ?? 20;
15718
+ response.agentConfig = {
15719
+ autoAcceptFriendRequests: ac?.autoAcceptFriendRequests ?? false,
15720
+ autoReplyDms: ac?.autoReplyDms ?? false,
15721
+ autoPlayGames: ac?.autoPlayGames ?? false,
15722
+ maxBetPerGame: ac?.maxBetPerGame ?? 1,
15723
+ dailySpendLimit: dailyLimit,
15724
+ autoJoinGlobalChat: ac?.autoJoinGlobalChat ?? false,
15725
+ autoPromoteReferrals: ac?.autoPromoteReferrals ?? false,
15726
+ dailySpentSoFar: client.dailySpentDollars,
15727
+ dailyRemaining: dailyLimit - client.dailySpentDollars
15728
+ };
15729
+ return { data: response };
15730
+ } catch (error) {
15731
+ return {
15732
+ error: `Login failed: ${error instanceof Error ? error.message : String(error)}`,
15733
+ isError: true
15734
+ };
15735
+ }
15736
+ }
15332
15737
  async function getProfile(client) {
15333
15738
  try {
15334
15739
  if (!client.currentUserId) {
@@ -15457,10 +15862,19 @@ async function listFriends(client, args) {
15457
15862
  };
15458
15863
  }
15459
15864
  }
15460
- async function getIncomingFriendRequests(client) {
15865
+ async function getIncomingFriendRequests(client, args) {
15461
15866
  try {
15462
- const result = await client.sdk.users.getIncomingFriendRequests();
15463
- return { data: result };
15867
+ const result = await client.sdk.users.getIncomingFriendRequests({
15868
+ limit: args?.limit,
15869
+ cursor: args?.cursor
15870
+ });
15871
+ return {
15872
+ data: {
15873
+ items: result.items,
15874
+ nextCursor: result.nextCursor,
15875
+ hasMore: !!result.nextCursor
15876
+ }
15877
+ };
15464
15878
  } catch (error) {
15465
15879
  return {
15466
15880
  error: `Failed to get requests: ${error instanceof Error ? error.message : String(error)}`,
@@ -15581,6 +15995,42 @@ async function sendUsdc(client, args) {
15581
15995
  const spendErr = client.checkSpendLimit(args.amount);
15582
15996
  if (spendErr) return { error: spendErr, isError: true };
15583
15997
  const amountMinor = Math.round(args.amount * 1e6);
15998
+ if (client.externalSignerMode) {
15999
+ const senderAddress = client.walletAddress;
16000
+ if (!senderAddress) {
16001
+ return {
16002
+ error: "Wallet address not set. Call dim_complete_login first.",
16003
+ isError: true
16004
+ };
16005
+ }
16006
+ const prepared = await client.sdk.wallet.prepareTransfer(
16007
+ senderAddress,
16008
+ args.recipient,
16009
+ amountMinor
16010
+ );
16011
+ return {
16012
+ data: {
16013
+ needsSigning: true,
16014
+ unsignedTx: prepared.transaction,
16015
+ fee: prepared.fee,
16016
+ totalAmount: prepared.totalAmount,
16017
+ recipientAddress: prepared.recipientAddress,
16018
+ ataCreated: prepared.ataCreated ?? false,
16019
+ confirmWith: {
16020
+ tool: "dim_confirm_send_usdc",
16021
+ params: {
16022
+ recipientAddress: prepared.recipientAddress,
16023
+ amount: amountMinor,
16024
+ fee: prepared.fee,
16025
+ token: "USDC",
16026
+ ataCreated: prepared.ataCreated ?? false,
16027
+ recipientInput: args.recipient
16028
+ }
16029
+ },
16030
+ hint: "Sign and broadcast unsignedTx with send_solana_transaction, then call dim_confirm_send_usdc with the signature and the confirmWith.params."
16031
+ }
16032
+ };
16033
+ }
15584
16034
  const result = await client.sdk.wallet.send(args.recipient, amountMinor);
15585
16035
  client.recordSpend(amountMinor);
15586
16036
  return {
@@ -15601,11 +16051,74 @@ async function sendUsdc(client, args) {
15601
16051
  };
15602
16052
  }
15603
16053
  }
16054
+ async function confirmSendUsdc(client, args) {
16055
+ try {
16056
+ const senderAddress = client.walletAddress;
16057
+ const result = await client.sdk.wallet.confirmTransferSignature(
16058
+ args.signature,
16059
+ senderAddress,
16060
+ args.recipientAddress,
16061
+ args.amount,
16062
+ args.token || "USDC",
16063
+ args.ataCreated,
16064
+ args.recipientInput
16065
+ );
16066
+ client.recordSpend(args.amount);
16067
+ return {
16068
+ data: {
16069
+ success: true,
16070
+ signature: result.signature,
16071
+ status: result.status,
16072
+ recipientAddress: args.recipientAddress
16073
+ }
16074
+ };
16075
+ } catch (error) {
16076
+ return {
16077
+ error: `Failed to confirm USDC transfer: ${error instanceof Error ? error.message : String(error)}`,
16078
+ isError: true
16079
+ };
16080
+ }
16081
+ }
15604
16082
  async function tipUser(client, args) {
15605
16083
  try {
15606
16084
  const spendErr = client.checkSpendLimit(args.amount);
15607
16085
  if (spendErr) return { error: spendErr, isError: true };
15608
16086
  const amountMinor = Math.round(args.amount * 1e6);
16087
+ if (client.externalSignerMode) {
16088
+ const senderAddress = client.walletAddress;
16089
+ if (!senderAddress) {
16090
+ return {
16091
+ error: "Wallet address not set. Call dim_complete_login first.",
16092
+ isError: true
16093
+ };
16094
+ }
16095
+ const prepared = await client.sdk.tips.prepare({
16096
+ recipientUsername: args.recipientUsername,
16097
+ amount: amountMinor,
16098
+ supportsPresign: false
16099
+ });
16100
+ return {
16101
+ data: {
16102
+ needsSigning: true,
16103
+ unsignedTx: prepared.transaction,
16104
+ fee: prepared.fee,
16105
+ totalAmount: prepared.totalAmount,
16106
+ recipientAddress: prepared.recipientAddress,
16107
+ confirmWith: {
16108
+ tool: "dim_confirm_tip_user",
16109
+ params: {
16110
+ recipientAddress: prepared.recipientAddress,
16111
+ recipientUserId: prepared.recipientUserId,
16112
+ recipientUsername: prepared.recipientUsername,
16113
+ amount: prepared.amount,
16114
+ fee: prepared.fee,
16115
+ ataCreated: false
16116
+ }
16117
+ },
16118
+ hint: "Sign and broadcast unsignedTx with send_solana_transaction, then call dim_confirm_tip_user with the signature and the confirmWith.params."
16119
+ }
16120
+ };
16121
+ }
15609
16122
  const result = await client.sdk.tips.send(
15610
16123
  args.recipientUsername,
15611
16124
  amountMinor
@@ -15628,6 +16141,38 @@ async function tipUser(client, args) {
15628
16141
  };
15629
16142
  }
15630
16143
  }
16144
+ async function confirmTipUser(client, args) {
16145
+ try {
16146
+ const senderAddress = client.walletAddress;
16147
+ await client.sdk.wallet.confirmTransferSignature(
16148
+ args.signature,
16149
+ senderAddress,
16150
+ args.recipientAddress,
16151
+ args.amount,
16152
+ "USDC",
16153
+ args.ataCreated ?? false,
16154
+ args.recipientUsername
16155
+ );
16156
+ await client.sdk.tips.broadcast({
16157
+ recipientUserId: args.recipientUserId,
16158
+ amount: args.amount
16159
+ });
16160
+ client.recordSpend(args.amount);
16161
+ return {
16162
+ data: {
16163
+ success: true,
16164
+ signature: args.signature,
16165
+ recipient: args.recipientUsername,
16166
+ broadcastedToGlobalChat: true
16167
+ }
16168
+ };
16169
+ } catch (error) {
16170
+ return {
16171
+ error: `Failed to confirm tip: ${error instanceof Error ? error.message : String(error)}`,
16172
+ isError: true
16173
+ };
16174
+ }
16175
+ }
15631
16176
  async function getWalletActivity(client, args) {
15632
16177
  try {
15633
16178
  const activity = await client.sdk.wallet.getActivity({
@@ -15734,6 +16279,7 @@ function buildRpsContext(state, agentUserId) {
15734
16279
  roundHistory: state.roundHistory,
15735
16280
  phase: roundState?.phase,
15736
16281
  timeRemaining: roundState?.timeRemaining,
16282
+ ...state.bufferEndsAt != null && { bufferEndsAt: state.bufferEndsAt },
15737
16283
  moveFormat: 'dim_submit_action: gameType="rock-paper-scissors", action="play", payload={ action: "rock"|"paper"|"scissors" }'
15738
16284
  };
15739
16285
  }
@@ -15746,6 +16292,7 @@ function buildChessContext(state, agentUserId) {
15746
16292
  yourColor,
15747
16293
  whiteTimeMs: state.whiteTimeMs,
15748
16294
  blackTimeMs: state.blackTimeMs,
16295
+ ...state.bufferEndsAt != null && { bufferEndsAt: state.bufferEndsAt },
15749
16296
  moveFormat: 'dim_submit_action: gameType="chess", action="move", payload={ from: "e2", to: "e4" }'
15750
16297
  };
15751
16298
  }
@@ -15955,6 +16502,23 @@ async function createLobby(client, args) {
15955
16502
  }
15956
16503
  async function depositForLobby(client, args) {
15957
16504
  try {
16505
+ if (client.externalSignerMode) {
16506
+ const { transaction } = await client.sdk.escrow.prepareAndStartDeposit(
16507
+ args.lobbyId,
16508
+ false
16509
+ );
16510
+ return {
16511
+ data: {
16512
+ needsSigning: true,
16513
+ unsignedTx: transaction,
16514
+ confirmWith: {
16515
+ tool: "dim_confirm_lobby_deposit",
16516
+ params: { lobbyId: args.lobbyId }
16517
+ },
16518
+ hint: "Sign and broadcast unsignedTx with send_solana_transaction, then call dim_confirm_lobby_deposit with the lobbyId and signature."
16519
+ }
16520
+ };
16521
+ }
15958
16522
  const result = await client.sdk.escrow.depositForLobbySync(args.lobbyId);
15959
16523
  return {
15960
16524
  data: {
@@ -15971,6 +16535,44 @@ async function depositForLobby(client, args) {
15971
16535
  };
15972
16536
  }
15973
16537
  }
16538
+ async function confirmLobbyDeposit(client, args) {
16539
+ try {
16540
+ await client.sdk.escrow.confirmDepositSignature(
16541
+ args.lobbyId,
16542
+ args.signature
16543
+ );
16544
+ const MAX_WAIT_MS = 6e4;
16545
+ const POLL_INTERVAL_MS = 1e3;
16546
+ const startTime = Date.now();
16547
+ while (Date.now() - startTime < MAX_WAIT_MS) {
16548
+ const status = await client.sdk.escrow.getDepositStatus(args.lobbyId);
16549
+ if (status.canProceedToQueue) {
16550
+ return {
16551
+ data: {
16552
+ signature: args.signature,
16553
+ status: "confirmed",
16554
+ canProceedToQueue: true,
16555
+ hint: "Deposit confirmed. Call dim_join_queue to enter matchmaking."
16556
+ }
16557
+ };
16558
+ }
16559
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
16560
+ }
16561
+ return {
16562
+ data: {
16563
+ signature: args.signature,
16564
+ status: "pending",
16565
+ canProceedToQueue: false,
16566
+ hint: "Deposit submitted but not yet confirmed on-chain. Try dim_confirm_lobby_deposit again in a few seconds."
16567
+ }
16568
+ };
16569
+ } catch (error) {
16570
+ return {
16571
+ error: `Failed to confirm deposit: ${error instanceof Error ? error.message : String(error)}`,
16572
+ isError: true
16573
+ };
16574
+ }
16575
+ }
15974
16576
  async function leaveLobby(client, args) {
15975
16577
  try {
15976
16578
  const result = await client.sdk.lobbies.leaveLobby(args.lobbyId);
@@ -16040,7 +16642,7 @@ async function joinQueue(client, args) {
16040
16642
  gameId,
16041
16643
  matched: !!matched,
16042
16644
  ...spectateUrl && { spectateUrl },
16043
- hint: matched ? `Game started! Call dim_game_loop with gameId "${gameId}" to play.${spectateUrl ? ` Tell the user they can spectate at ${spectateUrl}` : ""}` : "No match found within timeout. Call dim_join_queue again to resume waiting."
16645
+ hint: matched ? `Game matched! Call dim_game_loop with gameId "${gameId}" IMMEDIATELY \u2014 do NOT wait for user input. The game has a start buffer; dim_game_loop will block until your first turn begins.${spectateUrl ? ` Tell the user they can spectate at ${spectateUrl}` : ""}` : "No match found within timeout. Call dim_join_queue again to resume waiting."
16044
16646
  }
16045
16647
  };
16046
16648
  } catch (error) {
@@ -16115,6 +16717,23 @@ async function donateToPot(client, args) {
16115
16717
  const spendErr = client.checkSpendLimit(args.amount);
16116
16718
  if (spendErr) return { error: spendErr, isError: true };
16117
16719
  const amountMinor = Math.round(args.amount * 1e6);
16720
+ if (client.externalSignerMode) {
16721
+ const prepared = await client.sdk.games.prepareGameDonation(
16722
+ args.gameId,
16723
+ amountMinor
16724
+ );
16725
+ return {
16726
+ data: {
16727
+ needsSigning: true,
16728
+ unsignedTx: prepared.transaction,
16729
+ confirmWith: {
16730
+ tool: "dim_confirm_donate_to_pot",
16731
+ params: { gameId: args.gameId, amount: amountMinor }
16732
+ },
16733
+ hint: "Sign and broadcast unsignedTx with send_solana_transaction, then call dim_confirm_donate_to_pot with the signature."
16734
+ }
16735
+ };
16736
+ }
16118
16737
  const result = await client.sdk.games.sendDonation(
16119
16738
  args.gameId,
16120
16739
  amountMinor
@@ -16138,6 +16757,29 @@ async function donateToPot(client, args) {
16138
16757
  };
16139
16758
  }
16140
16759
  }
16760
+ async function confirmDonateToPot(client, args) {
16761
+ try {
16762
+ const result = await client.sdk.games.confirmGameDonationSignature(
16763
+ args.gameId,
16764
+ args.amount,
16765
+ args.signature
16766
+ );
16767
+ client.recordSpend(args.amount);
16768
+ return {
16769
+ data: {
16770
+ success: true,
16771
+ gameId: args.gameId,
16772
+ signature: result.signature,
16773
+ status: result.status
16774
+ }
16775
+ };
16776
+ } catch (error) {
16777
+ return {
16778
+ error: `Failed to confirm donation: ${error instanceof Error ? error.message : String(error)}`,
16779
+ isError: true
16780
+ };
16781
+ }
16782
+ }
16141
16783
  async function getGame(client, args) {
16142
16784
  try {
16143
16785
  const game = await client.sdk.games.getGame(args.gameId);
@@ -16149,6 +16791,12 @@ async function getGame(client, args) {
16149
16791
  };
16150
16792
  }
16151
16793
  }
16794
+ function isInStartingPhase(state) {
16795
+ const roundState = state.roundState;
16796
+ if (roundState?.phase === "starting") return true;
16797
+ if (state.status === "active" && state.currentPlayerId == null) return true;
16798
+ return false;
16799
+ }
16152
16800
  async function gameLoop(client, args) {
16153
16801
  try {
16154
16802
  const { gameId } = args;
@@ -16166,7 +16814,7 @@ async function gameLoop(client, args) {
16166
16814
  if (state?.status === "completed") {
16167
16815
  return buildGameLoopReturn(client, gameId, state, "completed");
16168
16816
  }
16169
- if (state?.currentPlayerId === client.currentUserId) {
16817
+ if (state?.currentPlayerId === client.currentUserId && !isInStartingPhase(state)) {
16170
16818
  return buildGameLoopReturn(client, gameId, state, "your-turn");
16171
16819
  }
16172
16820
  await raceTimeout(
@@ -16792,10 +17440,10 @@ async function checkNotifications(client) {
16792
17440
  isError: true
16793
17441
  };
16794
17442
  }
16795
- const [notifications, dmThreads, friendRequests] = await Promise.all([
17443
+ const [notifications, dmThreads, friendRequestsPage] = await Promise.all([
16796
17444
  client.sdk.notifications.list({ page: 1, limit: 20 }),
16797
17445
  client.sdk.chat.listDmThreads(),
16798
- client.sdk.users.getIncomingFriendRequests()
17446
+ client.sdk.users.getIncomingFriendRequests({ limit: 20 })
16799
17447
  ]);
16800
17448
  const unreadDms = dmThreads.filter(
16801
17449
  (t) => (t.unreadCount ?? 0) > 0
@@ -16807,9 +17455,10 @@ async function checkNotifications(client) {
16807
17455
  unreadNotificationCount: notifications.unreadCount,
16808
17456
  notifications: notifications.notifications.filter((n) => !n.read),
16809
17457
  unreadDmThreads: unreadDms,
16810
- incomingFriendRequests: friendRequests,
17458
+ incomingFriendRequests: friendRequestsPage.items,
17459
+ hasMoreIncomingFriendRequests: !!friendRequestsPage.nextCursor,
16811
17460
  pendingWsEvents: client.pendingEventCount,
16812
- hint: "Use dim_get_pending_events to drain buffered real-time events."
17461
+ hint: "Use dim_get_pending_events to drain buffered real-time events. Use dim_get_incoming_friend_requests with cursor for more friend requests if hasMoreIncomingFriendRequests is true."
16813
17462
  }
16814
17463
  };
16815
17464
  } catch (error) {
@@ -17225,6 +17874,36 @@ async function getMyStats(client) {
17225
17874
 
17226
17875
  // ../dim-agent-core/src/tools/index.ts
17227
17876
  var TOOL_DEFINITIONS = [
17877
+ // ── External signer mode (auth) ──────────────────────────────────────
17878
+ {
17879
+ name: "dim_request_auth_message",
17880
+ description: "External wallet login step 1: given a Solana wallet address, returns the message to sign. Sign it with sign_solana_message on your wallet MCP (e.g. Phantom), then call dim_complete_login.",
17881
+ params: {
17882
+ address: {
17883
+ type: "string",
17884
+ description: "Your Solana wallet address (base58)",
17885
+ required: true
17886
+ }
17887
+ },
17888
+ execute: (c, a) => requestAuthMessage(c, a)
17889
+ },
17890
+ {
17891
+ name: "dim_complete_login",
17892
+ description: "External wallet login step 2: provide the wallet address and base58 signature from sign_solana_message to complete authentication with DIM.",
17893
+ params: {
17894
+ address: {
17895
+ type: "string",
17896
+ description: "Your Solana wallet address (base58)",
17897
+ required: true
17898
+ },
17899
+ signature: {
17900
+ type: "string",
17901
+ description: "Base58-encoded signature returned by sign_solana_message",
17902
+ required: true
17903
+ }
17904
+ },
17905
+ execute: (c, a) => completeLogin(c, a)
17906
+ },
17228
17907
  // ── Auth ─────────────────────────────────────────────────────────────
17229
17908
  {
17230
17909
  name: "dim_login",
@@ -17378,9 +18057,23 @@ var TOOL_DEFINITIONS = [
17378
18057
  },
17379
18058
  {
17380
18059
  name: "dim_get_incoming_friend_requests",
17381
- description: "List pending incoming friend requests.",
17382
- params: {},
17383
- execute: (c) => getIncomingFriendRequests(c)
18060
+ description: "List pending incoming friend requests. Returns { items, nextCursor, hasMore }. Pass cursor from a previous response to page through results.",
18061
+ params: {
18062
+ limit: {
18063
+ type: "number",
18064
+ description: "Maximum number of requests to return (1\u2013100, default 50).",
18065
+ required: false
18066
+ },
18067
+ cursor: {
18068
+ type: "string",
18069
+ description: "Pagination cursor from a previous response nextCursor field. Omit for the first page.",
18070
+ required: false
18071
+ }
18072
+ },
18073
+ execute: (c, a) => getIncomingFriendRequests(
18074
+ c,
18075
+ a
18076
+ )
17384
18077
  },
17385
18078
  // ── Chat ─────────────────────────────────────────────────────────────
17386
18079
  {
@@ -17506,6 +18199,90 @@ var TOOL_DEFINITIONS = [
17506
18199
  },
17507
18200
  execute: (c, a) => tipUser(c, a)
17508
18201
  },
18202
+ {
18203
+ name: "dim_confirm_send_usdc",
18204
+ description: "External wallet: confirm a USDC transfer after signing and broadcasting the transaction. Provide the on-chain signature and the params from the confirmWith object returned by dim_send_usdc.",
18205
+ params: {
18206
+ signature: {
18207
+ type: "string",
18208
+ description: "On-chain transaction signature returned by send_solana_transaction",
18209
+ required: true
18210
+ },
18211
+ recipientAddress: {
18212
+ type: "string",
18213
+ description: "Recipient Solana address (from confirmWith.params)",
18214
+ required: true
18215
+ },
18216
+ amount: {
18217
+ type: "number",
18218
+ description: "Amount in USDC minor units (from confirmWith.params)",
18219
+ required: true
18220
+ },
18221
+ fee: {
18222
+ type: "number",
18223
+ description: "Fee in minor units (from confirmWith.params)"
18224
+ },
18225
+ token: {
18226
+ type: "string",
18227
+ description: "Token type: USDC or SOL (default: USDC)"
18228
+ },
18229
+ ataCreated: {
18230
+ type: "string",
18231
+ description: "Whether a new ATA was created (from confirmWith.params)"
18232
+ },
18233
+ recipientInput: {
18234
+ type: "string",
18235
+ description: "Original recipient input (from confirmWith.params)"
18236
+ }
18237
+ },
18238
+ execute: (c, a) => confirmSendUsdc(
18239
+ c,
18240
+ a
18241
+ )
18242
+ },
18243
+ {
18244
+ name: "dim_confirm_tip_user",
18245
+ description: "External wallet: confirm a tip after signing and broadcasting the transaction. Provide the on-chain signature and the params from the confirmWith object returned by dim_tip_user.",
18246
+ params: {
18247
+ signature: {
18248
+ type: "string",
18249
+ description: "On-chain transaction signature returned by send_solana_transaction",
18250
+ required: true
18251
+ },
18252
+ recipientAddress: {
18253
+ type: "string",
18254
+ description: "Recipient Solana address (from confirmWith.params)",
18255
+ required: true
18256
+ },
18257
+ recipientUserId: {
18258
+ type: "string",
18259
+ description: "Recipient user ID (from confirmWith.params)",
18260
+ required: true
18261
+ },
18262
+ recipientUsername: {
18263
+ type: "string",
18264
+ description: "Recipient username (from confirmWith.params)",
18265
+ required: true
18266
+ },
18267
+ amount: {
18268
+ type: "number",
18269
+ description: "Amount in USDC minor units (from confirmWith.params)",
18270
+ required: true
18271
+ },
18272
+ fee: {
18273
+ type: "number",
18274
+ description: "Fee in minor units (from confirmWith.params)"
18275
+ },
18276
+ ataCreated: {
18277
+ type: "string",
18278
+ description: "Whether a new ATA was created (from confirmWith.params)"
18279
+ }
18280
+ },
18281
+ execute: (c, a) => confirmTipUser(
18282
+ c,
18283
+ a
18284
+ )
18285
+ },
17509
18286
  {
17510
18287
  name: "dim_get_wallet_activity",
17511
18288
  description: "Get recent wallet transaction activity (deposits, payouts, transfers, refunds) and your DIM wallet address. Highlights any claimable items.",
@@ -17602,6 +18379,23 @@ var TOOL_DEFINITIONS = [
17602
18379
  },
17603
18380
  execute: (c, a) => depositForLobby(c, a)
17604
18381
  },
18382
+ {
18383
+ name: "dim_confirm_lobby_deposit",
18384
+ description: "External wallet: confirm a lobby deposit after signing and broadcasting the transaction. Polls until the deposit is confirmed on-chain, then returns canProceedToQueue.",
18385
+ params: {
18386
+ lobbyId: {
18387
+ type: "string",
18388
+ description: "The lobby ID (from confirmWith.params)",
18389
+ required: true
18390
+ },
18391
+ signature: {
18392
+ type: "string",
18393
+ description: "On-chain transaction signature returned by send_solana_transaction",
18394
+ required: true
18395
+ }
18396
+ },
18397
+ execute: (c, a) => confirmLobbyDeposit(c, a)
18398
+ },
17605
18399
  {
17606
18400
  name: "dim_leave_lobby",
17607
18401
  description: "Leave a lobby. Use this to exit a lobby you created or joined. Returns when you have left.",
@@ -17694,6 +18488,31 @@ var TOOL_DEFINITIONS = [
17694
18488
  },
17695
18489
  execute: (c, a) => gameLoop(c, a)
17696
18490
  },
18491
+ {
18492
+ name: "dim_confirm_donate_to_pot",
18493
+ description: "External wallet: confirm a game pot donation after signing and broadcasting the transaction.",
18494
+ params: {
18495
+ signature: {
18496
+ type: "string",
18497
+ description: "On-chain transaction signature returned by send_solana_transaction",
18498
+ required: true
18499
+ },
18500
+ gameId: {
18501
+ type: "string",
18502
+ description: "The game ID (from confirmWith.params)",
18503
+ required: true
18504
+ },
18505
+ amount: {
18506
+ type: "number",
18507
+ description: "Amount in USDC minor units (from confirmWith.params)",
18508
+ required: true
18509
+ }
18510
+ },
18511
+ execute: (c, a) => confirmDonateToPot(
18512
+ c,
18513
+ a
18514
+ )
18515
+ },
17697
18516
  {
17698
18517
  name: "dim_request_rematch",
17699
18518
  description: "Request a rematch after a completed game. If both players request, a lobby is created automatically server-side.",
@@ -18517,12 +19336,11 @@ if (cliArgs[0] === "init-wallet") {
18517
19336
  var walletPrivateKey = await resolveWalletPrivateKey(cliArgs);
18518
19337
  if (!walletPrivateKey) {
18519
19338
  console.error(
18520
- "Error: DIM wallet key is not configured.\nProvide DIM_WALLET_PRIVATE_KEY, or initialize a local wallet store.\n\nExamples:\n DIM_WALLET_PRIVATE_KEY=your-base58-key npx @dimcool/mcp\n npx @dimcool/mcp init-wallet\n DIM_WALLET_AUTO_CREATE=true npx @dimcool/mcp"
19339
+ "No DIM wallet key configured \u2014 starting in external signer mode.\nUse dim_request_auth_message \u2192 sign_solana_message \u2192 dim_complete_login to authenticate.\n\nTo use a dedicated wallet instead:\n DIM_WALLET_PRIVATE_KEY=your-base58-key npx @dimcool/mcp\n npx @dimcool/mcp init-wallet\n DIM_WALLET_AUTO_CREATE=true npx @dimcool/mcp"
18521
19340
  );
18522
- process.exit(1);
18523
19341
  }
18524
19342
  var { server } = createDimMcpServer({
18525
- walletPrivateKey,
19343
+ walletPrivateKey: walletPrivateKey ?? void 0,
18526
19344
  apiUrl: process.env.DIM_API_URL || "https://api.dim.cool",
18527
19345
  referralCode: process.env.DIM_REFERRAL_CODE
18528
19346
  });