@dubsdotapp/expo 0.2.70 → 0.2.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -406,6 +406,7 @@ interface UiConfig {
406
406
  appName?: string;
407
407
  appUrl?: string;
408
408
  tagline?: string;
409
+ environment?: 'sandbox' | 'production';
409
410
  }
410
411
 
411
412
  interface DubsClientConfig {
@@ -482,7 +483,7 @@ declare class DubsClient {
482
483
  parseErrorLocal(error: unknown): ParsedError;
483
484
  /** Get the full local error code map */
484
485
  getErrorCodesLocal(): Record<number, SolanaErrorCode>;
485
- /** Fetch the app's UI customization config (accent color, icon, tagline) */
486
+ /** Fetch the app's UI customization config (accent color, icon, tagline, environment) */
486
487
  getAppConfig(): Promise<UiConfig>;
487
488
  }
488
489
 
package/dist/index.d.ts CHANGED
@@ -406,6 +406,7 @@ interface UiConfig {
406
406
  appName?: string;
407
407
  appUrl?: string;
408
408
  tagline?: string;
409
+ environment?: 'sandbox' | 'production';
409
410
  }
410
411
 
411
412
  interface DubsClientConfig {
@@ -482,7 +483,7 @@ declare class DubsClient {
482
483
  parseErrorLocal(error: unknown): ParsedError;
483
484
  /** Get the full local error code map */
484
485
  getErrorCodesLocal(): Record<number, SolanaErrorCode>;
485
- /** Fetch the app's UI customization config (accent color, icon, tagline) */
486
+ /** Fetch the app's UI customization config (accent color, icon, tagline, environment) */
486
487
  getAppConfig(): Promise<UiConfig>;
487
488
  }
488
489
 
package/dist/index.js CHANGED
@@ -585,10 +585,14 @@ var DubsClient = class {
585
585
  return { ...SOLANA_PROGRAM_ERRORS };
586
586
  }
587
587
  // ── App Config ──
588
- /** Fetch the app's UI customization config (accent color, icon, tagline) */
588
+ /** Fetch the app's UI customization config (accent color, icon, tagline, environment) */
589
589
  async getAppConfig() {
590
590
  const res = await this.request("GET", "/apps/config");
591
- return res.data?.uiConfig || {};
591
+ const config = res.data?.uiConfig || {};
592
+ if (res.data?.environment) {
593
+ config.environment = res.data.environment;
594
+ }
595
+ return config;
592
596
  }
593
597
  };
594
598
 
@@ -1846,7 +1850,7 @@ function useCreateGame() {
1846
1850
  console.log("[useCreateGame] Step 2 done. Signature:", signature);
1847
1851
  setStatus("confirming");
1848
1852
  console.log("[useCreateGame] Step 3: Confirming with backend...");
1849
- await client.confirmGame({
1853
+ const confirmResult = await client.confirmGame({
1850
1854
  gameId: createResult.gameId,
1851
1855
  playerWallet: params.playerWallet,
1852
1856
  signature,
@@ -1856,12 +1860,11 @@ function useCreateGame() {
1856
1860
  gameAddress: createResult.gameAddress
1857
1861
  });
1858
1862
  console.log("[useCreateGame] Step 3 done.");
1859
- const explorerUrl = `https://solscan.io/tx/${signature}`;
1860
1863
  const result = {
1861
1864
  gameId: createResult.gameId,
1862
1865
  gameAddress: createResult.gameAddress,
1863
1866
  signature,
1864
- explorerUrl
1867
+ explorerUrl: confirmResult.explorerUrl
1865
1868
  };
1866
1869
  setData(result);
1867
1870
  setStatus("success");
@@ -1917,14 +1920,13 @@ function useJoinGame() {
1917
1920
  gameAddress: joinResult.gameAddress
1918
1921
  };
1919
1922
  console.log("[useJoinGame] Step 3: Confirming with backend...", confirmParams);
1920
- await client.confirmGame(confirmParams);
1923
+ const confirmResult = await client.confirmGame(confirmParams);
1921
1924
  console.log("[useJoinGame] Step 3 done. Backend confirmed.");
1922
- const explorerUrl = `https://solscan.io/tx/${signature}`;
1923
1925
  const result = {
1924
1926
  gameId: params.gameId,
1925
1927
  gameAddress: joinResult.gameAddress,
1926
1928
  signature,
1927
- explorerUrl
1929
+ explorerUrl: confirmResult.explorerUrl
1928
1930
  };
1929
1931
  setData(result);
1930
1932
  setStatus("success");
@@ -2042,7 +2044,7 @@ function useCreateCustomGame() {
2042
2044
  console.log("[useCreateCustomGame] Step 2 done. Signature:", signature);
2043
2045
  setStatus("confirming");
2044
2046
  console.log("[useCreateCustomGame] Step 3: Confirming with backend...");
2045
- await client.confirmCustomGame({
2047
+ const confirmResult = await client.confirmCustomGame({
2046
2048
  gameId: createResult.gameId,
2047
2049
  playerWallet: params.playerWallet,
2048
2050
  signature,
@@ -2052,12 +2054,11 @@ function useCreateCustomGame() {
2052
2054
  gameAddress: createResult.gameAddress
2053
2055
  });
2054
2056
  console.log("[useCreateCustomGame] Step 3 done.");
2055
- const explorerUrl = `https://solscan.io/tx/${signature}`;
2056
2057
  const result = {
2057
2058
  gameId: createResult.gameId,
2058
2059
  gameAddress: createResult.gameAddress,
2059
2060
  signature,
2060
- explorerUrl,
2061
+ explorerUrl: confirmResult.explorerUrl,
2061
2062
  buyIn: params.wagerAmount
2062
2063
  };
2063
2064
  setData(result);
@@ -2185,6 +2186,7 @@ async function getDeviceInfo() {
2185
2186
  function useAuth() {
2186
2187
  const sharedAuth = (0, import_react13.useContext)(AuthContext);
2187
2188
  const { client, wallet } = useDubs();
2189
+ const disconnect = useDisconnect();
2188
2190
  const [status, setStatus] = (0, import_react13.useState)("idle");
2189
2191
  const [user, setUser] = (0, import_react13.useState)(null);
2190
2192
  const [token, setToken] = (0, import_react13.useState)(null);
@@ -2227,10 +2229,18 @@ function useAuth() {
2227
2229
  setToken(result.token);
2228
2230
  setStatus("authenticated");
2229
2231
  } catch (err) {
2230
- setError(err instanceof Error ? err : new Error(String(err)));
2232
+ const message = err instanceof Error ? err.message : String(err);
2233
+ if (message.includes("4100") || message.includes("not been authorized")) {
2234
+ console.log("[useAuth] Stale Phantom session detected (4100), forcing disconnect");
2235
+ await disconnect?.();
2236
+ setStatus("idle");
2237
+ setError(null);
2238
+ return;
2239
+ }
2240
+ setError(err instanceof Error ? err : new Error(message));
2231
2241
  setStatus("error");
2232
2242
  }
2233
- }, [client, wallet]);
2243
+ }, [client, wallet, disconnect]);
2234
2244
  const register = (0, import_react13.useCallback)(async (username, referralCode, avatarUrl) => {
2235
2245
  try {
2236
2246
  const pending = pendingAuth.current;
@@ -3143,21 +3153,28 @@ function DubsProvider({
3143
3153
  const config = NETWORK_CONFIG[network];
3144
3154
  const baseUrl = baseUrlOverride || config.baseUrl;
3145
3155
  const rpcUrl = rpcUrlOverride || config.rpcUrl;
3146
- const cluster = config.cluster;
3147
3156
  const client = (0, import_react18.useMemo)(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
3148
- const connection = (0, import_react18.useMemo)(() => new import_web34.Connection(rpcUrl, { commitment: "confirmed" }), [rpcUrl]);
3149
3157
  const storage = (0, import_react18.useMemo)(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
3150
3158
  const [uiConfig, setUiConfig] = (0, import_react18.useState)(null);
3159
+ const [resolvedNetwork, setResolvedNetwork] = (0, import_react18.useState)(network);
3151
3160
  (0, import_react18.useEffect)(() => {
3152
- client.getAppConfig().then((config2) => {
3153
- console.log("[DubsProvider] UI config loaded:", JSON.stringify(config2));
3154
- setUiConfig(config2);
3161
+ client.getAppConfig().then((cfg) => {
3162
+ console.log("[DubsProvider] UI config loaded:", JSON.stringify(cfg));
3163
+ setUiConfig(cfg);
3164
+ if (cfg.environment === "sandbox" && network === "mainnet-beta" && !rpcUrlOverride) {
3165
+ console.log("[DubsProvider] Sandbox API key detected \u2014 auto-switching to devnet");
3166
+ setResolvedNetwork("devnet");
3167
+ }
3155
3168
  }).catch((err) => {
3156
3169
  console.log("[DubsProvider] UI config fetch failed, using defaults:", err?.message);
3157
3170
  setUiConfig({});
3158
3171
  });
3159
3172
  }, [client]);
3160
3173
  if (uiConfig === null) return null;
3174
+ const resolvedConfig = NETWORK_CONFIG[resolvedNetwork];
3175
+ const resolvedRpcUrl = rpcUrlOverride || resolvedConfig.rpcUrl;
3176
+ const cluster = resolvedConfig.cluster;
3177
+ const connection = (0, import_react18.useMemo)(() => new import_web34.Connection(resolvedRpcUrl, { commitment: "confirmed" }), [resolvedRpcUrl]);
3161
3178
  const themeOverrides = {};
3162
3179
  if (uiConfig.accentColor) {
3163
3180
  themeOverrides.accent = uiConfig.accentColor;
@@ -3170,7 +3187,7 @@ function DubsProvider({
3170
3187
  connection,
3171
3188
  wallet: externalWallet,
3172
3189
  appName: uiConfig.appName || appName,
3173
- network,
3190
+ network: resolvedNetwork,
3174
3191
  storage,
3175
3192
  managed,
3176
3193
  renderLoading,
@@ -3202,7 +3219,7 @@ function DubsProvider({
3202
3219
  connection,
3203
3220
  wallet: adapter,
3204
3221
  appName: uiConfig.appName || appName,
3205
- network,
3222
+ network: resolvedNetwork,
3206
3223
  storage,
3207
3224
  renderLoading,
3208
3225
  renderError,