@wheelx-widget/widget 0.1.11 → 0.1.12

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.js CHANGED
@@ -69,7 +69,8 @@ var defaultTheme = {
69
69
  normalButtonBg: "#F5F6F8",
70
70
  normalButtonText: "#1A1D26",
71
71
  disabledButtonBg: "#E2E4E8",
72
- disabledButtonText: "#A0A4AE"
72
+ disabledButtonText: "#A0A4AE",
73
+ getGasSwitchColorPalette: "purple"
73
74
  };
74
75
  var WidgetThemeContext = React5.createContext({
75
76
  theme: defaultTheme
@@ -88,9 +89,15 @@ var WidgetThemeProvider = ({
88
89
  };
89
90
 
90
91
  // src/api/consts.ts
91
- var BASE_API_URL = "https://api.wheelx.fi";
92
+ var _baseApiUrl = "https://api.wheelx.fi";
93
+ function getBaseApiUrl() {
94
+ return _baseApiUrl;
95
+ }
96
+ function setBaseApiUrl(url) {
97
+ _baseApiUrl = url;
98
+ }
92
99
  async function getChainsAndTokens() {
93
- const url = `${BASE_API_URL}/v1/chain-info`;
100
+ const url = `${getBaseApiUrl()}/v1/chain-info`;
94
101
  const res = await axios6__default.default.get(url);
95
102
  return res.data;
96
103
  }
@@ -100,6 +107,7 @@ var useChainsAndTokens = (enabled = true) => {
100
107
  queryFn: () => getChainsAndTokens(),
101
108
  enabled,
102
109
  staleTime: 30 * 1e3,
110
+ // 30s:与 ISR 对齐,避免客户端立即重复请求
103
111
  refetchOnWindowFocus: false
104
112
  });
105
113
  return result;
@@ -184,10 +192,12 @@ var useWalletConnectedStore = zustand.create((set, get) => ({
184
192
  setEvmWalletInfo: (address, connectorId) => set({ evmWalletAddress: address, evmWalletConnectorId: connectorId }),
185
193
  isEvmWalletMetamask: false,
186
194
  setIsEvmWalletMetamask: (isEvmWalletMetamask) => set({ isEvmWalletMetamask }),
195
+ // Widget: logging-out guard
187
196
  isLoggingOut: false,
188
197
  setIsLoggingOut: (isLoggingOut) => set({ isLoggingOut }),
198
+ // Widget: disconnect timestamp for 2-second auto-reconnect guard
189
199
  lastDisconnectTimestamp: 0,
190
- setLastDisconnectTimestamp: (ts) => set({ lastDisconnectTimestamp: ts })
200
+ setLastDisconnectTimestamp: (timestamp) => set({ lastDisconnectTimestamp: timestamp })
191
201
  }));
192
202
 
193
203
  // src/stores/useSyncWalletConnectedStore.ts
@@ -206,15 +216,16 @@ var useSyncWalletConnectedStore = () => {
206
216
  isLoggingOut,
207
217
  lastDisconnectTimestamp
208
218
  } = useWalletConnectedStore();
219
+ const guardRef = React5.useRef({
220
+ isLoggingOut: false,
221
+ lastDisconnectTimestamp: 0
222
+ });
223
+ guardRef.current = { isLoggingOut, lastDisconnectTimestamp };
209
224
  React5.useEffect(() => {
210
- if (isLoggingOut) return;
211
- const msSinceDisconnect = Date.now() - lastDisconnectTimestamp;
212
- if (msSinceDisconnect < 2e3) {
213
- const { isEthWalletConnected, isSolanaWalletConnected } = useWalletConnectedStore.getState();
214
- const hasNoConnectedWallets = !isEthWalletConnected && !isSolanaWalletConnected;
215
- if (hasNoConnectedWallets) {
216
- return;
217
- }
225
+ if (guardRef.current.isLoggingOut) return;
226
+ const msSinceDisconnect = Date.now() - guardRef.current.lastDisconnectTimestamp;
227
+ if (guardRef.current.lastDisconnectTimestamp > 0 && msSinceDisconnect < 2e3) {
228
+ return;
218
229
  }
219
230
  const solanaWallet = userWallets.find((wallet) => {
220
231
  const chain = String(
@@ -231,16 +242,10 @@ var useSyncWalletConnectedStore = () => {
231
242
  ).toLowerCase();
232
243
  return chain.includes("evm");
233
244
  });
234
- const hasEverDisconnected = lastDisconnectTimestamp > 0;
235
- let evmAddress = null;
236
- if (hasEverDisconnected && !evmWallet) {
237
- evmAddress = null;
238
- } else {
239
- evmAddress = evmWallet?.address ?? wagmiAddress ?? null;
240
- }
245
+ const evmAddress = evmWallet?.address ?? wagmiAddress ?? null;
241
246
  const evmConnectorId = wagmiConnector?.id ?? getEvmConnectorId(evmWallet) ?? null;
242
247
  setEvmWalletInfo(evmAddress, evmConnectorId);
243
- setIsEthWalletConnected(Boolean(evmAddress || isConnected && !hasEverDisconnected));
248
+ setIsEthWalletConnected(Boolean(evmAddress || isConnected));
244
249
  }, [
245
250
  userWallets,
246
251
  wagmiAddress,
@@ -272,79 +277,116 @@ var FavoritesContext = React5.createContext({
272
277
  isLoading: true,
273
278
  walletAddress: void 0
274
279
  });
275
- var FavoritesProvider = ({ children }) => {
280
+ var FavoritesProvider = ({
281
+ children
282
+ }) => {
276
283
  const address = useEvmAddress();
284
+ const { isConnected } = wagmi.useAccount();
277
285
  const [favorites, setFavorites] = React5.useState([]);
278
286
  const [isLoading, setIsLoading] = React5.useState(true);
279
- const mountedRef = React5.useRef(false);
280
287
  const getStorageKey = React5.useCallback(() => {
281
288
  if (!address) return null;
282
289
  return `web3-favorites-${address.toLowerCase()}`;
283
290
  }, [address]);
284
291
  React5.useEffect(() => {
285
- mountedRef.current = true;
286
- const id = requestAnimationFrame(() => {
287
- if (!mountedRef.current) return;
292
+ const loadFavorites = async () => {
288
293
  if (!address) {
289
294
  setFavorites([]);
290
295
  setIsLoading(false);
291
296
  return;
292
297
  }
293
298
  try {
294
- const k = getStorageKey();
295
- if (!k) {
299
+ const storageKey = getStorageKey();
300
+ if (!storageKey) {
296
301
  setIsLoading(false);
297
302
  return;
298
303
  }
299
- const s = localStorage.getItem(k);
300
- if (s) setFavorites(JSON.parse(s));
301
- } catch (_) {
304
+ const stored = localStorage.getItem(storageKey);
305
+ if (stored) {
306
+ const parsedFavorites = JSON.parse(stored);
307
+ setFavorites(parsedFavorites);
308
+ }
309
+ } catch (error) {
310
+ console.error("Failed to load favorites from localStorage:", error);
302
311
  setFavorites([]);
303
312
  } finally {
304
313
  setIsLoading(false);
305
314
  }
306
- });
307
- return () => {
308
- mountedRef.current = false;
309
- cancelAnimationFrame(id);
310
315
  };
316
+ loadFavorites();
311
317
  }, [address, getStorageKey]);
312
- const save = (n) => {
318
+ const saveFavorites = (newFavorites) => {
313
319
  if (typeof window === "undefined") return;
314
- const k = getStorageKey();
315
- if (!k) return;
320
+ const storageKey = getStorageKey();
321
+ if (!storageKey) return;
316
322
  try {
317
- localStorage.setItem(k, JSON.stringify(n));
318
- setFavorites(n);
319
- } catch (_) {
323
+ localStorage.setItem(storageKey, JSON.stringify(newFavorites));
324
+ setFavorites(newFavorites);
325
+ } catch (error) {
326
+ console.error("Failed to save favorites to localStorage:", error);
320
327
  }
321
328
  };
322
- const addFavorite = (nId, nName = "Unknown Network") => {
323
- if (!address) return;
324
- if (!favorites.find((f) => f.networkId === nId))
325
- save([...favorites, { networkId: nId, networkName: nName, timestamp: Date.now() }]);
329
+ const addFavorite = (networkId, networkName = "Unknown Network") => {
330
+ if (!isConnected || !address) {
331
+ console.warn("Cannot add favorite: No wallet connected");
332
+ return;
333
+ }
334
+ const existingIndex = favorites.findIndex(
335
+ (fav) => fav.networkId === networkId
336
+ );
337
+ if (existingIndex === -1) {
338
+ const newFavorite = {
339
+ networkId,
340
+ networkName,
341
+ timestamp: Date.now()
342
+ };
343
+ const updatedFavorites = [...favorites, newFavorite];
344
+ saveFavorites(updatedFavorites);
345
+ }
326
346
  };
327
- const removeFavorite = (nId) => {
328
- if (!address) return;
329
- save(favorites.filter((f) => f.networkId !== nId));
347
+ const removeFavorite = (networkId) => {
348
+ if (!isConnected || !address) {
349
+ console.warn("Cannot remove favorite: No wallet connected");
350
+ return;
351
+ }
352
+ const updatedFavorites = favorites.filter(
353
+ (fav) => fav.networkId !== networkId
354
+ );
355
+ saveFavorites(updatedFavorites);
356
+ };
357
+ const isFavorite = (networkId) => {
358
+ return favorites.some((fav) => fav.networkId === networkId);
330
359
  };
331
- const isFavorite = (nId) => favorites.some((f) => f.networkId === nId);
332
360
  const clearFavorites = () => {
333
- if (!address) return;
334
- const k = getStorageKey();
335
- if (!k) return;
361
+ if (!isConnected || !address) return;
362
+ const storageKey = getStorageKey();
363
+ if (!storageKey) return;
336
364
  try {
337
- localStorage.removeItem(k);
365
+ localStorage.removeItem(storageKey);
338
366
  setFavorites([]);
339
- } catch (_) {
367
+ } catch (error) {
368
+ console.error("Failed to clear favorites:", error);
340
369
  }
341
370
  };
342
- return /* @__PURE__ */ jsxRuntime.jsx(FavoritesContext.Provider, { value: { favorites, addFavorite, removeFavorite, isFavorite, clearFavorites, isLoading, walletAddress: address }, children });
371
+ const contextValue = {
372
+ favorites,
373
+ addFavorite,
374
+ removeFavorite,
375
+ isFavorite,
376
+ clearFavorites,
377
+ isLoading,
378
+ walletAddress: address
379
+ };
380
+ return /* @__PURE__ */ jsxRuntime.jsx(FavoritesContext.Provider, { value: contextValue, children });
343
381
  };
344
382
  var useFavoritesContext = () => {
345
- const c = React5.useContext(FavoritesContext);
346
- if (c === void 0) throw new Error("useFavoritesContext must be used within a FavoritesProvider");
347
- return c;
383
+ const context = React5.useContext(FavoritesContext);
384
+ if (context === void 0) {
385
+ throw new Error(
386
+ "useFavoritesContext must be used within a FavoritesProvider"
387
+ );
388
+ }
389
+ return context;
348
390
  };
349
391
 
350
392
  // src/core/SelectTokenModal/storageUtils.ts
@@ -377,88 +419,229 @@ var TokenFavoritesContext = React5.createContext({
377
419
  walletAddress: void 0,
378
420
  storageError: null
379
421
  });
380
- var TokenFavoritesProvider = ({ children }) => {
422
+ var TokenFavoritesProvider = ({
423
+ children
424
+ }) => {
381
425
  const address = useEvmAddress();
426
+ const { isConnected } = wagmi.useAccount();
382
427
  const [favorites, setFavorites] = React5.useState([]);
383
428
  const [isLoading, setIsLoading] = React5.useState(true);
384
429
  const [storageError, setStorageError] = React5.useState(null);
385
- const mountedRef = React5.useRef(false);
386
430
  const getStorageKey = React5.useCallback(() => {
387
431
  if (!address) return null;
388
432
  return `web3-token-favorites-${address.toLowerCase()}`;
389
433
  }, [address]);
390
434
  React5.useEffect(() => {
391
- mountedRef.current = true;
392
- const id = requestAnimationFrame(() => {
393
- if (!mountedRef.current) return;
435
+ const loadFavorites = async () => {
394
436
  if (!address) {
395
437
  setFavorites([]);
396
438
  setIsLoading(false);
397
439
  return;
398
440
  }
399
441
  try {
400
- const k = getStorageKey();
401
- if (!k) {
442
+ const storageKey = getStorageKey();
443
+ if (!storageKey) {
402
444
  setIsLoading(false);
403
445
  return;
404
446
  }
405
- const s = localStorage.getItem(k);
406
- if (s) setFavorites(JSON.parse(s));
407
- } catch (_) {
447
+ const stored = localStorage.getItem(storageKey);
448
+ if (stored) {
449
+ const parsedFavorites = JSON.parse(stored);
450
+ setFavorites(parsedFavorites);
451
+ }
452
+ } catch (error) {
453
+ console.error("Failed to load favorites from localStorage:", error);
408
454
  setFavorites([]);
409
455
  } finally {
410
456
  setIsLoading(false);
411
457
  }
412
- });
413
- return () => {
414
- mountedRef.current = false;
415
- cancelAnimationFrame(id);
416
458
  };
459
+ loadFavorites();
417
460
  }, [address, getStorageKey]);
418
- const saveFavorites = (n) => {
461
+ const saveFavorites = (newFavorites) => {
419
462
  if (typeof window === "undefined") return;
420
463
  if (!isLocalStorageSupported()) {
421
- setStorageError("no localStorage");
464
+ setStorageError("you browser can not using local storage");
422
465
  return;
423
466
  }
424
- const k = getStorageKey();
425
- if (!k) return;
467
+ const storageKey = getStorageKey();
468
+ if (!storageKey) return;
426
469
  try {
427
- localStorage.setItem(k, JSON.stringify(n));
428
- setFavorites(n);
429
- } catch (_) {
470
+ localStorage.setItem(storageKey, JSON.stringify(newFavorites));
471
+ setFavorites(newFavorites);
472
+ } catch (error) {
473
+ console.error("Failed to save favorites to localStorage:", error);
430
474
  }
431
475
  };
432
- const addFavorite = (ci, ta, s, d, l, n, tg) => {
433
- if (!address) return;
434
- if (!favorites.find((f) => f.chain_id === ci && f.address === ta))
435
- saveFavorites([...favorites, { chain_id: ci, address: ta, symbol: s, decimals: d, logo: l, name: n, tags: tg, timestamp: Date.now() }]);
476
+ const addFavorite = (chainId, tokenAddress, symbol, decimals, logo, name, tags) => {
477
+ if (!isConnected || !address) {
478
+ console.warn("Cannot add favorite: No wallet connected");
479
+ return;
480
+ }
481
+ const existingIndex = favorites.findIndex(
482
+ (fav) => fav.chain_id === chainId && fav.address === tokenAddress
483
+ );
484
+ if (existingIndex === -1) {
485
+ const newFavorite = {
486
+ chain_id: chainId,
487
+ address: tokenAddress,
488
+ symbol,
489
+ decimals,
490
+ logo,
491
+ name,
492
+ tags,
493
+ timestamp: Date.now()
494
+ };
495
+ const updatedFavorites = [...favorites, newFavorite];
496
+ saveFavorites(updatedFavorites);
497
+ }
436
498
  };
437
- const removeFavorite = (ci, ta) => {
438
- if (!address) return;
439
- setFavorites((p) => {
440
- const u = p.filter((f) => !(f.chain_id === ci && f.address === ta));
441
- saveFavorites(u);
442
- return u;
499
+ const removeFavorite = (chainId, tokenAddress) => {
500
+ if (!isConnected || !address) {
501
+ console.warn("Cannot remove favorite: No wallet connected");
502
+ return;
503
+ }
504
+ setFavorites((prevFavorites) => {
505
+ const updatedFavorites = prevFavorites.filter(
506
+ (fav) => !(fav.chain_id === chainId && fav.address === tokenAddress)
507
+ );
508
+ saveFavorites(updatedFavorites);
509
+ return updatedFavorites;
443
510
  });
444
511
  };
445
- const isFavorite = (ci, ta) => favorites.some((f) => f.chain_id === ci && f.address === ta);
512
+ const isFavorite = (chainId, tokenAddress) => {
513
+ return favorites.some(
514
+ (fav) => fav.chain_id === chainId && fav.address === tokenAddress
515
+ );
516
+ };
446
517
  const clearFavorites = () => {
447
- if (!address) return;
448
- const k = getStorageKey();
449
- if (!k) return;
518
+ if (!isConnected || !address) return;
519
+ const storageKey = getStorageKey();
520
+ if (!storageKey) return;
450
521
  try {
451
- localStorage.removeItem(k);
522
+ localStorage.removeItem(storageKey);
452
523
  setFavorites([]);
453
- } catch (_) {
524
+ } catch (error) {
525
+ console.error("Failed to clear favorites:", error);
454
526
  }
455
527
  };
456
- return /* @__PURE__ */ jsxRuntime.jsx(TokenFavoritesContext.Provider, { value: { favorites, addFavorite, removeFavorite, isFavorite, clearFavorites, isLoading, walletAddress: address, storageError }, children });
528
+ const contextValue = {
529
+ favorites,
530
+ addFavorite,
531
+ removeFavorite,
532
+ isFavorite,
533
+ clearFavorites,
534
+ isLoading,
535
+ storageError,
536
+ walletAddress: address
537
+ };
538
+ return /* @__PURE__ */ jsxRuntime.jsx(TokenFavoritesContext.Provider, { value: contextValue, children });
457
539
  };
458
540
  var useTokenFavoritesContext = () => {
459
- const c = React5.useContext(TokenFavoritesContext);
460
- if (c === void 0) throw new Error("useTokenFavoritesContext must be used within TokenFavoritesProvider");
461
- return c;
541
+ const context = React5.useContext(TokenFavoritesContext);
542
+ if (context === void 0) {
543
+ throw new Error(
544
+ "useFavoritesContext must be used within a token FavoritesProvider"
545
+ );
546
+ }
547
+ return context;
548
+ };
549
+
550
+ // src/utils/platform.ts
551
+ var isReactNativeWebView = () => {
552
+ if (typeof window === "undefined") return false;
553
+ return !!window.ReactNativeWebView;
554
+ };
555
+ var isWebView = () => {
556
+ if (typeof window === "undefined" || typeof navigator === "undefined") return false;
557
+ const ua = navigator.userAgent.toLowerCase();
558
+ if (ua.includes("wv") || ua.includes("android-webview")) return true;
559
+ if ((ua.includes("iphone") || ua.includes("ipad")) && !ua.includes("safari") && !ua.includes("crios"))
560
+ return true;
561
+ if (isReactNativeWebView()) return true;
562
+ return false;
563
+ };
564
+ var isMobileDevice = () => {
565
+ if (typeof navigator === "undefined" || typeof window === "undefined") return false;
566
+ const ua = navigator.userAgent.toLowerCase();
567
+ const isMobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini|mobile/i.test(ua);
568
+ const hasTouchScreen = "ontouchstart" in window || navigator.maxTouchPoints > 0;
569
+ return isMobile || hasTouchScreen && window.innerWidth < 1024;
570
+ };
571
+ var shouldInterceptDeepLinks = () => {
572
+ return isReactNativeWebView();
573
+ };
574
+ var isDeepLinkUrl = (url) => {
575
+ if (!url) return false;
576
+ const lower = url.toLowerCase();
577
+ return /^[a-z][a-z0-9+.-]*:\/\//i.test(url) && !lower.startsWith("http://") && !lower.startsWith("https://") && !lower.startsWith("about:") && !lower.startsWith("javascript:") && !lower.startsWith("data:") && !lower.startsWith("blob:") && !lower.startsWith("file:") || // WalletConnect v2: wc:<topic>@2?param=value (no "://")
578
+ lower.startsWith("wc:") || // Android intent:// URLs
579
+ lower.startsWith("intent://");
580
+ };
581
+ var KNOWN_WALLET_UNIVERSAL_LINKS = {
582
+ // MetaMask
583
+ "https://metamask.app.link/": "https://metamask.app.link/",
584
+ // Phantom — /ul/v1/* are encrypted session API endpoints that ONLY work
585
+ // with the https://phantom.app domain. Do NOT convert to phantom://.
586
+ // Both key and value are identical → convertToDeepLink() returns as-is.
587
+ "https://phantom.app/": "https://phantom.app/",
588
+ // Coinbase Wallet
589
+ "https://go.cb-w.com/": "https://go.cb-w.com/",
590
+ // Trust Wallet
591
+ "https://link.trustwallet.com/": "https://link.trustwallet.com/",
592
+ // Rainbow
593
+ "https://rnbwapp.com/": "https://rnbwapp.com/",
594
+ // OKX Wallet
595
+ "https://www.okx.com/": "https://www.okx.com/",
596
+ "https://okx.com/": "https://okx.com/",
597
+ // BitGet / BitKeep
598
+ "https://bitkeep.com/": "https://bitkeep.com/",
599
+ "https://bitget.com/": "https://bitget.com/",
600
+ // TokenPocket
601
+ "https://rn.tokenpocket.pro/": "https://rn.tokenpocket.pro/",
602
+ // SafePal
603
+ "https://safepal.io/": "https://safepal.io/",
604
+ // Zerion
605
+ "https://zerion.io/": "https://zerion.io/",
606
+ // Ledger Live
607
+ "https://ledger.live/": "https://ledger.live/"
608
+ };
609
+ var convertToDeepLink = (url) => {
610
+ if (!url) return url;
611
+ for (const [prefix, scheme] of Object.entries(KNOWN_WALLET_UNIVERSAL_LINKS)) {
612
+ if (url.toLowerCase().startsWith(prefix)) {
613
+ return url.slice(prefix.length) ? scheme + url.slice(prefix.length) : scheme;
614
+ }
615
+ }
616
+ return url;
617
+ };
618
+ var isWalletRelatedUrl = (url) => {
619
+ if (!url) return false;
620
+ if (isDeepLinkUrl(url)) return true;
621
+ const lower = url.toLowerCase();
622
+ return Object.keys(KNOWN_WALLET_UNIVERSAL_LINKS).some(
623
+ (prefix) => lower.startsWith(prefix)
624
+ );
625
+ };
626
+ var handleDeepLink = (url, handler) => {
627
+ if (handler) {
628
+ handler(url);
629
+ return;
630
+ }
631
+ const rnWebView = window.ReactNativeWebView;
632
+ if (rnWebView?.postMessage) {
633
+ rnWebView.postMessage(
634
+ JSON.stringify({
635
+ type: "WHEELX_DEEP_LINK",
636
+ url,
637
+ timestamp: Date.now()
638
+ })
639
+ );
640
+ console.log("[WheelX Widget] Sent deep link via ReactNativeWebView.postMessage:", url);
641
+ return;
642
+ }
643
+ window.dispatchEvent(new CustomEvent("wheelx:deepLink", { detail: { url } }));
644
+ console.log("[WheelX Widget] Dispatched wheelx:deepLink event:", url);
462
645
  };
463
646
  var tempo = viem.defineChain({
464
647
  id: 4217,
@@ -650,12 +833,95 @@ function LoadingSkeleton() {
650
833
  }
651
834
  );
652
835
  }
836
+ function DeepLinkInterceptor({ config }) {
837
+ const interceptorInstalled = React5.useRef(false);
838
+ React5.useEffect(() => {
839
+ if (typeof window === "undefined") return;
840
+ if (interceptorInstalled.current) return;
841
+ if (!shouldInterceptDeepLinks()) return;
842
+ interceptorInstalled.current = true;
843
+ const originalOpen = window.open.bind(window);
844
+ window.open = function(...args) {
845
+ const url = typeof args[0] === "string" ? args[0] : "";
846
+ if (url && isWalletRelatedUrl(url)) {
847
+ const deepLink = convertToDeepLink(url);
848
+ console.log("[WheelX Widget] Intercepted window.open deep link:", url, "\u2192", deepLink);
849
+ handleDeepLink(deepLink, config?.onDeepLink);
850
+ return null;
851
+ }
852
+ return originalOpen(...args);
853
+ };
854
+ let originalLocationHrefSetter = null;
855
+ try {
856
+ const proto = Object.getPrototypeOf(window.location);
857
+ const desc = Object.getOwnPropertyDescriptor(proto, "href");
858
+ if (desc?.set) {
859
+ originalLocationHrefSetter = desc.set.bind(window.location);
860
+ Object.defineProperty(window.location, "href", {
861
+ ...desc,
862
+ set(value) {
863
+ if (isWalletRelatedUrl(value)) {
864
+ const deepLink = convertToDeepLink(value);
865
+ console.log("[WheelX Widget] Intercepted location.href deep link:", value, "\u2192", deepLink);
866
+ handleDeepLink(deepLink, config?.onDeepLink);
867
+ return;
868
+ }
869
+ return originalLocationHrefSetter.call(window.location, value);
870
+ }
871
+ });
872
+ console.log("[WheelX Widget] location.href interceptor INSTALLED successfully");
873
+ } else {
874
+ console.warn("[WheelX Widget] location.href interceptor NOT installed: no setter descriptor found");
875
+ }
876
+ } catch (e) {
877
+ console.warn("[WheelX Widget] location.href interceptor FAILED:", String(e));
878
+ }
879
+ const handleClick = (e) => {
880
+ const target = e.target;
881
+ const anchor = target.closest("a");
882
+ if (!anchor) return;
883
+ const href = anchor.getAttribute("href") || "";
884
+ if (href && isWalletRelatedUrl(href)) {
885
+ e.preventDefault();
886
+ e.stopPropagation();
887
+ const deepLink = convertToDeepLink(href);
888
+ console.log("[WheelX Widget] Intercepted anchor click deep link:", href, "\u2192", deepLink);
889
+ handleDeepLink(deepLink, config?.onDeepLink);
890
+ }
891
+ };
892
+ const handleBeforeUnload = () => {
893
+ const currentHref = window.location.href;
894
+ if (isWalletRelatedUrl(currentHref)) {
895
+ console.log("[WheelX Widget] Detected deep link navigation in beforeunload:", currentHref);
896
+ }
897
+ };
898
+ document.addEventListener("click", handleClick, true);
899
+ window.addEventListener("beforeunload", handleBeforeUnload);
900
+ console.log("[WheelX Widget] Deep link interceptor installed for WebView environment");
901
+ return () => {
902
+ document.removeEventListener("click", handleClick, true);
903
+ window.removeEventListener("beforeunload", handleBeforeUnload);
904
+ window.open = originalOpen;
905
+ if (originalLocationHrefSetter) {
906
+ try {
907
+ const proto = Object.getPrototypeOf(window.location);
908
+ const originalDesc = Object.getOwnPropertyDescriptor(proto, "href");
909
+ if (originalDesc) {
910
+ Object.defineProperty(window.location, "href", originalDesc);
911
+ }
912
+ } catch (_) {
913
+ }
914
+ }
915
+ };
916
+ }, []);
917
+ return null;
918
+ }
653
919
  function ChainsAndTokensLoader({ children, config }) {
654
920
  const { data } = useChainsAndTokens(true);
655
921
  const { setChains, setSlippagePolicies } = useChainsStore();
656
922
  const { setTokens } = useTokensStore();
657
923
  const initialDataRef = React5__namespace.default.useRef(false);
658
- const allChains = React5.useMemo(() => {
924
+ const allChains2 = React5.useMemo(() => {
659
925
  if (!data?.chains) return null;
660
926
  const l = [...data.chains];
661
927
  if (data.deposit_platforms?.prediction?.chains) l.push(...data.deposit_platforms.prediction.chains);
@@ -667,7 +933,7 @@ function ChainsAndTokensLoader({ children, config }) {
667
933
  if (data.deposit_platforms?.prediction?.tokens) l.push(...data.deposit_platforms.prediction.tokens);
668
934
  return l;
669
935
  }, [data]);
670
- const filteredChains = allChains;
936
+ const filteredChains = allChains2;
671
937
  const filteredTokens = allTokens;
672
938
  React5__namespace.default.useEffect(() => {
673
939
  if (filteredChains && !initialDataRef.current) {
@@ -692,6 +958,9 @@ function ChainsAndTokensLoader({ children, config }) {
692
958
  var DEFAULT_ENVIRONMENT_ID = "f217660e-2cec-470b-a8f4-ac655b16f802";
693
959
  var solanaRpcUrl = "https://mainnet.helius-rpc.com/?api-key=7337bed2-6c3a-472f-b06f-9b2be0e1392f";
694
960
  var WheelXProvider = ({ config, children }) => {
961
+ if (config?.apiBaseUrl) {
962
+ setBaseApiUrl(config.apiBaseUrl);
963
+ }
695
964
  const queryClient = React5.useMemo(() => new reactQuery.QueryClient(), []);
696
965
  const evmNetworks = React5.useMemo(() => supportedChains.map((chain) => ({
697
966
  chainId: chain.id,
@@ -702,18 +971,46 @@ var WheelXProvider = ({ config, children }) => {
702
971
  blockExplorerUrls: chain.blockExplorers?.default?.url ? [chain.blockExplorers.default.url] : []
703
972
  })), []);
704
973
  const solanaConnectors = React5.useMemo(() => solana.SolanaWalletConnectorsWithConfig({ customRpcUrls: { solana: [solanaRpcUrl] } }), []);
705
- const dynamicSettings = React5.useMemo(() => ({
706
- environmentId: config?.dynamicEnvironmentId || DEFAULT_ENVIRONMENT_ID,
707
- walletConnectors: [ethereum.EthereumWalletConnectors, solanaConnectors],
708
- enableConnectOnlyFallback: false,
709
- initialAuthenticationMode: "connect-only",
710
- mobileExperience: "redirect",
711
- deepLinkPreference: "universal",
712
- defaultNumberOfWalletsToShow: 25,
713
- overrides: { evmNetworks }
714
- }), [evmNetworks, solanaConnectors, config?.dynamicEnvironmentId]);
974
+ const dynamicSettings = React5.useMemo(() => {
975
+ const isRN = isReactNativeWebView();
976
+ return {
977
+ environmentId: config?.dynamicEnvironmentId || DEFAULT_ENVIRONMENT_ID,
978
+ walletConnectors: [ethereum.EthereumWalletConnectors, solanaConnectors],
979
+ enableConnectOnlyFallback: false,
980
+ initialAuthenticationMode: "connect-only",
981
+ // ── mobileExperience ──────────────────────────────────────
982
+ // H5 / DApp browser: use simple global string (original behavior).
983
+ // The browser natively handles https:// universal links to open
984
+ // wallet apps — no interception needed.
985
+ //
986
+ // React Native WebView: use per-wallet object config so each wallet
987
+ // explicitly uses 'redirect' mode, forcing the SDK to generate deep
988
+ // link URLs that our DeepLinkInterceptor can catch and forward.
989
+ ...isRN ? {
990
+ mobileExperience: {
991
+ okx: "redirect",
992
+ phantom: "redirect",
993
+ metamask: "redirect",
994
+ default: "redirect"
995
+ }
996
+ } : {
997
+ mobileExperience: "redirect"
998
+ },
999
+ // In React Native WebView, use 'native' so Dynamic SDK generates
1000
+ // phantom://, metamask:// etc. — these custom schemes route directly
1001
+ // to the wallet app via Linking.openURL(), avoiding the browser.
1002
+ // In H5 / DApp, use 'universal' so the browser handles the https://
1003
+ // universal links normally.
1004
+ deepLinkPreference: isRN ? "native" : "universal",
1005
+ defaultNumberOfWalletsToShow: 25,
1006
+ overrides: { evmNetworks }
1007
+ };
1008
+ }, [evmNetworks, solanaConnectors, config?.dynamicEnvironmentId]);
715
1009
  const wagmiConfig = React5.useMemo(() => getWagmiConfig(), []);
716
- return /* @__PURE__ */ jsxRuntime.jsx(WidgetThemeProvider, { theme: config?.theme, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(sdkReactCore.DynamicContextProvider, { settings: dynamicSettings, children: /* @__PURE__ */ jsxRuntime.jsx(wagmi.WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsxRuntime.jsx(wagmiConnector.DynamicWagmiConnector, { children: /* @__PURE__ */ jsxRuntime.jsx(ChainsAndTokensLoader, { config, children }) }) }) }) }) });
1010
+ return /* @__PURE__ */ jsxRuntime.jsx(WidgetThemeProvider, { theme: config?.theme, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(sdkReactCore.DynamicContextProvider, { settings: dynamicSettings, children: /* @__PURE__ */ jsxRuntime.jsx(wagmi.WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsxRuntime.jsxs(wagmiConnector.DynamicWagmiConnector, { children: [
1011
+ /* @__PURE__ */ jsxRuntime.jsx(DeepLinkInterceptor, { config }),
1012
+ /* @__PURE__ */ jsxRuntime.jsx(ChainsAndTokensLoader, { config, children })
1013
+ ] }) }) }) }) });
717
1014
  };
718
1015
  var createQuoteMutationError = (message, extra) => {
719
1016
  const quoteError = new Error(message);
@@ -740,7 +1037,7 @@ var useGetQuote = (signal) => reactQuery.useMutation({
740
1037
  mutationFn: async (requestBody) => {
741
1038
  try {
742
1039
  const res = await axios6__default.default.post(
743
- `${BASE_API_URL}/v1/quote`,
1040
+ `${getBaseApiUrl()}/v1/quote`,
744
1041
  {
745
1042
  ...requestBody,
746
1043
  quote_only: true
@@ -803,7 +1100,7 @@ var useGetQuote = (signal) => reactQuery.useMutation({
803
1100
  }
804
1101
  });
805
1102
  async function getTokenInfo(value, chainId) {
806
- const url = `${BASE_API_URL}/v1/token-info`;
1103
+ const url = `${getBaseApiUrl()}/v1/token-info`;
807
1104
  const res = await axios6__default.default.get(url, {
808
1105
  params: {
809
1106
  address: value,
@@ -820,12 +1117,13 @@ var useTokenInfo = ({
820
1117
  const result = reactQuery.useQuery({
821
1118
  queryKey: ["tokenInfo", value, chainId],
822
1119
  queryFn: () => getTokenInfo(value, chainId),
1120
+ // enabled: !!value && isAddress(value)
823
1121
  enabled: !!value && !!chainId
824
1122
  });
825
1123
  return result;
826
1124
  };
827
1125
  async function getUsdPrice(tokens) {
828
- const url = `${BASE_API_URL}/v1/token-price`;
1126
+ const url = `${getBaseApiUrl()}/v1/token-price`;
829
1127
  const res = await axios6__default.default.post(url, tokens);
830
1128
  return res.data;
831
1129
  }
@@ -839,15 +1137,25 @@ var useUsdPrice = (tokens) => {
839
1137
  });
840
1138
  };
841
1139
  var getHyperliquidBalance = async (address) => {
1140
+ const newUrl = `https://api.hyperliquid.xyz/info`;
842
1141
  try {
843
- const response = await fetch("https://api.hyperliquid.xyz/info", {
1142
+ const response = await fetch(`${newUrl}`, {
844
1143
  method: "POST",
845
- headers: { "Content-Type": "application/json" },
846
- body: JSON.stringify({ type: "clearinghouseState", user: address })
1144
+ headers: {
1145
+ "Content-Type": "application/json"
1146
+ },
1147
+ body: JSON.stringify({
1148
+ type: "clearinghouseState",
1149
+ user: address
1150
+ })
847
1151
  });
848
1152
  return await response.json();
849
1153
  } catch (error) {
850
- return { code: 1, message: error, withdrawable: null };
1154
+ return {
1155
+ code: 1,
1156
+ message: error,
1157
+ withdrawable: null
1158
+ };
851
1159
  }
852
1160
  };
853
1161
  var useHyperliquidBalance = (address, enabled) => {
@@ -867,7 +1175,7 @@ var useHyperliquidBalance = (address, enabled) => {
867
1175
  };
868
1176
  async function getOrderDetail(orderId) {
869
1177
  const res = await axios6__default.default.get(
870
- `${BASE_API_URL}/v1/order/${orderId}`
1178
+ `${getBaseApiUrl()}/v1/order/${orderId}`
871
1179
  );
872
1180
  return res.data;
873
1181
  }
@@ -890,6 +1198,7 @@ var useIntervalGetOrderDetailPlus = ({
890
1198
  },
891
1199
  refetchOnMount: false,
892
1200
  retry: false,
1201
+ // Disable React Query's built-in retries; rely on refetchInterval for continuous polling
893
1202
  enabled: queryEnabled
894
1203
  });
895
1204
  React5.useEffect(() => {
@@ -915,14 +1224,22 @@ var useIntervalGetOrderDetailPlus = ({
915
1224
  };
916
1225
  };
917
1226
  async function getTokenBalance(address) {
918
- const url = `${BASE_API_URL}/v1/token-balances`;
919
- const res = await axios6__default.default.get(url, { params: { address } });
1227
+ const url = `${getBaseApiUrl()}/v1/token-balances`;
1228
+ const res = await axios6__default.default.get(url, {
1229
+ params: {
1230
+ address
1231
+ }
1232
+ });
920
1233
  return res.data;
921
1234
  }
922
1235
  async function getSolanaTokenBalance(address) {
923
1236
  if (!address) return [];
924
- const url = `${BASE_API_URL}/v1/token-balances`;
925
- const res = await axios6__default.default.get(url, { params: { address } });
1237
+ const url = `${getBaseApiUrl()}/v1/token-balances`;
1238
+ const res = await axios6__default.default.get(url, {
1239
+ params: {
1240
+ address
1241
+ }
1242
+ });
926
1243
  return res.data;
927
1244
  }
928
1245
  async function getAllTokenBalances(evmAddress, solanaAddress) {
@@ -933,11 +1250,12 @@ async function getAllTokenBalances(evmAddress, solanaAddress) {
933
1250
  return [...evmBalances || [], ...solanaBalances || []];
934
1251
  }
935
1252
  var useAllTokenBalance = (evmAddress, solanaAddress) => {
936
- return reactQuery.useQuery({
1253
+ const result = reactQuery.useQuery({
937
1254
  queryKey: ["allTokenBalance", evmAddress, solanaAddress],
938
1255
  queryFn: () => getAllTokenBalances(evmAddress, solanaAddress),
939
1256
  enabled: !!evmAddress || !!solanaAddress
940
1257
  });
1258
+ return result;
941
1259
  };
942
1260
  var useDifferentAddressStore = zustand.create((set) => ({
943
1261
  differentAddress: void 0,
@@ -945,6 +1263,10 @@ var useDifferentAddressStore = zustand.create((set) => ({
945
1263
  isDepositPlatformToken: false,
946
1264
  setIsDepositPlatformToken: (isDepositPlatformToken) => set({ isDepositPlatformToken })
947
1265
  }));
1266
+ var useGetGasStore = zustand.create((set) => ({
1267
+ sponsorGas: false,
1268
+ setSponsorGas: (sponsorGas) => set({ sponsorGas })
1269
+ }));
948
1270
  var useWalletConnectModal = () => {
949
1271
  const { setShowAuthFlow } = sdkReactCore.useDynamicContext();
950
1272
  const { setShowLinkNewWalletModal } = sdkReactCore.useDynamicModals();
@@ -1058,6 +1380,7 @@ var Store = class {
1058
1380
  setStorageData(data) {
1059
1381
  setLocalStorage(this.key, JSON.stringify(data));
1060
1382
  }
1383
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1061
1384
  get(label) {
1062
1385
  const data = this.getStorageData();
1063
1386
  return data[label] || null;
@@ -1197,35 +1520,28 @@ var openFunctionHash = "0x3448bbc2203c608599ad448eeb1007cea04b788ac631f9f558e8dd
1197
1520
  function isApproveValid(approve) {
1198
1521
  return approve != null && typeof approve === "object" && Object.keys(approve).length > 0 && approve.amount !== void 0 && approve.spender !== void 0 && approve.token !== void 0;
1199
1522
  }
1200
-
1201
- // src/core/ui/toaster.tsx
1202
- var createToastStub = () => ({
1203
- success: (_opts) => {
1204
- },
1205
- error: (_opts) => {
1206
- },
1207
- warning: (_opts) => {
1208
- },
1209
- info: (_opts) => {
1210
- },
1211
- loading: (_opts) => {
1212
- },
1213
- create: (_opts) => "",
1214
- remove: (_id) => {
1215
- },
1216
- isActive: (_id) => false,
1217
- closeAll: () => {
1218
- },
1219
- close: (_id) => {
1220
- }
1523
+ var toaster = react.createToaster({
1524
+ placement: "top-end",
1525
+ pauseOnPageIdle: true
1526
+ });
1527
+ var bottomToaster = react.createToaster({
1528
+ placement: "bottom-end",
1529
+ pauseOnPageIdle: true
1530
+ });
1531
+ var topToaster = react.createToaster({
1532
+ placement: "top",
1533
+ pauseOnPageIdle: true
1221
1534
  });
1222
- var toaster = createToastStub();
1223
1535
  var initialState = {
1536
+ // fromTxHash:
1537
+ // '0x635470331be4c59357ff80b62c596ba5b09508d8c1572477ad7b2f4f0a0bd1a7' as `0x${string}`,
1224
1538
  fromTxHash: null,
1225
1539
  toTxHash: null,
1226
1540
  startTrading: false,
1227
1541
  solanaFromTxHash: null,
1228
1542
  isSolanaTransaction: false
1543
+ // fromValue: null,
1544
+ // tryAgain: false
1229
1545
  };
1230
1546
  var useTxStateContextStore = zustand.create((set) => ({
1231
1547
  ...initialState,
@@ -1464,9 +1780,6 @@ var useResetSwapAndBridgeState = () => {
1464
1780
  prevPathnameRef.current = currentPathname;
1465
1781
  }, []);
1466
1782
  };
1467
- var logger2 = {
1468
- error: (...args) => console.error(...args)
1469
- };
1470
1783
  var useGuardChain = (callback, requiredChainId) => {
1471
1784
  const [isSwitching, setIsSwitching] = React5.useState(false);
1472
1785
  const cb = React5.useRef(callback);
@@ -1479,29 +1792,42 @@ var useGuardChain = (callback, requiredChainId) => {
1479
1792
  isSwitching,
1480
1793
  sendTx: React5.useCallback(async () => {
1481
1794
  if (chainId !== requiredChainId) {
1795
+ console.log("###chainId is !== requiredChainId, need switch chain###");
1796
+ console.log(
1797
+ "###current chainId:",
1798
+ chainId,
1799
+ "requiredChainId:",
1800
+ requiredChainId
1801
+ );
1482
1802
  try {
1483
1803
  setIsSwitching(true);
1484
1804
  await connectRequiredChain(config, requiredChainId, connector);
1805
+ console.log("###switch chain success###");
1806
+ console.log("### reconnecting wagmi connector ###");
1485
1807
  try {
1486
1808
  await reconnectAsync();
1487
- } catch {
1809
+ } catch (reconnectError) {
1810
+ console.log("### reconnect failed, but continuing ###", reconnectError);
1488
1811
  }
1489
1812
  await new Promise((resolve) => setTimeout(resolve, 500));
1490
1813
  setIsSwitching(false);
1491
1814
  cb.current();
1492
1815
  } catch (error) {
1493
1816
  setIsSwitching(false);
1494
- logger2.error("switch chain error", error);
1817
+ console.log("###switch chain fail###");
1818
+ logger.error("switch chain error", error);
1495
1819
  throw new Error(
1496
1820
  `Failed to switch to ${getChainName(config, requiredChainId)}. Please switch manually in your wallet.`
1497
1821
  );
1498
1822
  }
1499
1823
  } else {
1500
1824
  if (!connector) {
1825
+ console.log("### connector is undefined on correct chain, reconnecting... ###");
1501
1826
  try {
1502
1827
  await reconnectAsync();
1503
1828
  await new Promise((resolve) => setTimeout(resolve, 300));
1504
- } catch {
1829
+ } catch (reconnectError) {
1830
+ console.log("### reconnect failed ###", reconnectError);
1505
1831
  }
1506
1832
  }
1507
1833
  cb.current();
@@ -1518,13 +1844,24 @@ async function connectRequiredChain(config, chainId, connector) {
1518
1844
  if (!chain) {
1519
1845
  throw new Error(`Chain with id ${chainId} not found in config`);
1520
1846
  }
1847
+ console.log("### connectRequiredChain ###", {
1848
+ chainId,
1849
+ chainName: chain.name
1850
+ });
1851
+ console.log("### connector ###", connector?.name, connector?.id);
1521
1852
  let provider;
1522
1853
  if (connector) {
1523
1854
  try {
1524
1855
  if (connector.id && connector.name) {
1525
1856
  provider = await connector.getProvider?.();
1857
+ console.log("### Got provider from connector ###", {
1858
+ connectorName: connector.name,
1859
+ connectorId: connector.id,
1860
+ isMetaMask: provider?.isMetaMask
1861
+ });
1526
1862
  }
1527
- } catch {
1863
+ } catch (e) {
1864
+ console.log("### Failed to get provider from connector, will use fallback ###", e);
1528
1865
  }
1529
1866
  }
1530
1867
  if (!provider) {
@@ -1544,17 +1881,30 @@ async function connectRequiredChain(config, chainId, connector) {
1544
1881
  } else {
1545
1882
  provider = ethereum;
1546
1883
  }
1884
+ console.log("### Fallback to window.ethereum ###", {
1885
+ isMetaMask: provider?.isMetaMask,
1886
+ isOkxWallet: provider?.isOkxWallet
1887
+ });
1547
1888
  }
1548
1889
  if (!provider) {
1549
1890
  throw new Error("No wallet provider found");
1550
1891
  }
1892
+ console.log("### Provider info ###", {
1893
+ isMetaMask: provider.isMetaMask,
1894
+ isConnected: provider.isConnected?.()
1895
+ });
1551
1896
  try {
1897
+ console.log("### Trying wallet_switchEthereumChain ###");
1552
1898
  await provider.request({
1553
1899
  method: "wallet_switchEthereumChain",
1554
1900
  params: [{ chainId: `0x${chainId.toString(16)}` }]
1555
1901
  });
1902
+ console.log("### wallet_switchEthereumChain success ###");
1556
1903
  } catch (switchError) {
1904
+ console.log("### switchChain error ###", switchError);
1905
+ console.log("### error.code ###", switchError?.code);
1557
1906
  if (switchError?.code === 4902) {
1907
+ console.log("### Chain not found, adding to wallet ###");
1558
1908
  const addChainParams = {
1559
1909
  chainId: `0x${chainId.toString(16)}`,
1560
1910
  chainName: chain.name,
@@ -1562,16 +1912,20 @@ async function connectRequiredChain(config, chainId, connector) {
1562
1912
  name: chain.nativeCurrency.name,
1563
1913
  symbol: chain.nativeCurrency.symbol,
1564
1914
  decimals: 18
1915
+ // Metamask requires decimals to be 18
1565
1916
  },
1566
1917
  rpcUrls: chain.rpcUrls.default.http,
1567
1918
  blockExplorerUrls: chain.blockExplorers?.default ? [chain.blockExplorers.default.url] : []
1568
1919
  };
1920
+ console.log("### addChainParams ###", addChainParams);
1569
1921
  try {
1570
1922
  await provider.request({
1571
1923
  method: "wallet_addEthereumChain",
1572
1924
  params: [addChainParams]
1573
1925
  });
1926
+ console.log("### Chain added successfully ###");
1574
1927
  } catch (addError) {
1928
+ console.log("### wallet_addEthereumChain error ###", addError);
1575
1929
  throw addError;
1576
1930
  }
1577
1931
  } else {
@@ -1616,11 +1970,311 @@ var useRefreshLoading = () => {
1616
1970
  }, [isLoading, setIsLoading]);
1617
1971
  return { isLoading, startLoading };
1618
1972
  };
1973
+ var katana2 = /* @__PURE__ */ viem.defineChain({
1974
+ id: 747474,
1975
+ name: "Katana",
1976
+ network: "katana",
1977
+ nativeCurrency: {
1978
+ name: "Ether",
1979
+ symbol: "ETH",
1980
+ decimals: 18
1981
+ },
1982
+ rpcUrls: {
1983
+ default: {
1984
+ http: ["https://rpc.katana.network"]
1985
+ }
1986
+ },
1987
+ blockExplorers: {
1988
+ default: {
1989
+ name: "katana explorer",
1990
+ url: "https://explorer.katanarpc.com"
1991
+ }
1992
+ },
1993
+ contracts: {
1994
+ multicall3: {
1995
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
1996
+ blockCreated: 1898013
1997
+ }
1998
+ },
1999
+ testnet: false
2000
+ });
2001
+ var hyperevm2 = /* @__PURE__ */ viem.defineChain({
2002
+ id: 999,
2003
+ name: "HyperEVM",
2004
+ network: "HYPE",
2005
+ nativeCurrency: {
2006
+ name: "HYPER",
2007
+ symbol: "HYPER",
2008
+ decimals: 18
2009
+ },
2010
+ rpcUrls: {
2011
+ default: {
2012
+ http: ["https://rpc.hyperliquid.xyz/evm", "https://rpc.hypurrscan.io"]
2013
+ }
2014
+ },
2015
+ blockExplorers: {
2016
+ default: {
2017
+ name: "Purrsec",
2018
+ url: "https://hyperevmscan.io"
2019
+ }
2020
+ },
2021
+ contracts: {
2022
+ multicall3: {
2023
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
2024
+ blockCreated: 13051
2025
+ }
2026
+ },
2027
+ testnet: false
2028
+ });
2029
+ var plasma2 = /* @__PURE__ */ viem.defineChain({
2030
+ id: 9745,
2031
+ name: "Plasma",
2032
+ network: "Plasma",
2033
+ nativeCurrency: {
2034
+ name: "Plasma",
2035
+ symbol: "XPL",
2036
+ decimals: 18
2037
+ },
2038
+ rpcUrls: {
2039
+ default: {
2040
+ http: ["https://rpc.plasma.to"]
2041
+ }
2042
+ },
2043
+ blockExplorers: {
2044
+ default: {
2045
+ name: "Plasma explorer",
2046
+ url: "https://plasmascan.to"
2047
+ }
2048
+ },
2049
+ contracts: {
2050
+ multicall3: {
2051
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
2052
+ blockCreated: 1
2053
+ }
2054
+ },
2055
+ testnet: true
2056
+ });
2057
+ var rari2 = /* @__PURE__ */ viem.defineChain({
2058
+ id: 1380012617,
2059
+ name: "RARI",
2060
+ network: "rari",
2061
+ nativeCurrency: {
2062
+ name: "Ether",
2063
+ symbol: "ETH",
2064
+ decimals: 18
2065
+ },
2066
+ rpcUrls: {
2067
+ default: {
2068
+ http: ["https://mainnet.rpc.rarichain.org/http"]
2069
+ }
2070
+ },
2071
+ blockExplorers: {
2072
+ default: {
2073
+ name: "RARI explorer",
2074
+ url: "https://mainnet.explorer.rarichain.org/"
2075
+ }
2076
+ },
2077
+ contracts: {
2078
+ multicall3: {
2079
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
2080
+ blockCreated: 1898013
2081
+ }
2082
+ },
2083
+ testnet: true
2084
+ });
2085
+
2086
+ // src/consts/stable.ts
2087
+ var stable2 = { tokens: [], id: 1 };
2088
+
2089
+ // src/consts/monad.ts
2090
+ var monad2 = { tokens: [], chains: [], id: 10143 };
2091
+
2092
+ // src/consts/mainnet.ts
2093
+ var mainnet3 = { tokens: [], chains: [], id: 1 };
2094
+ var metis2 = /* @__PURE__ */ viem.defineChain({
2095
+ id: 1088,
2096
+ name: "Metis",
2097
+ nativeCurrency: {
2098
+ decimals: 18,
2099
+ name: "Metis",
2100
+ symbol: "METIS"
2101
+ },
2102
+ rpcUrls: {
2103
+ default: {
2104
+ http: [
2105
+ "https://metis.api.onfinality.io/public",
2106
+ "https://metis-public.nodies.app",
2107
+ "https://metis-andromeda.rpc.thirdweb.com",
2108
+ "https://metis.drpc.org"
2109
+ ],
2110
+ webSocket: ["wss://metis-rpc.publicnode.com", "wss://metis.drpc.org"]
2111
+ }
2112
+ },
2113
+ blockExplorers: {
2114
+ default: {
2115
+ name: "Metis Explorer",
2116
+ url: "https://explorer.metis.io",
2117
+ apiUrl: "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan/api"
2118
+ }
2119
+ },
2120
+ contracts: {
2121
+ multicall3: {
2122
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
2123
+ blockCreated: 2338552
2124
+ }
2125
+ }
2126
+ });
2127
+ var polygonZkEvm2 = /* @__PURE__ */ viem.defineChain({
2128
+ id: 1101,
2129
+ name: "Polygon zkEVM",
2130
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
2131
+ rpcUrls: {
2132
+ default: {
2133
+ http: ["https://zkevm-rpc.com"]
2134
+ }
2135
+ },
2136
+ blockExplorers: {
2137
+ default: {
2138
+ name: "PolygonScan",
2139
+ url: "https://www.oklink.com/polygon-zkevm",
2140
+ apiUrl: "https://api-zkevm.polygonscan.com/api"
2141
+ }
2142
+ },
2143
+ contracts: {
2144
+ multicall3: {
2145
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
2146
+ blockCreated: 57746
2147
+ }
2148
+ }
2149
+ });
2150
+ var megaeth2 = /* @__PURE__ */ viem.defineChain({
2151
+ id: 4326,
2152
+ name: "MegaETH",
2153
+ network: "MegaETH",
2154
+ nativeCurrency: {
2155
+ name: "ETH",
2156
+ symbol: "ETH",
2157
+ decimals: 18
2158
+ },
2159
+ rpcUrls: {
2160
+ default: {
2161
+ http: ["https://mainnet.megaeth.com/rpc"]
2162
+ }
2163
+ },
2164
+ blockExplorers: {
2165
+ default: {
2166
+ name: "megaeth explorer",
2167
+ url: "https://megaeth.blockscout.com/"
2168
+ }
2169
+ },
2170
+ contracts: {
2171
+ multicall3: {
2172
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
2173
+ blockCreated: 0
2174
+ }
2175
+ },
2176
+ testnet: false
2177
+ });
2178
+
2179
+ // src/consts/chainsInfo.ts
2180
+ var allChains = [
2181
+ { chain: chains$1.mainnet, networkType: "mainnet" },
2182
+ { chain: chains$1.arbitrum, networkType: "mainnet" },
2183
+ { chain: chains$1.optimism, networkType: "mainnet" },
2184
+ { chain: chains$1.base, networkType: "mainnet" },
2185
+ { chain: chains$1.polygon, networkType: "mainnet" },
2186
+ { chain: chains$1.bsc, networkType: "mainnet" },
2187
+ { chain: chains$1.avalanche, networkType: "mainnet" },
2188
+ { chain: chains$1.zksync, networkType: "mainnet" },
2189
+ { chain: chains$1.linea, networkType: "mainnet" },
2190
+ { chain: chains$1.scroll, networkType: "mainnet" },
2191
+ { chain: chains$1.mantle, networkType: "mainnet" },
2192
+ { chain: chains$1.blast, networkType: "mainnet" },
2193
+ { chain: chains$1.celo, networkType: "mainnet" },
2194
+ { chain: chains$1.gnosis, networkType: "mainnet" },
2195
+ { chain: chains$1.sonic, networkType: "mainnet" },
2196
+ { chain: chains$1.zora, networkType: "mainnet" },
2197
+ { chain: chains$1.mode, networkType: "mainnet" },
2198
+ { chain: chains$1.taiko, networkType: "mainnet" },
2199
+ { chain: chains$1.sei, networkType: "mainnet" },
2200
+ { chain: chains$1.xdc, networkType: "mainnet" },
2201
+ { chain: chains$1.ink, networkType: "mainnet" },
2202
+ { chain: chains$1.soneium, networkType: "mainnet" },
2203
+ { chain: chains$1.worldchain, networkType: "mainnet" },
2204
+ { chain: chains$1.unichain, networkType: "mainnet" },
2205
+ { chain: chains$1.opBNB, networkType: "mainnet" },
2206
+ { chain: chains$1.lisk, networkType: "mainnet" },
2207
+ { chain: chains$1.morph, networkType: "mainnet" },
2208
+ { chain: chains$1.bob, networkType: "mainnet" },
2209
+ { chain: chains$1.abstract, networkType: "mainnet" },
2210
+ { chain: chains$1.hemi, networkType: "mainnet" },
2211
+ { chain: chains$1.xLayer, networkType: "mainnet" },
2212
+ { chain: chains$1.cronos, networkType: "mainnet" },
2213
+ { chain: chains$1.gravity, networkType: "mainnet" },
2214
+ { chain: chains$1.manta, networkType: "mainnet" },
2215
+ { chain: chains$1.zircuit, networkType: "mainnet" },
2216
+ { chain: chains$1.berachain, networkType: "mainnet" },
2217
+ { chain: chains$1.plumeMainnet, networkType: "mainnet" },
2218
+ { chain: chains$1.plume, networkType: "mainnet" },
2219
+ { chain: chains$1.hashkey, networkType: "mainnet" },
2220
+ { chain: chains$1.flowMainnet, networkType: "mainnet" },
2221
+ { chain: chains$1.etherlink, networkType: "mainnet" },
2222
+ { chain: chains$1.ronin, networkType: "mainnet" },
2223
+ { chain: chains$1.flare, networkType: "mainnet" },
2224
+ { chain: chains$1.rootstock, networkType: "mainnet" },
2225
+ { chain: chains$1.iota, networkType: "mainnet" },
2226
+ { chain: chains$1.pulsechain, networkType: "mainnet" },
2227
+ // custom chains
2228
+ { chain: katana2, networkType: "mainnet" },
2229
+ { chain: hyperevm2, networkType: "mainnet" },
2230
+ { chain: plasma2, networkType: "mainnet" },
2231
+ { chain: rari2, networkType: "mainnet" },
2232
+ { chain: stable2, networkType: "mainnet" },
2233
+ { chain: monad2, networkType: "mainnet" },
2234
+ { chain: mainnet3, networkType: "mainnet" },
2235
+ { chain: metis2, networkType: "mainnet" },
2236
+ { chain: polygonZkEvm2, networkType: "mainnet" },
2237
+ { chain: megaeth2, networkType: "mainnet" },
2238
+ // testnet
2239
+ { chain: chains$1.sepolia, networkType: "testnet" },
2240
+ { chain: chains$1.arbitrumSepolia, networkType: "testnet" },
2241
+ { chain: chains$1.optimismSepolia, networkType: "testnet" },
2242
+ { chain: chains$1.baseSepolia, networkType: "testnet" },
2243
+ { chain: chains$1.unichainSepolia, networkType: "testnet" }
2244
+ ];
2245
+ var testnetIdMapMainnetId = {
2246
+ [chains$1.sepolia.id]: chains$1.mainnet.id,
2247
+ [chains$1.arbitrumSepolia.id]: chains$1.arbitrum.id,
2248
+ [chains$1.optimismSepolia.id]: chains$1.optimism.id,
2249
+ [chains$1.baseSepolia.id]: chains$1.base.id,
2250
+ [chains$1.unichainSepolia.id]: chains$1.unichain.id
2251
+ };
2252
+ var chainsInfo = allChains.reduce(
2253
+ (acc, { chain }) => {
2254
+ acc[chain.id] = {
2255
+ name: chain.name ?? `Chain ${chain.id}`,
2256
+ id: chain.id,
2257
+ icon: chain.testnet ? `https://wheelx.fi/images/networks/${testnetIdMapMainnetId[chain.id] || chain.id}.png` : `https://wheelx.fi/images/networks/${chain.id}.png`,
2258
+ explorer: chain.blockExplorers?.default?.url,
2259
+ rpc: chain.rpcUrls?.default?.http?.[0] ?? ""
2260
+ };
2261
+ return acc;
2262
+ },
2263
+ {}
2264
+ );
2265
+ var defaultRpc = allChains.reduce(
2266
+ (acc, { chain }) => {
2267
+ acc[chain.id] = chain.rpcUrls?.default?.http?.[0] ?? "";
2268
+ return acc;
2269
+ },
2270
+ {}
2271
+ );
2272
+
2273
+ // src/core/hooks/useTokenBalance.ts
1619
2274
  var FRONTEND_MAX_RETRY_COUNT = 3;
1620
2275
  var REQUEST_TIMEOUT = 4e3;
1621
2276
  var BALANCE_REFETCH_INTERVAL = 12e3;
1622
2277
  var chainRpcMode = /* @__PURE__ */ new Map();
1623
- var defaultRpc = {};
1624
2278
  var getBalanceByClient = async (client, address, tokenAddress) => {
1625
2279
  if (tokenAddress) {
1626
2280
  const [value2, decimals, symbol] = await Promise.all([
@@ -1746,9 +2400,10 @@ var selectSolanaConnection = (providers) => {
1746
2400
  defaultProvider: solanaProviders?.[0]?.provider ?? null
1747
2401
  };
1748
2402
  };
1749
- var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
2403
+ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true, ownerAddress) => {
1750
2404
  const { solanaWalletAddress } = useWalletConnectedStore();
1751
2405
  const { defaultProvider: connection } = sdkReactCore.useRpcProviders(selectSolanaConnection);
2406
+ const resolvedOwnerAddress = ownerAddress || solanaWalletAddress;
1752
2407
  const normalizedTokenMint = normalizeAddress(tokenMintAddress);
1753
2408
  const isSolToken = !tokenMintAddress || normalizedTokenMint === normalizeAddress(SOL_MINT_ADDRESS) || normalizedTokenMint === normalizeAddress(SOL_NATIVE_ADDRESS);
1754
2409
  const {
@@ -1758,7 +2413,7 @@ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
1758
2413
  error,
1759
2414
  fetchAccountBalances
1760
2415
  } = sdkReactCore.useTokenBalances({
1761
- accountAddress: solanaWalletAddress || void 0,
2416
+ accountAddress: resolvedOwnerAddress || void 0,
1762
2417
  chainName: sdkReactCore.ChainEnum.Sol,
1763
2418
  networkId: SOLANA_MAINNET_NETWORK_ID,
1764
2419
  includeNativeBalance: true,
@@ -1772,7 +2427,7 @@ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
1772
2427
  React5.useEffect(() => {
1773
2428
  let cancelled = false;
1774
2429
  const fetchByRpc = async () => {
1775
- if (!isEnabled || !solanaWalletAddress || !connection) {
2430
+ if (!isEnabled || !resolvedOwnerAddress || !connection) {
1776
2431
  setRpcData(null);
1777
2432
  setRpcError(null);
1778
2433
  setRpcLoading(false);
@@ -1781,7 +2436,7 @@ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
1781
2436
  setRpcLoading(true);
1782
2437
  setRpcError(null);
1783
2438
  try {
1784
- const owner = new web3_js.PublicKey(solanaWalletAddress);
2439
+ const owner = new web3_js.PublicKey(resolvedOwnerAddress);
1785
2440
  if (isSolToken) {
1786
2441
  const lamports = await connection.getBalance(owner);
1787
2442
  if (cancelled) return;
@@ -1830,9 +2485,9 @@ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
1830
2485
  return () => {
1831
2486
  cancelled = true;
1832
2487
  };
1833
- }, [connection, isEnabled, isSolToken, solanaWalletAddress, tokenMintAddress]);
2488
+ }, [connection, isEnabled, isSolToken, resolvedOwnerAddress, tokenMintAddress]);
1834
2489
  const dynamicData = React5.useMemo(() => {
1835
- if (!isEnabled || !solanaWalletAddress) return null;
2490
+ if (!isEnabled || !resolvedOwnerAddress) return null;
1836
2491
  if (isSolToken) {
1837
2492
  const native = tokenBalances.find((item) => item.isNative);
1838
2493
  if (!native) {
@@ -1867,12 +2522,12 @@ var useSolanaTokenBalance = (tokenMintAddress, isEnabled = true) => {
1867
2522
  formatted: String(targetToken.balance ?? 0),
1868
2523
  symbol: targetToken.symbol || ""
1869
2524
  };
1870
- }, [isEnabled, isSolToken, normalizedTokenMint, solanaWalletAddress, tokenBalances]);
2525
+ }, [isEnabled, isSolToken, normalizedTokenMint, resolvedOwnerAddress, tokenBalances]);
1871
2526
  const data = React5.useMemo(() => {
1872
- if (!isEnabled || !solanaWalletAddress) return null;
2527
+ if (!isEnabled || !resolvedOwnerAddress) return null;
1873
2528
  if (rpcData) return rpcData;
1874
2529
  return dynamicData;
1875
- }, [dynamicData, isEnabled, rpcData, solanaWalletAddress]);
2530
+ }, [dynamicData, isEnabled, rpcData, resolvedOwnerAddress]);
1876
2531
  return {
1877
2532
  data,
1878
2533
  isLoading: isLoading || rpcLoading,
@@ -2511,24 +3166,29 @@ function useRetryAbleTransactionReceipt(hash, chain_id, maxRetries = 6) {
2511
3166
  lastError
2512
3167
  };
2513
3168
  }
2514
-
2515
- // src/core/utils/consts.ts
2516
3169
  var nullAddress = "0x0000000000000000000000000000000000000000";
3170
+ var hyperliquidChainId = 998;
2517
3171
  var ETH_TO_ETH_BRIDGE_SLIPPAGE = 0;
2518
3172
  var ETH_TO_ETH_BRIDGE_REFRESH_INTERVAL = 15;
2519
- var isETHtoETHBridge = (fromToken, toToken, chains) => {
2520
- if (!chains) return false;
2521
- const fromChain = chains.find((c) => c.chain_id === fromToken.chain_id);
2522
- const toChain = chains.find((c) => c.chain_id === toToken.chain_id);
2523
- if (!fromChain || !toChain) return false;
2524
- const fromIsEth = fromToken.address.toLowerCase() === fromChain.eth_token.toLowerCase();
2525
- const toIsEth = toToken.address.toLowerCase() === toChain.eth_token.toLowerCase();
2526
- const isDifferentChain = fromToken.chain_id !== toToken.chain_id;
2527
- return fromIsEth && toIsEth && isDifferentChain;
2528
- };
3173
+ function isETHtoETHBridge(fromTokenInfo, toTokenInfo, chains) {
3174
+ if (!fromTokenInfo || !toTokenInfo || !chains) return false;
3175
+ if (fromTokenInfo.chain_id === toTokenInfo.chain_id) return false;
3176
+ const fromChain = chains.find(
3177
+ (c) => c.chain_id === fromTokenInfo.chain_id
3178
+ );
3179
+ const toChain = chains.find(
3180
+ (c) => c.chain_id === toTokenInfo.chain_id
3181
+ );
3182
+ const fromIsETH = fromTokenInfo.address === fromChain?.eth_token || fromTokenInfo.tags?.includes("native");
3183
+ const toIsETH = toTokenInfo.address === toChain?.eth_token || toTokenInfo.tags?.includes("native");
3184
+ return fromIsETH && toIsETH;
3185
+ }
2529
3186
  var STABLECOIN_SAME_CHAIN_SLIPPAGE = 10;
2530
3187
  var STABLECOIN_CROSS_CHAIN_SLIPPAGE = 50;
2531
3188
  var STABLECOIN_REFRESH_INTERVAL = 30;
3189
+ var STABLECOIN_SAME_CHAIN_WARN_SLIPPAGE = 5;
3190
+ var STABLECOIN_CROSS_CHAIN_WARN_SLIPPAGE = 20;
3191
+ var HIGH_SLIPPAGE_WARN_THRESHOLD = 300;
2532
3192
  function isStablecoin(tokenInfo) {
2533
3193
  if (!tokenInfo?.categories) return false;
2534
3194
  return tokenInfo.categories.includes("stablecoin");
@@ -2558,7 +3218,26 @@ function getDefaultSlippage(policy, isBridge, isSameChain) {
2558
3218
  if (isBridge) return 200;
2559
3219
  return 0;
2560
3220
  }
2561
- var hyperliquidChainId = 998;
3221
+ function getLowSlippageWarnThreshold(fromTokenInfo, toTokenInfo, matchedPolicy, isETHtoETH = false) {
3222
+ if (!fromTokenInfo || !toTokenInfo) return 0;
3223
+ if (isETHtoETH) return 0;
3224
+ const isSameChain = fromTokenInfo.chain_id === toTokenInfo.chain_id;
3225
+ const isBridge = !isSameChain;
3226
+ if (isStablecoin(fromTokenInfo) && isStablecoin(toTokenInfo)) {
3227
+ return isBridge ? STABLECOIN_CROSS_CHAIN_WARN_SLIPPAGE : STABLECOIN_SAME_CHAIN_WARN_SLIPPAGE;
3228
+ }
3229
+ if (matchedPolicy?.min_slippage !== void 0) {
3230
+ return matchedPolicy.min_slippage;
3231
+ }
3232
+ return 0;
3233
+ }
3234
+ function isNativeToken(tokenInfo) {
3235
+ if (!tokenInfo) return false;
3236
+ if (isSolanaChain2(tokenInfo.chain_id)) {
3237
+ return tokenInfo.symbol?.toUpperCase() === "SOL" || String(tokenInfo.address) === "11111111111111111111111111111111";
3238
+ }
3239
+ return tokenInfo.address === viem.zeroAddress || tokenInfo.tags?.includes("native");
3240
+ }
2562
3241
  var calculateSlippage = (slippage) => {
2563
3242
  if (!slippage) return;
2564
3243
  const slippageFraction = new biFraction.Fraction(slippage);
@@ -2570,31 +3249,86 @@ var formatSlippage = (slippage) => {
2570
3249
  };
2571
3250
 
2572
3251
  // src/core/utils/debounce.ts
2573
- function debounce2(func, wait) {
2574
- let timeout = null;
3252
+ function debounce2(func, delay) {
3253
+ let timeoutId = null;
2575
3254
  return (...args) => {
2576
- if (timeout) clearTimeout(timeout);
2577
- timeout = setTimeout(() => {
3255
+ if (timeoutId) {
3256
+ clearTimeout(timeoutId);
3257
+ }
3258
+ timeoutId = setTimeout(() => {
2578
3259
  func(...args);
2579
- }, wait);
3260
+ timeoutId = null;
3261
+ }, delay);
2580
3262
  };
2581
3263
  }
2582
3264
 
2583
3265
  // src/core/utils/defaultData.ts
2584
3266
  var saveDay = [
2585
- { name: "Blast", chainId: 81457, day: 8 },
2586
- { name: "Bob", chainId: 60808, day: 5 },
2587
- { name: "Celo", chainId: 42220, day: 7 },
2588
- { name: "Gravity", chainId: 1625, day: 7 },
2589
- { name: "Hashkey Chain", chainId: 177, day: 7 },
2590
- { name: "Ink", chainId: 57073, day: 7 },
2591
- { name: "Lisk", chainId: 1135, day: 7 },
2592
- { name: "Mode", chainId: 34443, day: 7 },
2593
- { name: "opBNB", chainId: 204, day: 7 },
2594
- { name: "RARI", chainId: 1380012617, day: 8 },
2595
- { name: "Unichain", chainId: 130, day: 7 },
2596
- { name: "Worldchain", chainId: 480, day: 7 },
2597
- { name: "Zora", chainId: 7777777, day: 7 }
3267
+ {
3268
+ name: "Blast",
3269
+ chainId: 81457,
3270
+ day: 8
3271
+ },
3272
+ {
3273
+ name: "Bob",
3274
+ chainId: 60808,
3275
+ day: 5
3276
+ },
3277
+ {
3278
+ name: "Celo",
3279
+ chainId: 42220,
3280
+ day: 7
3281
+ },
3282
+ {
3283
+ name: "Gravity",
3284
+ chainId: 1625,
3285
+ day: 7
3286
+ },
3287
+ {
3288
+ name: "Hashkey Chain",
3289
+ chainId: 177,
3290
+ day: 7
3291
+ },
3292
+ {
3293
+ name: "Ink",
3294
+ chainId: 57073,
3295
+ day: 7
3296
+ },
3297
+ {
3298
+ name: "Lisk",
3299
+ chainId: 1135,
3300
+ day: 7
3301
+ },
3302
+ {
3303
+ name: "Mode",
3304
+ chainId: 34443,
3305
+ day: 7
3306
+ },
3307
+ {
3308
+ name: "opBNB",
3309
+ chainId: 204,
3310
+ day: 7
3311
+ },
3312
+ {
3313
+ name: "RARI",
3314
+ chainId: 1380012617,
3315
+ day: 8
3316
+ },
3317
+ {
3318
+ name: "Unichain",
3319
+ chainId: 130,
3320
+ day: 7
3321
+ },
3322
+ {
3323
+ name: "Worldchain",
3324
+ chainId: 480,
3325
+ day: 7
3326
+ },
3327
+ {
3328
+ name: "Zora",
3329
+ chainId: 7777777,
3330
+ day: 7
3331
+ }
2598
3332
  ];
2599
3333
 
2600
3334
  // ../../node_modules/@wagmi/core/dist/esm/utils/getAction.js
@@ -2924,29 +3658,6 @@ var getErc20Approval = (config) => {
2924
3658
  };
2925
3659
 
2926
3660
  // src/core/utils/index.ts
2927
- var getOrderedTokensChainSearch = (tokens) => tokens;
2928
- var getOrderedTokensAssets = (tokens) => tokens;
2929
- var mergeAndDeduplicate = (a, b, key = "") => [...a, ...b];
2930
- var STABLECOIN_SAME_CHAIN_WARN_SLIPPAGE = 5;
2931
- var STABLECOIN_CROSS_CHAIN_WARN_SLIPPAGE = 20;
2932
- var HIGH_SLIPPAGE_WARN_THRESHOLD = 300;
2933
- function isStablecoin2(tokenInfo) {
2934
- if (!tokenInfo?.categories) return false;
2935
- return tokenInfo.categories.includes("stablecoin");
2936
- }
2937
- function getLowSlippageWarnThreshold(fromTokenInfo, toTokenInfo, matchedPolicy, isETHtoETH = false) {
2938
- if (!fromTokenInfo || !toTokenInfo) return 0;
2939
- if (isETHtoETH) return 0;
2940
- const isSameChain = fromTokenInfo.chain_id === toTokenInfo.chain_id;
2941
- const isBridge = !isSameChain;
2942
- if (isStablecoin2(fromTokenInfo) && isStablecoin2(toTokenInfo)) {
2943
- return isBridge ? STABLECOIN_CROSS_CHAIN_WARN_SLIPPAGE : STABLECOIN_SAME_CHAIN_WARN_SLIPPAGE;
2944
- }
2945
- if (matchedPolicy?.min_slippage !== void 0) {
2946
- return matchedPolicy.min_slippage;
2947
- }
2948
- return 0;
2949
- }
2950
3661
  var formatDecimalNum = (val, fixed = 6) => {
2951
3662
  if (val === void 0 || val === null || val === "") return "";
2952
3663
  const num = Number(val);
@@ -3429,7 +4140,47 @@ var BoxWithBg = ({
3429
4140
  }) => {
3430
4141
  return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { w: "100%", bg: "#F5F6FF", borderRadius: "16px", p: 3, ...props, children });
3431
4142
  };
3432
- var OptimizedImage = (props) => /* @__PURE__ */ jsxRuntime.jsx(react.Image, { ...props });
4143
+ var OptimizedImage = React5.forwardRef(
4144
+ ({
4145
+ src,
4146
+ alt,
4147
+ width,
4148
+ height,
4149
+ fill = false,
4150
+ objectFit = "cover",
4151
+ w,
4152
+ h,
4153
+ ...props
4154
+ }, ref) => {
4155
+ const boxWidth = w ?? width;
4156
+ const boxHeight = h ?? height;
4157
+ const isPercentWidth = typeof boxWidth === "string" && boxWidth.endsWith("%");
4158
+ const shouldUseFill = fill || isPercentWidth;
4159
+ return /* @__PURE__ */ jsxRuntime.jsx(
4160
+ react.Box,
4161
+ {
4162
+ ref,
4163
+ position: shouldUseFill ? "relative" : "static",
4164
+ overflow: "hidden",
4165
+ w,
4166
+ h,
4167
+ ...props,
4168
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4169
+ react.Image,
4170
+ {
4171
+ src,
4172
+ alt,
4173
+ width: shouldUseFill ? "100%" : boxWidth,
4174
+ height: shouldUseFill ? "100%" : boxHeight,
4175
+ objectFit,
4176
+ loading: "lazy"
4177
+ }
4178
+ )
4179
+ }
4180
+ );
4181
+ }
4182
+ );
4183
+ OptimizedImage.displayName = "OptimizedImage";
3433
4184
 
3434
4185
  // src/core/utils/twoApprove.ts
3435
4186
  var useUSDTHandler = () => {
@@ -3471,7 +4222,9 @@ var FormButton = ({
3471
4222
  clearLockedRequestId,
3472
4223
  lockedRequestId,
3473
4224
  getQuote,
3474
- currentRequestId
4225
+ currentRequestId,
4226
+ skipEvmWalletConnect = false,
4227
+ skipSolanaWalletConnect = false
3475
4228
  }) => {
3476
4229
  const { theme } = useWidgetTheme();
3477
4230
  const address = useEvmAddress();
@@ -3691,11 +4444,19 @@ var FormButton = ({
3691
4444
  console.log("[Transaction] Connectors empty but wallet detected, triggering Dynamic reconnect...");
3692
4445
  openModal();
3693
4446
  setUserCancelsTransaction(true);
4447
+ toaster.create({
4448
+ description: "Please reconnect your EVM wallet and try again",
4449
+ type: "info"
4450
+ });
3694
4451
  return;
3695
4452
  }
3696
4453
  if (!txOwner || !txConnector) {
3697
4454
  setUserCancelsTransaction(true);
3698
4455
  openConnectModal();
4456
+ toaster.create({
4457
+ description: "Please reconnect EVM wallet and try again",
4458
+ type: "error"
4459
+ });
3699
4460
  return;
3700
4461
  }
3701
4462
  try {
@@ -3956,6 +4717,10 @@ var FormButton = ({
3956
4717
  const handleSolanaSwap = async () => {
3957
4718
  if (!isSolanaWalletConnected || !solanaWalletAddress) {
3958
4719
  setUserCancelsTransaction(true);
4720
+ toaster.create({
4721
+ description: "Please reconnect Solana wallet and try again",
4722
+ type: "error"
4723
+ });
3959
4724
  openModal();
3960
4725
  return;
3961
4726
  }
@@ -4038,7 +4803,7 @@ var FormButton = ({
4038
4803
  }
4039
4804
  ) });
4040
4805
  }
4041
- if ((fromTokenInfo.isSolana || toTokenInfo.isSolana) && !solanaWalletAddress) {
4806
+ if ((fromTokenInfo.isSolana || toTokenInfo.isSolana) && !solanaWalletAddress && !(skipSolanaWalletConnect && !fromTokenInfo.isSolana)) {
4042
4807
  return renderSolanaWalletConnectButton();
4043
4808
  }
4044
4809
  if (!fromTokenInfo.isSolana && !hasEvmUiWallet) {
@@ -4050,14 +4815,14 @@ var FormButton = ({
4050
4815
  }
4051
4816
  return renderEvmWalletConnectButton();
4052
4817
  } else if (!hasEvmUiWallet && solanaWalletAddress) {
4053
- if (!fromTokenInfo.isSolana && !toTokenInfo.isSolana || !fromTokenInfo.isSolana && toTokenInfo.isSolana || fromTokenInfo.isSolana && !toTokenInfo.isSolana) {
4818
+ if (!fromTokenInfo.isSolana && !toTokenInfo.isSolana || !fromTokenInfo.isSolana && toTokenInfo.isSolana || fromTokenInfo.isSolana && !toTokenInfo.isSolana && !skipEvmWalletConnect) {
4054
4819
  return renderEvmWalletConnectButton("EVM");
4055
4820
  }
4056
4821
  } else if (hasEvmUiWallet && !solanaWalletAddress) {
4057
- if (fromTokenInfo.isSolana || toTokenInfo.isSolana) {
4822
+ if (fromTokenInfo.isSolana || toTokenInfo.isSolana && !skipSolanaWalletConnect) {
4058
4823
  return renderSolanaWalletConnectButton();
4059
4824
  }
4060
- if (fromTokenInfo.isSolana && toTokenInfo.isSolana || !fromTokenInfo.isSolana && toTokenInfo.isSolana || fromTokenInfo.isSolana && !toTokenInfo.isSolana) {
4825
+ if (fromTokenInfo.isSolana && toTokenInfo.isSolana || !fromTokenInfo.isSolana && toTokenInfo.isSolana && !skipSolanaWalletConnect || fromTokenInfo.isSolana && !toTokenInfo.isSolana) {
4061
4826
  return renderSolanaWalletConnectButton();
4062
4827
  }
4063
4828
  }
@@ -4171,9 +4936,10 @@ var FormButton = ({
4171
4936
  )
4172
4937
  ] });
4173
4938
  };
4174
- function getOrderedTokensAssets2(tokens, selectedChain, propertyName) {
4939
+ function getOrderedTokensAssets(tokens, selectedChain, propertyName) {
4175
4940
  return tokens?.filter((token) => {
4176
- return true;
4941
+ if (!selectedChain) return true;
4942
+ return token.chain_id === selectedChain;
4177
4943
  }).sort((a, b) => {
4178
4944
  if (a.usdPrice === null && b.usdPrice === null) {
4179
4945
  if (a.balance && b.balance) {
@@ -4275,6 +5041,48 @@ function getOrderedTokensChainNormal(tokens, selectedChain, propertyName) {
4275
5041
  return 0;
4276
5042
  });
4277
5043
  }
5044
+ function getOrderedTokensChainSearch(tokens, selectedChain) {
5045
+ return tokens?.filter((token) => {
5046
+ if (!selectedChain) return true;
5047
+ return token.chain_id === selectedChain;
5048
+ }).sort((a, b) => {
5049
+ if (a.usdPrice && b.usdPrice && a.balance && b.balance) {
5050
+ if (a.balance === "NaN" && b.balance !== "NaN") {
5051
+ return -1;
5052
+ }
5053
+ if (a.balance !== "NaN" && b.balance === "NaN") {
5054
+ return 1;
5055
+ }
5056
+ if (a.balance === "NaN" && b.balance === "NaN") {
5057
+ return 0;
5058
+ }
5059
+ const aBalance = new biFraction.Fraction(a.usdPrice).mul(a.balance);
5060
+ const bBalance = new biFraction.Fraction(b.usdPrice).mul(b.balance);
5061
+ if (aBalance.gt(bBalance)) return -1;
5062
+ if (aBalance.lt(bBalance)) return 1;
5063
+ }
5064
+ if (a.balance && b.balance) {
5065
+ if (a.balance === "NaN" && b.balance !== "NaN") {
5066
+ return -1;
5067
+ }
5068
+ if (a.balance !== "NaN" && b.balance === "NaN") {
5069
+ return 1;
5070
+ }
5071
+ if (a.balance === "NaN" && b.balance === "NaN") {
5072
+ return 0;
5073
+ }
5074
+ if (new biFraction.Fraction(a.balance).gt(new biFraction.Fraction(b.balance))) return -1;
5075
+ if (new biFraction.Fraction(a.balance).lt(new biFraction.Fraction(b.balance))) return 1;
5076
+ }
5077
+ if (a.balance && !b.balance) return -1;
5078
+ if (!a.balance && b.balance) return 1;
5079
+ const aIsDin = a.token_type === "preset";
5080
+ const bIsDin = b.token_type === "preset";
5081
+ if (aIsDin && !bIsDin) return -1;
5082
+ if (!aIsDin && bIsDin) return 1;
5083
+ return 0;
5084
+ });
5085
+ }
4278
5086
  function processChains(favorites, allNetworks) {
4279
5087
  const favoriteNetworkIds = new Set(favorites.map((fav) => fav.networkId));
4280
5088
  const favoriteChains = allNetworks.filter(
@@ -4285,6 +5093,28 @@ function processChains(favorites, allNetworks) {
4285
5093
  );
4286
5094
  return { favoriteChains, nonFavoriteChains };
4287
5095
  }
5096
+ function mergeAndDeduplicate(arr1, arr2) {
5097
+ const mergedArray = [...arr1, ...arr2];
5098
+ const map = /* @__PURE__ */ new Map();
5099
+ for (const item of mergedArray) {
5100
+ const key = `${item.address}-${item.chain_id}`;
5101
+ if (!map.has(key)) {
5102
+ map.set(key, item);
5103
+ } else {
5104
+ const existingItem = map.get(key);
5105
+ const existingHasPreset = existingItem.token_type === "preset";
5106
+ const currentHasPreset = item.token_type === "preset";
5107
+ if (existingHasPreset && !currentHasPreset) {
5108
+ continue;
5109
+ } else if (!existingHasPreset && currentHasPreset) {
5110
+ map.set(key, item);
5111
+ } else {
5112
+ continue;
5113
+ }
5114
+ }
5115
+ }
5116
+ return Array.from(map.values());
5117
+ }
4288
5118
  function filterTokenByType(items, searchString) {
4289
5119
  return items.filter((item) => item.categories?.includes(searchString));
4290
5120
  }
@@ -4296,15 +5126,6 @@ function filterTokenUnType(items, excludeTypes) {
4296
5126
  });
4297
5127
  }
4298
5128
 
4299
- // src/consts/mainnet.ts
4300
- var mainnet3 = { id: 1 };
4301
-
4302
- // src/consts/monad.ts
4303
- var monad2 = { id: 10143 };
4304
-
4305
- // src/consts/stable.ts
4306
- var stable2 = { id: 1 };
4307
-
4308
5129
  // src/core/SelectTokenModal/hooks/useChainsAndTokensForSelect.ts
4309
5130
  [mainnet3.id, chains.base.id, chains.ink.id, chains.bsc.id, monad2.id, chains.soneium.id, stable2.id];
4310
5131
  var useChainsAndTokensForSelect = ({
@@ -4322,7 +5143,7 @@ var useChainsAndTokensForSelect = ({
4322
5143
  ],
4323
5144
  [data?.chains, data?.deposit_platforms?.prediction?.chains]
4324
5145
  );
4325
- const allChains = React5.useMemo(() => {
5146
+ const allChains2 = React5.useMemo(() => {
4326
5147
  if (!allowedChainIds || allowedChainIds.length === 0) return rawChains;
4327
5148
  const allowedSet = new Set(allowedChainIds);
4328
5149
  return rawChains.filter((c) => allowedSet.has(c.chain_id));
@@ -4351,39 +5172,39 @@ var useChainsAndTokensForSelect = ({
4351
5172
  setSearchTokensValue("");
4352
5173
  }, []);
4353
5174
  const popularChains = React5.useMemo(
4354
- () => (allChains ?? []).filter((chain) => chain.is_popular === true).sort((a, b) => {
5175
+ () => (allChains2 ?? []).filter((chain) => chain.is_popular === true).sort((a, b) => {
4355
5176
  const nameA = a.name.toLowerCase();
4356
5177
  const nameB = b.name.toLowerCase();
4357
5178
  if (nameA < nameB) return -1;
4358
5179
  if (nameA > nameB) return 1;
4359
5180
  return 0;
4360
5181
  }),
4361
- [allChains]
5182
+ [allChains2]
4362
5183
  );
4363
5184
  const currentChain = React5.useMemo(() => {
4364
5185
  if (selectedChainByPlatformId) {
4365
- return allChains?.find(
5186
+ return allChains2?.find(
4366
5187
  (chain) => chain.platform_id === selectedChainByPlatformId
4367
5188
  );
4368
5189
  } else {
4369
- return allChains?.find((chain) => chain.chain_id === selectedChain);
5190
+ return allChains2?.find((chain) => chain.chain_id === selectedChain);
4370
5191
  }
4371
- }, [allChains, selectedChain]);
5192
+ }, [allChains2, selectedChain]);
4372
5193
  const searchChains = React5.useMemo(() => {
4373
- return allChains?.filter((chain) => {
5194
+ return allChains2?.filter((chain) => {
4374
5195
  if (searchChainsValue === "") return false;
4375
5196
  return chain.name.toLowerCase().includes(searchChainsValue.toLowerCase()) || chain.chain_id.toString().includes(searchChainsValue.toLowerCase());
4376
5197
  });
4377
- }, [allChains, searchChainsValue]);
5198
+ }, [allChains2, searchChainsValue]);
4378
5199
  const orderedChains = React5.useMemo(
4379
- () => allChains?.filter((chain) => !chain.is_popular).sort((a, b) => {
5200
+ () => allChains2?.filter((chain) => !chain.is_popular).sort((a, b) => {
4380
5201
  const firstCharA = a.name.toLowerCase();
4381
5202
  const firstCharB = b.name.toLowerCase();
4382
5203
  if (firstCharA < firstCharB) return -1;
4383
5204
  if (firstCharA > firstCharB) return 1;
4384
5205
  return 0;
4385
5206
  }),
4386
- [allChains]
5207
+ [allChains2]
4387
5208
  );
4388
5209
  const tokensWithBalances = React5.useMemo(() => {
4389
5210
  if (!allTokens) return void 0;
@@ -4443,7 +5264,7 @@ var useChainsAndTokensForSelect = ({
4443
5264
  handleSearchChains,
4444
5265
  handleSearchTokens,
4445
5266
  resetSearch,
4446
- allChains
5267
+ allChains: allChains2
4447
5268
  };
4448
5269
  };
4449
5270
  var useUserHasSelectedFromNetwork = zustand.create(
@@ -4489,15 +5310,15 @@ var useSearchTokens = ({
4489
5310
  if (filteredTokens) {
4490
5311
  const newArr = mergeAndDeduplicate(tokenWithBalances, filteredTokens);
4491
5312
  if (!selectedChain) {
4492
- return getOrderedTokensAssets(newArr);
5313
+ return getOrderedTokensAssets(newArr, selectedChain);
4493
5314
  } else {
4494
- return getOrderedTokensChainSearch(newArr);
5315
+ return getOrderedTokensChainSearch(newArr, selectedChain);
4495
5316
  }
4496
5317
  } else {
4497
5318
  if (!selectedChain) {
4498
- return getOrderedTokensAssets(tokenWithBalances);
5319
+ return getOrderedTokensAssets(tokenWithBalances, selectedChain);
4499
5320
  } else {
4500
- return getOrderedTokensChainSearch(tokenWithBalances);
5321
+ return getOrderedTokensChainSearch(tokenWithBalances, selectedChain);
4501
5322
  }
4502
5323
  }
4503
5324
  } else {
@@ -4506,9 +5327,9 @@ var useSearchTokens = ({
4506
5327
  return token.symbol.toLowerCase().includes(searchTokensValue.toLowerCase());
4507
5328
  });
4508
5329
  if (!selectedChain) {
4509
- return getOrderedTokensAssets(filteredTokens);
5330
+ return getOrderedTokensAssets(filteredTokens, selectedChain);
4510
5331
  } else {
4511
- return getOrderedTokensChainSearch(filteredTokens);
5332
+ return getOrderedTokensChainSearch(filteredTokens, selectedChain);
4512
5333
  }
4513
5334
  }
4514
5335
  }, [newAllToken, searchTokenInfoResult, searchTokensValue, selectedChain]);
@@ -4779,14 +5600,13 @@ var TokenAmountHeading = ({
4779
5600
  suffix,
4780
5601
  ...props
4781
5602
  }) => {
4782
- const { theme } = useWidgetTheme();
4783
5603
  const _amount = formatTokenAmount({
4784
5604
  amount,
4785
5605
  decimals
4786
5606
  });
4787
5607
  const leadingZeros = countLeadingZerosAfterDecimal(_amount);
4788
5608
  if (leadingZeros > 5) {
4789
- return /* @__PURE__ */ jsxRuntime.jsxs(Heading, { variant: "heading8", ...props, as: "div", color: theme.defaultTextColor, whiteSpace: "nowrap", children: [
5609
+ return /* @__PURE__ */ jsxRuntime.jsxs(Heading, { variant: "heading8", ...props, as: "div", whiteSpace: "nowrap", children: [
4790
5610
  prefix,
4791
5611
  " ",
4792
5612
  _amount.slice(0, 3),
@@ -4805,7 +5625,7 @@ var TokenAmountHeading = ({
4805
5625
  suffix
4806
5626
  ] });
4807
5627
  }
4808
- return /* @__PURE__ */ jsxRuntime.jsxs(Heading, { variant: "heading11", ...props, as: "div", color: theme.defaultTextColor, whiteSpace: "nowrap", children: [
5628
+ return /* @__PURE__ */ jsxRuntime.jsxs(Heading, { variant: "heading11", ...props, as: "div", whiteSpace: "nowrap", children: [
4809
5629
  prefix,
4810
5630
  " ",
4811
5631
  _amount,
@@ -4826,7 +5646,7 @@ var TokenAmountText = ({
4826
5646
  });
4827
5647
  const leadingZeros = countLeadingZerosAfterDecimal(_amount);
4828
5648
  if (leadingZeros > 5) {
4829
- return /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content8", ...props, children: [
5649
+ return /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content7", ...props, as: "div", children: [
4830
5650
  prefix,
4831
5651
  " ",
4832
5652
  _amount.slice(0, 3),
@@ -4845,7 +5665,7 @@ var TokenAmountText = ({
4845
5665
  suffix
4846
5666
  ] });
4847
5667
  }
4848
- return /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content7", ...props, children: [
5668
+ return /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content7", ...props, as: "div", children: [
4849
5669
  prefix,
4850
5670
  " ",
4851
5671
  _amount,
@@ -4853,7 +5673,6 @@ var TokenAmountText = ({
4853
5673
  suffix
4854
5674
  ] });
4855
5675
  };
4856
- var chainsInfo = {};
4857
5676
  var TokenIconWithNetworkLogo = ({
4858
5677
  tokenInfo,
4859
5678
  customChainLogo,
@@ -4901,7 +5720,7 @@ var TokenIconWithNetworkLogo = ({
4901
5720
  w,
4902
5721
  h,
4903
5722
  borderRadius: "full",
4904
- src: logo || `https://wheelx.fi/images/default-token-icon.png`,
5723
+ src: logo || `/images/default-token-icon.png`,
4905
5724
  alt: name || "",
4906
5725
  objectFit: "cover",
4907
5726
  priority
@@ -5403,7 +6222,7 @@ var TokenList = ({
5403
6222
  }
5404
6223
  }
5405
6224
  if (isSelectAll) {
5406
- return getOrderedTokensAssets2(userTokens)?.map((token, index) => {
6225
+ return getOrderedTokensAssets(userTokens)?.map((token, index) => {
5407
6226
  return /* @__PURE__ */ jsxRuntime.jsx(
5408
6227
  TokenAndAddress,
5409
6228
  {
@@ -5598,7 +6417,7 @@ var AllChainsIcon = () => {
5598
6417
  /* @__PURE__ */ jsxRuntime.jsx(
5599
6418
  react.Image,
5600
6419
  {
5601
- src: "https://wheelx.fi/images/networks/1.png",
6420
+ src: "/images/networks/1.png",
5602
6421
  alt: "ethereum",
5603
6422
  w: "10px",
5604
6423
  h: "10px",
@@ -5608,7 +6427,7 @@ var AllChainsIcon = () => {
5608
6427
  /* @__PURE__ */ jsxRuntime.jsx(
5609
6428
  react.Image,
5610
6429
  {
5611
- src: "https://wheelx.fi/images/networks/56.png",
6430
+ src: "/images/networks/56.png",
5612
6431
  alt: "bnb",
5613
6432
  w: "10px",
5614
6433
  h: "10px",
@@ -5620,7 +6439,7 @@ var AllChainsIcon = () => {
5620
6439
  /* @__PURE__ */ jsxRuntime.jsx(
5621
6440
  react.Image,
5622
6441
  {
5623
- src: "https://wheelx.fi/images/networks/8453.png",
6442
+ src: "/images/networks/8453.png",
5624
6443
  alt: "base",
5625
6444
  w: "10px",
5626
6445
  h: "10px",
@@ -5630,7 +6449,7 @@ var AllChainsIcon = () => {
5630
6449
  /* @__PURE__ */ jsxRuntime.jsx(
5631
6450
  react.Image,
5632
6451
  {
5633
- src: "https://wheelx.fi/images/networks/42161.png",
6452
+ src: "/images/networks/42161.png",
5634
6453
  alt: "arbitrum",
5635
6454
  w: "10px",
5636
6455
  h: "10px",
@@ -6337,7 +7156,7 @@ var SelectTokenModal = ({
6337
7156
  handleSearchChains,
6338
7157
  handleSearchTokens,
6339
7158
  resetSearch,
6340
- allChains
7159
+ allChains: allChains2
6341
7160
  } = useChainsAndTokensForSelect({
6342
7161
  data,
6343
7162
  selectedChain,
@@ -6464,7 +7283,7 @@ var SelectTokenModal = ({
6464
7283
  [handleClose, onSelectToken]
6465
7284
  );
6466
7285
  const [isMobileChainsOpen, setIsMobileChainsOpen] = React5.useState(false);
6467
- const selectedChainInfo = allChains?.find((chain) => {
7286
+ const selectedChainInfo = allChains2?.find((chain) => {
6468
7287
  if (selectedChainByPlatformId) {
6469
7288
  return chain.platform_id === selectedChainByPlatformId;
6470
7289
  } else {
@@ -6702,7 +7521,8 @@ var TokenSelectAndInput = ({
6702
7521
  totalGasFee,
6703
7522
  isLoadingFeeData,
6704
7523
  isInsufficientBalance,
6705
- onOpenDialog
7524
+ onOpenDialog,
7525
+ config
6706
7526
  }) => {
6707
7527
  const address = useEvmAddress();
6708
7528
  const userWallets = sdkReactCore.useUserWallets();
@@ -7033,6 +7853,21 @@ var TokenSelectAndInput = ({
7033
7853
  }
7034
7854
  if (address && !solanaWalletAddress) {
7035
7855
  if (!fromTokenInfo.isSolana && isSolanaChain2(toTokenInfo.chain_id) || fromTokenInfo.isSolana && isSolanaChain2(toTokenInfo.chain_id)) {
7856
+ if (config?.solanaDifferentAddress) {
7857
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.HStack, { gap: 1, children: [
7858
+ renderSolanaWalletIcon(),
7859
+ /* @__PURE__ */ jsxRuntime.jsx(
7860
+ Text2,
7861
+ {
7862
+ variant: "content8",
7863
+ backgroundColor: theme.highlightBgColor,
7864
+ padding: "2px",
7865
+ color: theme.highlightTextColor,
7866
+ children: sliceAddress(config.solanaDifferentAddress)
7867
+ }
7868
+ )
7869
+ ] });
7870
+ }
7036
7871
  return /* @__PURE__ */ jsxRuntime.jsxs(
7037
7872
  react.HStack,
7038
7873
  {
@@ -7072,6 +7907,21 @@ var TokenSelectAndInput = ({
7072
7907
  if (!fromTokenInfo.isSolana && isSolanaChain2(toTokenInfo.chain_id) || fromTokenInfo.isSolana && isSolanaChain2(toTokenInfo.chain_id)) {
7073
7908
  return renderSolanaAddress(solanaWalletAddress);
7074
7909
  } else {
7910
+ if (config?.evmDifferentAddress) {
7911
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.HStack, { gap: 1, children: [
7912
+ walletIcon,
7913
+ /* @__PURE__ */ jsxRuntime.jsx(
7914
+ Text2,
7915
+ {
7916
+ variant: "content8",
7917
+ backgroundColor: theme.highlightBgColor,
7918
+ padding: "2px",
7919
+ color: theme.highlightTextColor,
7920
+ children: sliceAddress(config.evmDifferentAddress)
7921
+ }
7922
+ )
7923
+ ] });
7924
+ }
7075
7925
  return /* @__PURE__ */ jsxRuntime.jsxs(
7076
7926
  react.HStack,
7077
7927
  {
@@ -7347,10 +8197,10 @@ var TokenSelectAndInput = ({
7347
8197
  bottom: ["6px", "8px"],
7348
8198
  left: 0,
7349
8199
  paddingRight: [2, 4],
7350
- children: !isFrom && !isDepositPlatformToken && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: tokenInfo.isSolana ? solanaWalletAddress && /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content8", children: [
8200
+ children: !isFrom && !isDepositPlatformToken && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: tokenInfo.isSolana ? (solanaWalletAddress || config?.solanaDifferentAddress) && /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content8", children: [
7351
8201
  "Balance: ",
7352
8202
  displayBalance
7353
- ] }) : address && /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content8", children: [
8203
+ ] }) : (address || config?.evmDifferentAddress) && /* @__PURE__ */ jsxRuntime.jsxs(Text2, { variant: "content8", children: [
7354
8204
  "Balance: ",
7355
8205
  displayBalance
7356
8206
  ] }) })
@@ -8153,6 +9003,12 @@ var DifferentAddressDialogInner = ({
8153
9003
  isDepositPlatformToken
8154
9004
  ]);
8155
9005
  React5.useEffect(() => {
9006
+ if (isAddressError) {
9007
+ bottomToaster.error({
9008
+ description: isSolanaTarget ? "This address is not a valid Solana address." : "This address is not a EVM address.",
9009
+ duration: 3e3
9010
+ });
9011
+ }
8156
9012
  }, [isAddressError, isSolanaTarget]);
8157
9013
  return /* @__PURE__ */ jsxRuntime.jsx(
8158
9014
  react.Dialog.Root,
@@ -8358,6 +9214,92 @@ var DifferentAddressDialog = ({
8358
9214
  );
8359
9215
  };
8360
9216
  var DifferentAddressDialog_default = DifferentAddressDialog;
9217
+ var GetGas = ({ tokenInfo, onToggle, config }) => {
9218
+ const { theme } = useWidgetTheme();
9219
+ const { solanaWalletAddress } = useWalletConnectedStore();
9220
+ const address = useEvmAddress();
9221
+ const { sponsorGas, setSponsorGas } = useGetGasStore();
9222
+ const { tokens } = useTokensStore();
9223
+ const { chains } = useChainsStore();
9224
+ const isNative = React5.useMemo(() => isNativeToken(tokenInfo), [tokenInfo]);
9225
+ const supportSponsorGas = React5.useMemo(() => {
9226
+ if (!chains) return false;
9227
+ const chain = chains.find((c) => c.chain_id === tokenInfo.chain_id);
9228
+ return chain?.support_sponsor_gas ?? false;
9229
+ }, [chains, tokenInfo.chain_id]);
9230
+ const nativeToken = React5.useMemo(() => {
9231
+ if (!tokens) return null;
9232
+ return tokens.find(
9233
+ (t) => t.chain_id === tokenInfo.chain_id && isNativeToken(t)
9234
+ );
9235
+ }, [tokens, tokenInfo.chain_id]);
9236
+ const isSolana = React5.useMemo(() => {
9237
+ return isSolanaChain2(tokenInfo.chain_id);
9238
+ }, [tokenInfo.chain_id]);
9239
+ const evmOwnerAddress = !isSolana && !address && config?.evmDifferentAddress ? config.evmDifferentAddress : void 0;
9240
+ const evmNativeBalance = useTokenBalance2({
9241
+ chainId: tokenInfo.chain_id,
9242
+ tokenAddress: void 0,
9243
+ connectAddress: evmOwnerAddress
9244
+ });
9245
+ const solanaOwnerAddress = isSolana && !solanaWalletAddress && config?.solanaDifferentAddress ? config.solanaDifferentAddress : void 0;
9246
+ const { data: solanaNativeBalanceData } = useSolanaTokenBalance(
9247
+ void 0,
9248
+ isSolana,
9249
+ solanaOwnerAddress
9250
+ );
9251
+ const nativeBalance = React5.useMemo(() => {
9252
+ if (isSolana) return solanaNativeBalanceData ?? void 0;
9253
+ return evmNativeBalance;
9254
+ }, [isSolana, solanaNativeBalanceData, evmNativeBalance]);
9255
+ React5.useEffect(() => {
9256
+ if (!supportSponsorGas || isNative || nativeBalance === void 0) {
9257
+ setSponsorGas(false);
9258
+ return;
9259
+ }
9260
+ setSponsorGas(nativeBalance.value === 0n);
9261
+ }, [supportSponsorGas, isNative, nativeBalance, setSponsorGas]);
9262
+ const shouldShow = supportSponsorGas && !isNative && nativeBalance !== void 0 && nativeBalance.value === 0n;
9263
+ if (!shouldShow) return null;
9264
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9265
+ react.HStack,
9266
+ {
9267
+ w: "100%",
9268
+ h: "42px",
9269
+ padding: "0 14px",
9270
+ fontSize: "12px",
9271
+ color: theme.defaultTextColor,
9272
+ backgroundColor: theme.highlightBgColor,
9273
+ borderRadius: "10px",
9274
+ gap: 0,
9275
+ children: [
9276
+ /* @__PURE__ */ jsxRuntime.jsx(md.MdLocalGasStation, { width: "14px", height: "14px" }),
9277
+ /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { flex: 1, marginLeft: "5px", children: [
9278
+ "Get $",
9279
+ nativeToken?.symbol ?? "ETH",
9280
+ " as gas"
9281
+ ] }),
9282
+ /* @__PURE__ */ jsxRuntime.jsx(react.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(
9283
+ react.Switch.Root,
9284
+ {
9285
+ colorPalette: theme.getGasSwitchColorPalette ?? "purple",
9286
+ checked: sponsorGas,
9287
+ onCheckedChange: (e) => {
9288
+ setSponsorGas(e.checked);
9289
+ onToggle?.();
9290
+ },
9291
+ children: [
9292
+ /* @__PURE__ */ jsxRuntime.jsx(react.Switch.HiddenInput, {}),
9293
+ /* @__PURE__ */ jsxRuntime.jsx(react.Switch.Control, {}),
9294
+ /* @__PURE__ */ jsxRuntime.jsx(react.Switch.Label, {})
9295
+ ]
9296
+ }
9297
+ ) })
9298
+ ]
9299
+ }
9300
+ );
9301
+ };
9302
+ var GetGas_default = GetGas;
8361
9303
  var FormBody = ({
8362
9304
  getQuote,
8363
9305
  quoteInfo,
@@ -8393,6 +9335,7 @@ var FormBody = ({
8393
9335
  const [isInsufficientBalance, setIsInsufficientBalance] = React5.useState(false);
8394
9336
  const address = useEvmAddress();
8395
9337
  const { solanaWalletAddress } = useWalletConnectedStore();
9338
+ const { sponsorGas } = useGetGasStore();
8396
9339
  const slippage = address ? slippageStore.get(address) : customSlippage !== void 0 ? { value: customSlippage } : void 0;
8397
9340
  const fromTokenBalanceNormal = useTokenBalance2({
8398
9341
  chainId: fromTokenInfo.chain_id,
@@ -8402,6 +9345,11 @@ var FormBody = ({
8402
9345
  chainId: toTokenInfo.chain_id,
8403
9346
  tokenAddress: toTokenInfo.address === viem.zeroAddress ? void 0 : toTokenInfo.address
8404
9347
  });
9348
+ const toTokenFixedEvmBalance = useTokenBalance2({
9349
+ chainId: toTokenInfo.chain_id,
9350
+ tokenAddress: toTokenInfo.address === viem.zeroAddress ? void 0 : toTokenInfo.address,
9351
+ connectAddress: config?.evmDifferentAddress ? config.evmDifferentAddress : void 0
9352
+ });
8405
9353
  const { data: fromTokenBalanceHyperBack } = useHyperliquidBalance(
8406
9354
  address,
8407
9355
  isFromHyperChain
@@ -8457,10 +9405,10 @@ var FormBody = ({
8457
9405
  }, [fromTokenInfo.isSolana, solanaWalletAddress, address]);
8458
9406
  const toAddress = React5.useMemo(() => {
8459
9407
  if (toTokenInfo.isSolana) {
8460
- return solanaWalletAddress || "";
9408
+ return config?.solanaDifferentAddress || solanaWalletAddress || "";
8461
9409
  }
8462
- return differentAddress || address || "";
8463
- }, [toTokenInfo.isSolana, solanaWalletAddress, differentAddress, address]);
9410
+ return config?.evmDifferentAddress || differentAddress || address || "";
9411
+ }, [toTokenInfo.isSolana, solanaWalletAddress, differentAddress, address, config?.solanaDifferentAddress, config?.evmDifferentAddress]);
8464
9412
  const isFromNativeSOL = fromTokenInfo.isSolana && (fromTokenInfo.symbol?.toUpperCase() === "SOL" || fromTokenInfo.address === "11111111111111111111111111111111");
8465
9413
  const isToNativeSOL = toTokenInfo.isSolana && (toTokenInfo.symbol?.toUpperCase() === "SOL" || toTokenInfo.address === "11111111111111111111111111111111");
8466
9414
  const fromTokenBalanceSolana = useSolanaTokenBalance(
@@ -8489,19 +9437,29 @@ var FormBody = ({
8489
9437
  ]);
8490
9438
  const toTokenBalance = React5.useMemo(() => {
8491
9439
  if (toTokenInfo.isSolana) {
8492
- return toTokenBalanceSolana.data ? {
8493
- decimals: toTokenBalanceSolana.data.decimals,
8494
- value: toTokenBalanceSolana.data.value,
8495
- formatted: toTokenBalanceSolana.data.formatted
8496
- } : void 0;
9440
+ if (toTokenBalanceSolana.data) {
9441
+ return {
9442
+ decimals: toTokenBalanceSolana.data.decimals,
9443
+ value: toTokenBalanceSolana.data.value,
9444
+ formatted: toTokenBalanceSolana.data.formatted
9445
+ };
9446
+ }
9447
+ return void 0;
9448
+ }
9449
+ if (isToHyperChain) return toTokenBalanceHyper;
9450
+ if (!address && config?.evmDifferentAddress && toTokenFixedEvmBalance) {
9451
+ return toTokenFixedEvmBalance;
8497
9452
  }
8498
- return isToHyperChain ? toTokenBalanceHyper : toTokenBalanceNormal;
9453
+ return toTokenBalanceNormal;
8499
9454
  }, [
8500
9455
  toTokenInfo.isSolana,
8501
9456
  toTokenBalanceSolana.data,
8502
9457
  isToHyperChain,
8503
9458
  toTokenBalanceHyper,
8504
- toTokenBalanceNormal
9459
+ toTokenBalanceNormal,
9460
+ address,
9461
+ config?.evmDifferentAddress,
9462
+ toTokenFixedEvmBalance
8505
9463
  ]);
8506
9464
  const balanceInfo = React5.useMemo(() => {
8507
9465
  const fromBalance = new biFraction.Fraction(fromTokenBalance?.value ?? 0n);
@@ -8604,8 +9562,8 @@ var FormBody = ({
8604
9562
  if (isSelectingFromToken) {
8605
9563
  setFromTokenInfo(tokenInfo);
8606
9564
  if (isTestnetChain(tokenInfo.chain_id)) {
8607
- const isNativeToken = tokenInfo.tags?.includes("native") || tokenInfo.address === viem.zeroAddress;
8608
- if (isNativeToken) {
9565
+ const isNativeToken2 = tokenInfo.tags?.includes("native") || tokenInfo.address === viem.zeroAddress;
9566
+ if (isNativeToken2) {
8609
9567
  const otherToken = tokens?.find(
8610
9568
  (t) => t.chain_id === tokenInfo.chain_id && t.address !== tokenInfo.address
8611
9569
  );
@@ -8640,8 +9598,8 @@ var FormBody = ({
8640
9598
  } else {
8641
9599
  setToTokenInfo(tokenInfo);
8642
9600
  if (isTestnetChain(tokenInfo.chain_id)) {
8643
- const isNativeToken = tokenInfo.tags?.includes("native") || tokenInfo.address === viem.zeroAddress;
8644
- if (isNativeToken) {
9601
+ const isNativeToken2 = tokenInfo.tags?.includes("native") || tokenInfo.address === viem.zeroAddress;
9602
+ if (isNativeToken2) {
8645
9603
  const otherToken = tokens?.find(
8646
9604
  (t) => t.chain_id === tokenInfo.chain_id && t.address !== tokenInfo.address
8647
9605
  );
@@ -8709,9 +9667,9 @@ var FormBody = ({
8709
9667
  };
8710
9668
  const _toAddress = () => {
8711
9669
  if (_toTokenInfo.isSolana) {
8712
- return solanaWalletAddress || "";
9670
+ return config?.solanaDifferentAddress || solanaWalletAddress || "";
8713
9671
  }
8714
- return differentAddress || address || "";
9672
+ return config?.evmDifferentAddress || differentAddress || address || "";
8715
9673
  };
8716
9674
  const vCode = extractVPathSegment();
8717
9675
  await getQuote({
@@ -8725,7 +9683,8 @@ var FormBody = ({
8725
9683
  slippage: calculateSlippage(slippage?.value),
8726
9684
  toTokenDecimals: _toTokenInfo.decimals,
8727
9685
  affiliation: vCode,
8728
- to_platform_id: _toTokenInfo.platform_id || 0
9686
+ to_platform_id: _toTokenInfo.platform_id || 0,
9687
+ sponsor_gas: sponsorGas
8729
9688
  });
8730
9689
  saveTokenSelection();
8731
9690
  };
@@ -8749,7 +9708,8 @@ var FormBody = ({
8749
9708
  slippage: calculateSlippage(slippage?.value) || autoSlippage,
8750
9709
  toTokenDecimals: toTokenInfo.decimals,
8751
9710
  affiliation: vCode,
8752
- to_platform_id: toTokenInfo.platform_id || 0
9711
+ to_platform_id: toTokenInfo.platform_id || 0,
9712
+ sponsor_gas: sponsorGas
8753
9713
  });
8754
9714
  };
8755
9715
  const handleToAmountChange = (value) => {
@@ -8767,7 +9727,8 @@ var FormBody = ({
8767
9727
  amount: viem.parseUnits(fromAmount, fromTokenInfo.decimals).toString(),
8768
9728
  slippage: calculateSlippage(slippage?.value),
8769
9729
  toTokenDecimals: toTokenInfo.decimals,
8770
- to_platform_id: toTokenInfo.platform_id || 0
9730
+ to_platform_id: toTokenInfo.platform_id || 0,
9731
+ sponsor_gas: sponsorGas
8771
9732
  });
8772
9733
  };
8773
9734
  if (fromAddress && fromAmount) {
@@ -8830,12 +9791,14 @@ var FormBody = ({
8830
9791
  userBalance: balanceInfo.toBalance,
8831
9792
  usdPrice: toTokenUsdPrice,
8832
9793
  isInsufficientBalance,
8833
- onOpenDialog: handleOpenDifferentAddressDialog
9794
+ onOpenDialog: handleOpenDifferentAddressDialog,
9795
+ config
8834
9796
  }
8835
9797
  )
8836
9798
  ]
8837
9799
  }
8838
9800
  ),
9801
+ /* @__PURE__ */ jsxRuntime.jsx(GetGas_default, { tokenInfo: toTokenInfo, onToggle: refetchQuote, config }),
8839
9802
  /* @__PURE__ */ jsxRuntime.jsx(
8840
9803
  FormButton,
8841
9804
  {
@@ -8858,7 +9821,9 @@ var FormBody = ({
8858
9821
  currentRequestId: quoteInfo.request_id,
8859
9822
  clearLockedRequestId,
8860
9823
  lockedRequestId,
8861
- getQuote
9824
+ getQuote,
9825
+ skipEvmWalletConnect: !toTokenInfo.isSolana && !!config?.evmDifferentAddress,
9826
+ skipSolanaWalletConnect: toTokenInfo.isSolana && !!config?.solanaDifferentAddress
8862
9827
  }
8863
9828
  ),
8864
9829
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -8935,7 +9900,7 @@ var SlippageSettings = ({ refetchQuote }) => {
8935
9900
  [fromTokenInfo, toTokenInfo, chains]
8936
9901
  );
8937
9902
  const isStablecoinPair = React5.useMemo(
8938
- () => isStablecoin2(fromTokenInfo) && isStablecoin2(toTokenInfo),
9903
+ () => isStablecoin(fromTokenInfo) && isStablecoin(toTokenInfo),
8939
9904
  [fromTokenInfo, toTokenInfo]
8940
9905
  );
8941
9906
  const isSameChain = React5.useMemo(
@@ -9813,6 +10778,11 @@ var TxState = ({
9813
10778
  }
9814
10779
  }, [isError]);
9815
10780
  React5.useEffect(() => {
10781
+ if (timeOut && isTransactionBlocked) {
10782
+ topToaster.error({
10783
+ description: `This transaction is stuck on the source network. Please go to the wallet's activity section to speed up or cancel the transaction.`
10784
+ });
10785
+ }
9816
10786
  }, [isTransactionBlocked, timeOut]);
9817
10787
  React5.useEffect(() => {
9818
10788
  if (isSolanaTransaction && solanaFromTxHash) {
@@ -10485,7 +11455,7 @@ var TxState = ({
10485
11455
  ) });
10486
11456
  };
10487
11457
  async function getOrderHistory(address, offset = 0, limit = 4) {
10488
- const url = `${BASE_API_URL}/v1/orders`;
11458
+ const url = `${getBaseApiUrl()}/v1/orders`;
10489
11459
  const res = await axios6__default.default.get(url, {
10490
11460
  params: {
10491
11461
  address: Array.isArray(address) ? address : [address],
@@ -10921,10 +11891,10 @@ var MainForm = ({ config }) => {
10921
11891
  }, [fromTokenInfo.isSolana, solanaWalletAddress, address]);
10922
11892
  const toAddress = React5.useMemo(() => {
10923
11893
  if (toTokenInfo.isSolana) {
10924
- return solanaWalletAddress || "";
11894
+ return config?.solanaDifferentAddress || solanaWalletAddress || "";
10925
11895
  }
10926
- return differentAddress || address || "";
10927
- }, [toTokenInfo.isSolana, solanaWalletAddress, differentAddress, address]);
11896
+ return config?.evmDifferentAddress || differentAddress || address || "";
11897
+ }, [toTokenInfo.isSolana, solanaWalletAddress, differentAddress, address, config?.solanaDifferentAddress, config?.evmDifferentAddress]);
10928
11898
  React5.useEffect(() => {
10929
11899
  if (timerRef.current && (new biFraction.Fraction(fromAmount).eq(0) || fromTxHash || solanaFromTxHash || address)) {
10930
11900
  clearTimeout(timerRef.current);
@@ -11203,7 +12173,8 @@ var MainForm = ({ config }) => {
11203
12173
  affiliation: vCode,
11204
12174
  slippage: isAutoSlippage ? slippageValue && slippageValue !== "0" ? calculateSlippage(slippageValue) : slippageValue === "0" ? 0 : void 0 : calculateSlippage(slippageValue || slippage?.value),
11205
12175
  toTokenDecimals: toTokenInfo.decimals,
11206
- to_platform_id: toTokenInfo.platform_id || 0
12176
+ to_platform_id: toTokenInfo.platform_id || 0,
12177
+ sponsor_gas: useGetGasStore.getState().sponsorGas
11207
12178
  });
11208
12179
  },
11209
12180
  [
@@ -11450,12 +12421,20 @@ var MainForm = ({ config }) => {
11450
12421
  };
11451
12422
  var WheelXWidget = MainForm;
11452
12423
 
12424
+ exports.KNOWN_WALLET_UNIVERSAL_LINKS = KNOWN_WALLET_UNIVERSAL_LINKS;
11453
12425
  exports.WheelXProvider = WheelXProvider;
11454
12426
  exports.WheelXWidget = WheelXWidget;
11455
12427
  exports.WidgetThemeProvider = WidgetThemeProvider;
12428
+ exports.convertToDeepLink = convertToDeepLink;
11456
12429
  exports.defaultTheme = defaultTheme;
11457
12430
  exports.getChainsAndTokens = getChainsAndTokens;
12431
+ exports.isDeepLinkUrl = isDeepLinkUrl;
12432
+ exports.isMobileDevice = isMobileDevice;
12433
+ exports.isReactNativeWebView = isReactNativeWebView;
12434
+ exports.isWalletRelatedUrl = isWalletRelatedUrl;
12435
+ exports.isWebView = isWebView;
11458
12436
  exports.mergeTokensWithCompositeKey = mergeTokensWithCompositeKey;
12437
+ exports.shouldInterceptDeepLinks = shouldInterceptDeepLinks;
11459
12438
  exports.useChainsAndTokens = useChainsAndTokens;
11460
12439
  exports.useChainsStore = useChainsStore;
11461
12440
  exports.useDifferentAddressStore = useDifferentAddressStore;