0xtrails 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/address.d.ts.map +1 -1
  2. package/dist/analytics.d.ts +18 -0
  3. package/dist/analytics.d.ts.map +1 -1
  4. package/dist/apiClient.d.ts +1 -1
  5. package/dist/apiClient.d.ts.map +1 -1
  6. package/dist/{ccip-CWd4g9uZ.js → ccip-dLSEJjCf.js} +55 -55
  7. package/dist/cctpqueue.d.ts +1 -1
  8. package/dist/cctpqueue.d.ts.map +1 -1
  9. package/dist/constants.d.ts +1 -0
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/decoders.d.ts +58 -0
  12. package/dist/decoders.d.ts.map +1 -0
  13. package/dist/ens.d.ts +6 -0
  14. package/dist/ens.d.ts.map +1 -1
  15. package/dist/error.d.ts +7 -0
  16. package/dist/error.d.ts.map +1 -1
  17. package/dist/{index-BTUBzx4R.js → index-BXbaLmtt.js} +25694 -24507
  18. package/dist/index.js +2 -2
  19. package/dist/intents.d.ts +4 -4
  20. package/dist/intents.d.ts.map +1 -1
  21. package/dist/metaTxns.d.ts +1 -1
  22. package/dist/metaTxns.d.ts.map +1 -1
  23. package/dist/mode.d.ts +1 -1
  24. package/dist/mode.d.ts.map +1 -1
  25. package/dist/preconditions.d.ts +1 -1
  26. package/dist/preconditions.d.ts.map +1 -1
  27. package/dist/prepareSend.d.ts +30 -24
  28. package/dist/prepareSend.d.ts.map +1 -1
  29. package/dist/prices.d.ts +1 -1
  30. package/dist/prices.d.ts.map +1 -1
  31. package/dist/proxyCaller.d.ts +0 -1
  32. package/dist/proxyCaller.d.ts.map +1 -1
  33. package/dist/tokenBalances.d.ts +1 -1
  34. package/dist/tokenBalances.d.ts.map +1 -1
  35. package/dist/tokens.d.ts.map +1 -1
  36. package/dist/trails.d.ts +1 -1
  37. package/dist/trails.d.ts.map +1 -1
  38. package/dist/transactions.d.ts +4 -0
  39. package/dist/transactions.d.ts.map +1 -1
  40. package/dist/utils.d.ts +6 -0
  41. package/dist/utils.d.ts.map +1 -1
  42. package/dist/widget/components/DebugScreensDropdown.d.ts.map +1 -1
  43. package/dist/widget/components/ErrorDisplay.d.ts +9 -0
  44. package/dist/widget/components/ErrorDisplay.d.ts.map +1 -0
  45. package/dist/widget/components/FundSendForm.d.ts +1 -1
  46. package/dist/widget/components/FundSendForm.d.ts.map +1 -1
  47. package/dist/widget/components/OriginTransferInformation.d.ts +10 -0
  48. package/dist/widget/components/OriginTransferInformation.d.ts.map +1 -0
  49. package/dist/widget/components/PaySendForm.d.ts +1 -1
  50. package/dist/widget/components/PaySendForm.d.ts.map +1 -1
  51. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  52. package/dist/widget/components/Receipt.d.ts.map +1 -1
  53. package/dist/widget/components/Receive.d.ts +12 -0
  54. package/dist/widget/components/Receive.d.ts.map +1 -0
  55. package/dist/widget/components/Swap.d.ts +5 -1
  56. package/dist/widget/components/Swap.d.ts.map +1 -1
  57. package/dist/widget/components/SwapDisplay.d.ts +9 -0
  58. package/dist/widget/components/SwapDisplay.d.ts.map +1 -0
  59. package/dist/widget/components/TransferPendingVertical.d.ts +2 -0
  60. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  61. package/dist/widget/components/YellowWarningAnimation.d.ts +2 -0
  62. package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
  63. package/dist/widget/hooks/useDebugScreens.d.ts +22 -0
  64. package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -0
  65. package/dist/widget/hooks/useSendForm.d.ts +7 -3
  66. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  67. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  68. package/dist/widget/index.js +1 -1
  69. package/dist/widget/widget.d.ts.map +1 -1
  70. package/package.json +16 -15
  71. package/src/address.ts +3 -0
  72. package/src/analytics.ts +105 -4
  73. package/src/apiClient.ts +1 -1
  74. package/src/cctpqueue.ts +1 -1
  75. package/src/constants.ts +3 -0
  76. package/src/decoders.ts +310 -0
  77. package/src/ens.ts +16 -1
  78. package/src/error.ts +86 -1
  79. package/src/intents.ts +10 -2
  80. package/src/metaTxns.ts +1 -1
  81. package/src/mode.ts +1 -1
  82. package/src/preconditions.ts +1 -1
  83. package/src/prepareSend.ts +432 -114
  84. package/src/prices.ts +5 -1
  85. package/src/proxyCaller.ts +2 -14
  86. package/src/tokenBalances.ts +21 -17
  87. package/src/tokens.ts +62 -3
  88. package/src/trails.ts +2 -2
  89. package/src/transactions.ts +35 -18
  90. package/src/utils.ts +28 -0
  91. package/src/widget/compiled.css +2 -2
  92. package/src/widget/components/DebugScreensDropdown.tsx +3 -0
  93. package/src/widget/components/ErrorDisplay.tsx +150 -0
  94. package/src/widget/components/FundSendForm.tsx +62 -9
  95. package/src/widget/components/OriginTransferInformation.tsx +59 -0
  96. package/src/widget/components/PaySendForm.tsx +65 -12
  97. package/src/widget/components/QRCodeDeposit.tsx +5 -5
  98. package/src/widget/components/QrCode.tsx +1 -1
  99. package/src/widget/components/QuoteDetails.tsx +93 -25
  100. package/src/widget/components/Receipt.tsx +296 -103
  101. package/src/widget/components/Receive.tsx +146 -0
  102. package/src/widget/components/RecentTokens.tsx +1 -1
  103. package/src/widget/components/Swap.tsx +206 -85
  104. package/src/widget/components/SwapDisplay.tsx +68 -0
  105. package/src/widget/components/TokenSelector.tsx +1 -1
  106. package/src/widget/components/TransferPendingVertical.tsx +162 -112
  107. package/src/widget/components/YellowWarningAnimation.tsx +146 -0
  108. package/src/widget/hooks/useDebugScreens.ts +583 -0
  109. package/src/widget/hooks/useSendForm.ts +46 -4
  110. package/src/widget/hooks/useTokenList.ts +8 -27
  111. package/src/widget/widget.tsx +201 -484
@@ -15,7 +15,7 @@ import React, {
15
15
  } from "react"
16
16
  import { createPortal } from "react-dom"
17
17
  import type { Chain, WalletClient } from "viem"
18
- import { createWalletClient, custom, http, parseUnits, isAddress } from "viem"
18
+ import { createWalletClient, custom, http, isAddress } from "viem"
19
19
  import * as viemChains from "viem/chains"
20
20
  import type { Connector } from "wagmi"
21
21
  import {
@@ -26,7 +26,7 @@ import {
26
26
  WagmiContext,
27
27
  WagmiProvider,
28
28
  } from "wagmi"
29
- import { getChainInfo } from "../chains.js"
29
+ import { getChainInfo, getRpcUrl } from "../chains.js"
30
30
  import type { TransactionState } from "../transactions.js"
31
31
  import type { RelayerEnv, MetaTxnReceipt } from "../relayer.js"
32
32
  import type { Theme } from "../theme.js"
@@ -53,7 +53,6 @@ import {
53
53
  trackWidgetScreen,
54
54
  } from "../analytics.js"
55
55
  import type { PrepareSendQuote } from "../prepareSend.js"
56
- import { getNormalizedQuoteObject } from "../prepareSend.js"
57
56
  import type { SupportedToken } from "../tokens.js"
58
57
  import {
59
58
  getIsWalletRejectedError,
@@ -61,6 +60,7 @@ import {
61
60
  getFullErrorMessage,
62
61
  getIsApiError,
63
62
  getIsRateLimitedError,
63
+ getPrettifiedErrorMessage,
64
64
  } from "../error.js"
65
65
  import {
66
66
  setSequenceIndexerUrl,
@@ -74,6 +74,7 @@ import {
74
74
  } from "../config.js"
75
75
  import { FundSendForm } from "./components/FundSendForm.js"
76
76
  import { Swap } from "./components/Swap.js"
77
+ import { Receive } from "./components/Receive.js"
77
78
  import type { MeshConnectProps } from "./components/MeshConnectIframe.js"
78
79
  import { MeshConnectFlow } from "./components/MeshConnectFlow.js"
79
80
  import WalletConnectScreen from "./components/WalletConnect.js"
@@ -90,6 +91,8 @@ import { cssObjectToString } from "../cssUtils.js"
90
91
  import { useCheckout } from "./hooks/useCheckout.js"
91
92
  import { useWallets, walletConnectConnector, connectors } from "../wallets.js"
92
93
  import { isValidNumeric, isValidInteger } from "../prices.js"
94
+ import { ErrorDisplay } from "./components/ErrorDisplay.js"
95
+ import { useDebugScreens } from "./hooks/useDebugScreens.js"
93
96
 
94
97
  export const aaveClient = AaveClient.create()
95
98
 
@@ -99,7 +102,7 @@ const isValidToToToken = (toToken: string | null | undefined) => {
99
102
  return true // Empty values are considered valid
100
103
  }
101
104
  const token = String(toToken).trim()
102
- if (token === "ETH" || token === "USDC") {
105
+ if (token?.length > 0 && token?.length <= 5) {
103
106
  return true
104
107
  }
105
108
 
@@ -114,6 +117,7 @@ type Screen =
114
117
  | "fund-methods"
115
118
  | "earn-pools"
116
119
  | "swap"
120
+ | "receive"
117
121
  | "wallet-confirmation"
118
122
  | "qr-code-deposit"
119
123
  | "pending"
@@ -287,16 +291,6 @@ const useTransactionState = (
287
291
  (tx: TransactionState) => tx.state === "failed",
288
292
  )
289
293
 
290
- console.log(
291
- "[trails-sdk] Transaction state monitoring:",
292
- "allConfirmed:",
293
- allConfirmed,
294
- "hasFailures:",
295
- hasFailures,
296
- "states:",
297
- transactionStates.map((tx) => tx.state),
298
- )
299
-
300
294
  if (allConfirmed && !hasFailures && onComplete) {
301
295
  console.log(
302
296
  "[trails-sdk] All transactions confirmed, triggering completion",
@@ -354,8 +348,17 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
354
348
  const { recentTokens, addRecentToken } = useRecentTokens(address)
355
349
  const { wallets: allWallets } = useWallets()
356
350
  const [isModalOpen, setIsModalOpen] = useState(false)
351
+ const [currentMode, setCurrentMode] = useState<Mode>(mode)
357
352
  const [currentScreen, setCurrentScreen] = useState<Screen>(
358
- isConnected ? (mode === "swap" ? "swap" : "tokens") : "connect",
353
+ isConnected
354
+ ? currentMode === "swap"
355
+ ? "swap"
356
+ : currentMode === "receive"
357
+ ? "receive"
358
+ : "tokens"
359
+ : currentMode === "receive"
360
+ ? "receive"
361
+ : "connect",
359
362
  )
360
363
  const [selectedToken, setSelectedToken] = useState<Token | null>(null)
361
364
  const [selectedFundMethod, setSelectedFundMethod] =
@@ -438,11 +441,11 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
438
441
  // Validate toToken - must be "ETH", "USDC", or a valid hex address
439
442
  if (!isValidToToken) {
440
443
  console.error(
441
- "[trails-sdk] Invalid toToken prop: must be 'ETH', 'USDC', or a valid hex address. Received:",
444
+ "[trails-sdk] Invalid toToken prop: must be a valid token symbol or a valid hex address. Received:",
442
445
  toToken,
443
446
  )
444
447
  setError(
445
- "Invalid toToken: must be 'ETH', 'USDC', or a valid hex address",
448
+ "Invalid toToken: must be a valid token symbol or a valid hex address",
446
449
  )
447
450
  return
448
451
  }
@@ -455,14 +458,14 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
455
458
  setError("Invalid toAddress: must be a valid hex address")
456
459
  }
457
460
 
458
- if (mode === "fund") {
461
+ if (currentMode === "fund") {
459
462
  if (toAmount) {
460
463
  setError("toAmount is not allowed in fund mode")
461
464
  return
462
465
  }
463
466
  }
464
467
 
465
- if (mode === "swap") {
468
+ if (currentMode === "swap") {
466
469
  if (toAmount) {
467
470
  setError("toAmount is not allowed in swap mode")
468
471
  return
@@ -479,7 +482,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
479
482
  return
480
483
  }
481
484
  }
482
- }, [toAmount, toChainId, toToken, mode, toAddress])
485
+ }, [toAmount, toChainId, toToken, currentMode, toAddress])
483
486
 
484
487
  const walletClient = useWalletManager(address, chainId, connector)
485
488
 
@@ -497,6 +500,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
497
500
 
498
501
  const [meshConnectProps, setMeshConnectProps] =
499
502
  useState<Partial<MeshConnectProps> | null>(null)
503
+ const [isNavigatingBack, setIsNavigatingBack] = useState(false)
500
504
 
501
505
  // Hook to auto-select pool when mode is "earn" and toAddress is specified
502
506
  const useAutoSelectPool = (
@@ -586,7 +590,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
586
590
  return { poolsLoading }
587
591
  }
588
592
 
589
- useAutoSelectPool(mode, toAddress, toChainId, toToken)
593
+ useAutoSelectPool(currentMode, toAddress, toChainId, toToken)
590
594
 
591
595
  const {
592
596
  setOriginTxHash,
@@ -609,12 +613,31 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
609
613
  onCheckoutStatusUpdate,
610
614
  })
611
615
 
616
+ // Use the debug screens hook
617
+ const { handleDebugScreenSelect } = useDebugScreens({
618
+ setCurrentScreen,
619
+ setSelectedToken,
620
+ setTransactionStates,
621
+ setPrepareSendQuote,
622
+ setShowWalletConfirmRetry,
623
+ setCurrentMode,
624
+ setSelectedWalletId,
625
+ setShowWalletConnectionRetry,
626
+ setError,
627
+ setIsConnecting,
628
+ setMeshConnectProps,
629
+ isConnected,
630
+ })
631
+
612
632
  // redirect to tokens screen only once after initial connection
613
633
  const [alreadyRedirectedToTokens, setAlreadyRedirectedToTokens] =
614
634
  useState(false)
615
635
 
616
636
  // Update screen based on connection state and mode
617
637
  useEffect(() => {
638
+ if (isNavigatingBack) {
639
+ return
640
+ }
618
641
  if (isConnected) {
619
642
  if (
620
643
  currentScreen === "connect" ||
@@ -623,9 +646,11 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
623
646
  ) {
624
647
  if (!alreadyRedirectedToTokens) {
625
648
  setAlreadyRedirectedToTokens(true)
626
- // For swap mode, go directly to swap screen, otherwise go to tokens
627
- if (mode === "swap") {
649
+ // Route to appropriate screen based on mode
650
+ if (currentMode === "swap") {
628
651
  setCurrentScreen("swap")
652
+ } else if (currentMode === "receive") {
653
+ setCurrentScreen("receive")
629
654
  } else {
630
655
  setCurrentScreen("tokens")
631
656
  }
@@ -636,14 +661,21 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
636
661
  currentScreen !== "connect" &&
637
662
  currentScreen !== "wallet-connect" &&
638
663
  currentScreen !== "wallet-list" &&
639
- currentScreen !== "wallet-connection-pending"
664
+ currentScreen !== "wallet-connection-pending" &&
665
+ currentScreen !== "receive"
640
666
  ) {
641
667
  setTimeout(() => {
642
668
  setCurrentScreen("connect")
643
669
  }, 0)
644
670
  }
645
671
  }
646
- }, [isConnected, currentScreen, alreadyRedirectedToTokens, mode])
672
+ }, [
673
+ isConnected,
674
+ currentScreen,
675
+ alreadyRedirectedToTokens,
676
+ currentMode,
677
+ isNavigatingBack,
678
+ ])
647
679
 
648
680
  useEffect(() => {
649
681
  if (
@@ -660,12 +692,12 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
660
692
  selectedToken &&
661
693
  (currentScreen === "send-form" || currentScreen === "fund-form")
662
694
  ) {
663
- const targetScreen = mode === "fund" ? "fund-form" : "send-form"
695
+ const targetScreen = currentMode === "fund" ? "fund-form" : "send-form"
664
696
  if (currentScreen !== targetScreen) {
665
697
  setCurrentScreen(targetScreen)
666
698
  }
667
699
  }
668
- }, [mode, currentScreen, selectedToken])
700
+ }, [currentMode, currentScreen, selectedToken])
669
701
 
670
702
  useEffect(() => {
671
703
  trackWidgetScreen({
@@ -688,14 +720,14 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
688
720
 
689
721
  // Update generated calldata when amount changes in earn mode
690
722
  useEffect(() => {
691
- if (selectedPool && mode === "earn" && generatedCalldata) {
723
+ if (selectedPool && currentMode === "earn" && generatedCalldata) {
692
724
  // The calldata will be updated via the onAmountUpdate callback
693
725
  // This effect ensures we have the initial calldata set up
694
726
  console.log(
695
727
  "Earn mode: Pool selected, calldata ready for amount updates",
696
728
  )
697
729
  }
698
- }, [selectedPool, mode, generatedCalldata])
730
+ }, [selectedPool, currentMode, generatedCalldata])
699
731
 
700
732
  const handleWalletConnect = async (walletId: string) => {
701
733
  try {
@@ -755,12 +787,18 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
755
787
  console.error("[trails-sdk] Failed to disconnect:", error)
756
788
  }
757
789
 
758
- setCurrentScreen("connect")
790
+ if (currentMode === "receive") {
791
+ setCurrentScreen("receive")
792
+ } else {
793
+ setCurrentScreen("connect")
794
+ }
759
795
  }
760
796
 
761
797
  const handleContinue = () => {
762
- if (mode === "swap") {
798
+ if (currentMode === "swap") {
763
799
  setCurrentScreen("swap")
800
+ } else if (currentMode === "receive") {
801
+ setCurrentScreen("receive")
764
802
  } else {
765
803
  setCurrentScreen("tokens")
766
804
  }
@@ -789,7 +827,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
789
827
  setSelectedToken(token)
790
828
 
791
829
  // For earn mode, check if we have toAddress and toChainId specified
792
- if (mode === "earn") {
830
+ if (currentMode === "earn") {
793
831
  if (toAddress && toChainId) {
794
832
  // Skip earn-pools and go directly to send-form when toAddress and toChainId are specified
795
833
  setCurrentScreen("send-form")
@@ -800,25 +838,15 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
800
838
  // Go to earn-pools for pool selection when no specific destination is set
801
839
  setCurrentScreen("earn-pools")
802
840
  }
803
- } else if (mode === "swap") {
841
+ } else if (currentMode === "swap") {
804
842
  setCurrentScreen("swap")
843
+ } else if (currentMode === "receive") {
844
+ setCurrentScreen("send-form")
805
845
  } else {
806
- setCurrentScreen(mode === "fund" ? "fund-form" : "send-form")
846
+ setCurrentScreen(currentMode === "fund" ? "fund-form" : "send-form")
807
847
  }
808
848
 
809
- // Track the token in recent tokens
810
- const chainInfo = getChainInfo(token.chainId)
811
- const supportedToken: SupportedToken = {
812
- id: `${token.symbol}-${chainInfo?.name || token.chainId}`,
813
- symbol: token.symbol,
814
- name: token.name,
815
- contractAddress: token.contractAddress,
816
- decimals: token.contractInfo?.decimals || 18,
817
- chainId: token.chainId,
818
- chainName: chainInfo?.name || `Chain ${token.chainId}`,
819
- imageUrl: token.imageUrl,
820
- }
821
- addRecentToken(supportedToken)
849
+ handleTrackToken(token)
822
850
  } catch (err) {
823
851
  setError(
824
852
  err instanceof Error ? err.message : "An unknown error occurred",
@@ -846,13 +874,31 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
846
874
  handleTokenSelect(token)
847
875
  }
848
876
 
877
+ const handleTrackToken = (token: Token) => {
878
+ // Track the token in recent tokens
879
+ const chainInfo = getChainInfo(token.chainId)
880
+ const supportedToken: SupportedToken = {
881
+ id: `${token.symbol}-${chainInfo?.name || token.chainId}`,
882
+ symbol: token.symbol,
883
+ name: token.name,
884
+ contractAddress: token.contractAddress,
885
+ decimals: token.contractInfo?.decimals || (token as any).decimals || 18,
886
+ chainId: token.chainId,
887
+ chainName: chainInfo?.name || `Chain ${token.chainId}`,
888
+ imageUrl: token.imageUrl,
889
+ }
890
+ addRecentToken(supportedToken)
891
+ }
892
+
849
893
  const handleOnSend = async (amount: string, recipient: string) => {
850
894
  console.log("[trails-sdk] handleOnSend", amount, recipient)
851
895
  }
852
896
 
853
897
  const handleSendAnother = () => {
854
- if (mode === "swap") {
898
+ if (currentMode === "swap") {
855
899
  setCurrentScreen("swap")
900
+ } else if (currentMode === "receive") {
901
+ setCurrentScreen("receive")
856
902
  } else {
857
903
  setCurrentScreen("tokens")
858
904
  }
@@ -861,7 +907,8 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
861
907
 
862
908
  const resetState = useCallback(() => {
863
909
  setSelectedFundMethod("wallet")
864
- setCurrentScreen("connect")
910
+ // Reset to appropriate screen based on mode
911
+ setCurrentScreen(currentMode === "receive" ? "receive" : "connect")
865
912
  setSelectedToken(null)
866
913
  setSelectedPool(null)
867
914
  setSelectedWalletId(null)
@@ -875,12 +922,14 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
875
922
  setTransactionStates([])
876
923
  setPrepareSendQuote(null)
877
924
  setTotalCompletionSeconds(null)
925
+ setAlreadyRedirectedToTokens(false)
878
926
  }, [
879
927
  setDestinationTxHash,
880
928
  setDestinationChainId,
881
929
  setTransactionStates,
882
930
  setOriginTxHash,
883
931
  setOriginChainId,
932
+ currentMode,
884
933
  ])
885
934
 
886
935
  // Expose modal control methods via ref
@@ -906,6 +955,13 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
906
955
 
907
956
  const handleBack = () => {
908
957
  setError(null)
958
+ console.log("[trails-sdk] handleBack", currentScreen)
959
+
960
+ // Set flag to prevent auto-selection when navigating back
961
+ if (setIsNavigatingBack) {
962
+ setIsNavigatingBack(true)
963
+ }
964
+
909
965
  switch (currentScreen) {
910
966
  case "fund-methods":
911
967
  setCurrentScreen("connect")
@@ -921,8 +977,11 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
921
977
  setCurrentScreen("connect")
922
978
  setSelectedToken(null)
923
979
  break
980
+ case "receive":
981
+ setCurrentScreen("connect")
982
+ break
924
983
  case "send-form":
925
- if (mode === "earn" && !toAddress && !toChainId) {
984
+ if (currentMode === "earn" && !toAddress && !toChainId) {
926
985
  setCurrentScreen("earn-pools")
927
986
  } else {
928
987
  setCurrentScreen("tokens")
@@ -934,14 +993,39 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
934
993
  setSelectedToken(null)
935
994
  break
936
995
  case "wallet-confirmation":
937
- setCurrentScreen(mode === "fund" ? "fund-form" : "send-form")
996
+ setCurrentScreen(
997
+ currentMode === "fund"
998
+ ? "fund-form"
999
+ : currentMode === "swap"
1000
+ ? "swap"
1001
+ : currentMode === "receive"
1002
+ ? "receive"
1003
+ : currentMode === "earn"
1004
+ ? "earn-pools"
1005
+ : "send-form",
1006
+ )
938
1007
  break
939
1008
  case "qr-code-deposit":
940
- setCurrentScreen(mode === "fund" ? "fund-form" : "send-form")
1009
+ setCurrentScreen(
1010
+ currentMode === "fund"
1011
+ ? "fund-form"
1012
+ : currentMode === "swap"
1013
+ ? "swap"
1014
+ : currentMode === "receive"
1015
+ ? "receive"
1016
+ : currentMode === "earn"
1017
+ ? "earn-pools"
1018
+ : "send-form",
1019
+ )
941
1020
  break
942
1021
  case "receipt":
943
- setCurrentScreen("tokens")
944
- setSelectedToken(null)
1022
+ // In receive mode, going back should go to receive screen
1023
+ if (currentMode === "receive") {
1024
+ setCurrentScreen("receive")
1025
+ } else {
1026
+ setCurrentScreen("tokens")
1027
+ setSelectedToken(null)
1028
+ }
945
1029
  setDestinationTxHash("")
946
1030
  setDestinationChainId(null)
947
1031
  setOriginTxHash("")
@@ -967,6 +1051,13 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
967
1051
  default:
968
1052
  break
969
1053
  }
1054
+
1055
+ // Reset the flag after a short delay to allow the screen change to complete
1056
+ if (setIsNavigatingBack) {
1057
+ setTimeout(() => {
1058
+ setIsNavigatingBack(false)
1059
+ }, 100)
1060
+ }
970
1061
  }
971
1062
 
972
1063
  function handleWalletConfirmComplete() {
@@ -1026,420 +1117,6 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
1026
1117
  setTransactionStates([..._transactionStates])
1027
1118
  }
1028
1119
 
1029
- const handleDebugScreenSelect = async (screen: string) => {
1030
- // Reset necessary state based on the target screen
1031
- setError(null)
1032
-
1033
- const dummySelectedToken = {
1034
- id: 1,
1035
- name: "USD Coin",
1036
- symbol: "USDC",
1037
- balance: parseUnits("1.99", 6)?.toString(),
1038
- imageUrl:
1039
- "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
1040
- chainId: 1,
1041
- contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
1042
- contractInfo: {
1043
- decimals: 6,
1044
- symbol: "USDC",
1045
- name: "USD Coin",
1046
- },
1047
- }
1048
-
1049
- const dummyQuote = await getNormalizedQuoteObject({
1050
- originAddress: "0x5A0fb747531bC369367CB031472b89ea4D5c6Df7",
1051
- originAmount: parseUnits("1", 6)?.toString(),
1052
- originTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
1053
- originChainId: 1,
1054
- originTokenPriceUsd: "1",
1055
- destinationChainId: 137,
1056
- destinationTokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
1057
- destinationAmount: parseUnits("0.97", 6)?.toString(),
1058
- destinationTokenPriceUsd: "1",
1059
- })
1060
-
1061
- switch (screen) {
1062
- case "connect":
1063
- setSelectedToken(null)
1064
- setTransactionStates([])
1065
- setCurrentScreen("connect")
1066
- break
1067
- case "tokens":
1068
- if (isConnected) {
1069
- setSelectedToken(null)
1070
- setTransactionStates([])
1071
- setCurrentScreen("tokens")
1072
- }
1073
- break
1074
- case "send-form":
1075
- // Set dummy USDC token for debug mode
1076
- setSelectedToken(dummySelectedToken)
1077
- setTransactionStates([])
1078
- setCurrentScreen("send-form")
1079
- break
1080
- case "fund-form":
1081
- // Set dummy USDC token for debug mode
1082
- setSelectedToken(dummySelectedToken)
1083
- setTransactionStates([])
1084
- setCurrentScreen("fund-form")
1085
- break
1086
- case "wallet-confirmation":
1087
- // Set dummy USDC token for debug mode
1088
- setSelectedToken(dummySelectedToken)
1089
- setPrepareSendQuote(dummyQuote)
1090
- setTransactionStates([])
1091
- setShowWalletConfirmRetry(false)
1092
- setCurrentScreen("wallet-confirmation")
1093
- break
1094
- case "wallet-confirmation-retry":
1095
- // Set dummy USDC token for debug mode
1096
- setSelectedToken(dummySelectedToken)
1097
- setPrepareSendQuote(dummyQuote)
1098
- setTransactionStates([])
1099
- setShowWalletConfirmRetry(true)
1100
- setCurrentScreen("wallet-confirmation")
1101
- break
1102
- case "pending-1-item-0-confirmed":
1103
- // Set dummy transaction states for debug mode - showing all steps
1104
- setTransactionStates([
1105
- {
1106
- transactionHash:
1107
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1108
- explorerUrl:
1109
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1110
- chainId: 137,
1111
- state: "pending",
1112
- label: "Swap",
1113
- },
1114
- ])
1115
- setPrepareSendQuote(dummyQuote)
1116
- setCurrentScreen("pending")
1117
- break
1118
- case "pending-1-item-1-confirmed":
1119
- // Set dummy transaction states for debug mode - showing all steps
1120
- setTransactionStates([
1121
- {
1122
- transactionHash:
1123
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1124
- explorerUrl:
1125
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1126
- chainId: 137,
1127
- state: "confirmed",
1128
- label: "Swap",
1129
- },
1130
- ])
1131
- setPrepareSendQuote(dummyQuote)
1132
- setCurrentScreen("pending")
1133
- break
1134
- case "pending-2-item-0-confirmed":
1135
- // Set dummy transaction states for debug mode - showing all steps
1136
- setTransactionStates([
1137
- {
1138
- transactionHash:
1139
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1140
- explorerUrl:
1141
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1142
- chainId: 137,
1143
- state: "pending",
1144
- label: "Transfer",
1145
- },
1146
- {
1147
- transactionHash:
1148
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1149
- explorerUrl:
1150
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1151
- chainId: 137,
1152
- state: "pending",
1153
- label: "Swap",
1154
- },
1155
- ])
1156
- setPrepareSendQuote(dummyQuote)
1157
- setCurrentScreen("pending")
1158
- break
1159
- case "pending-2-item-1-confirmed":
1160
- // Set dummy transaction states for debug mode - showing all steps
1161
- setTransactionStates([
1162
- {
1163
- transactionHash:
1164
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1165
- explorerUrl:
1166
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1167
- chainId: 137,
1168
- state: "confirmed",
1169
- label: "Transfer",
1170
- },
1171
- {
1172
- transactionHash:
1173
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1174
- explorerUrl:
1175
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1176
- chainId: 137,
1177
- state: "pending",
1178
- label: "Swap",
1179
- },
1180
- ])
1181
- setPrepareSendQuote(dummyQuote)
1182
- setCurrentScreen("pending")
1183
- break
1184
- case "pending-2-item-2-confirmed":
1185
- // Set dummy transaction states for debug mode - showing all steps
1186
- setTransactionStates([
1187
- {
1188
- transactionHash:
1189
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1190
- explorerUrl:
1191
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1192
- chainId: 137,
1193
- state: "confirmed",
1194
- label: "Transfer",
1195
- },
1196
- {
1197
- transactionHash:
1198
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1199
- explorerUrl:
1200
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1201
- chainId: 137,
1202
- state: "confirmed",
1203
- label: "Swap",
1204
- },
1205
- ])
1206
- setPrepareSendQuote(dummyQuote)
1207
- setCurrentScreen("pending")
1208
- break
1209
- case "pending-3-item-0-confirmed":
1210
- // Set dummy transaction states for debug mode - showing all steps
1211
- setTransactionStates([
1212
- {
1213
- transactionHash:
1214
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1215
- explorerUrl:
1216
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1217
- chainId: 137,
1218
- state: "pending",
1219
- label: "Transfer",
1220
- },
1221
- {
1222
- transactionHash:
1223
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1224
- explorerUrl:
1225
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1226
- chainId: 137,
1227
- state: "pending",
1228
- label: "Swap & Bridge",
1229
- },
1230
- {
1231
- transactionHash:
1232
- "0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1233
- explorerUrl:
1234
- "https://arbiscan.io/tx/0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1235
- chainId: 42161,
1236
- state: "pending",
1237
- label: "Execute",
1238
- },
1239
- ])
1240
- setPrepareSendQuote(dummyQuote)
1241
- setCurrentScreen("pending")
1242
- break
1243
- case "pending-3-item-1-confirmed":
1244
- // Set dummy transaction states for debug mode - showing all steps
1245
- setTransactionStates([
1246
- {
1247
- transactionHash:
1248
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1249
- explorerUrl:
1250
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1251
- chainId: 137,
1252
- state: "confirmed",
1253
- label: "Transfer",
1254
- },
1255
- {
1256
- transactionHash:
1257
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1258
- explorerUrl:
1259
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1260
- chainId: 137,
1261
- state: "pending",
1262
- label: "Swap & Bridge",
1263
- },
1264
- {
1265
- transactionHash:
1266
- "0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1267
- explorerUrl:
1268
- "https://arbiscan.io/tx/0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1269
- chainId: 42161,
1270
- state: "pending",
1271
- label: "Execute",
1272
- },
1273
- ])
1274
- setPrepareSendQuote(dummyQuote)
1275
- setCurrentScreen("pending")
1276
- break
1277
- case "pending-3-item-2-confirmed":
1278
- // Set dummy transaction states for debug mode - showing all steps
1279
- setTransactionStates([
1280
- {
1281
- transactionHash:
1282
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1283
- explorerUrl:
1284
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1285
- chainId: 137,
1286
- state: "confirmed",
1287
- label: "Transfer",
1288
- },
1289
- {
1290
- transactionHash:
1291
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1292
- explorerUrl:
1293
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1294
- chainId: 137,
1295
- state: "confirmed",
1296
- label: "Swap & Bridge",
1297
- },
1298
- {
1299
- transactionHash:
1300
- "0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1301
- explorerUrl:
1302
- "https://arbiscan.io/tx/0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1303
- chainId: 42161,
1304
- state: "pending",
1305
- label: "Execute",
1306
- },
1307
- ])
1308
- setPrepareSendQuote(dummyQuote)
1309
- setCurrentScreen("pending")
1310
- break
1311
- case "pending-3-item-3-confirmed":
1312
- // Set dummy transaction states for debug mode - showing all steps
1313
- setTransactionStates([
1314
- {
1315
- transactionHash:
1316
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1317
- explorerUrl:
1318
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1319
- chainId: 137,
1320
- state: "confirmed",
1321
- label: "Transfer",
1322
- },
1323
- {
1324
- transactionHash:
1325
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1326
- explorerUrl:
1327
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1328
- chainId: 137,
1329
- state: "confirmed",
1330
- label: "Swap & Bridge",
1331
- },
1332
- {
1333
- transactionHash:
1334
- "0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1335
- explorerUrl:
1336
- "https://arbiscan.io/tx/0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1337
- chainId: 42161,
1338
- state: "confirmed",
1339
- label: "Execute",
1340
- },
1341
- ])
1342
- setPrepareSendQuote(dummyQuote)
1343
- setCurrentScreen("pending")
1344
- break
1345
- case "receipt":
1346
- // Set dummy transaction states data for debug mode
1347
- setTransactionStates([
1348
- {
1349
- transactionHash:
1350
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1351
- explorerUrl:
1352
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1353
- chainId: 137,
1354
- state: "confirmed",
1355
- label: "Transfer",
1356
- },
1357
- {
1358
- transactionHash:
1359
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1360
- explorerUrl:
1361
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1362
- chainId: 137,
1363
- state: "confirmed",
1364
- label: "Swap & Bridge",
1365
- },
1366
- {
1367
- transactionHash:
1368
- "0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1369
- explorerUrl:
1370
- "https://arbiscan.io/tx/0xf3b172111d2e64e9d4940d91097f04a0bbd0acc816e2cf49eec664c6f8fcaf76",
1371
- chainId: 42161,
1372
- state: "confirmed",
1373
- label: "Execute",
1374
- },
1375
- ])
1376
-
1377
- setCurrentScreen("receipt")
1378
- break
1379
- case "receipt-failed":
1380
- // Set dummy transaction states data for debug mode
1381
- setTransactionStates([
1382
- {
1383
- transactionHash:
1384
- "0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1385
- explorerUrl:
1386
- "https://polygonscan.com/tx/0x45bb2259631e73f32841a6058b0a4008c75bca296942bec6326d188978d5353d",
1387
- chainId: 137,
1388
- state: "confirmed",
1389
- label: "Transfer",
1390
- },
1391
- {
1392
- transactionHash:
1393
- "0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1394
- explorerUrl:
1395
- "https://polygonscan.com/tx/0x6ff30196ca0d4998cc6928bca2ec282766eb3c3997535e0a61e0d69c9c9b16b8",
1396
- chainId: 137,
1397
- state: "confirmed",
1398
- label: "Swap & Bridge",
1399
- },
1400
- {
1401
- transactionHash: "",
1402
- explorerUrl: "",
1403
- chainId: 42161,
1404
- state: "failed",
1405
- label: "Execute",
1406
- },
1407
- ])
1408
-
1409
- setCurrentScreen("receipt")
1410
- break
1411
- case "mesh-connect":
1412
- setCurrentScreen("mesh-connect")
1413
- break
1414
- case "wallet-connect":
1415
- setCurrentScreen("wallet-connect")
1416
- break
1417
- case "wallet-list":
1418
- setCurrentScreen("wallet-list")
1419
- break
1420
- case "wallet-connection-pending":
1421
- setSelectedWalletId("metamask")
1422
- setCurrentScreen("wallet-connection-pending")
1423
- break
1424
- case "wallet-connection-pending-retry":
1425
- setSelectedWalletId("metamask")
1426
- setShowWalletConnectionRetry(true)
1427
- setCurrentScreen("wallet-connection-pending")
1428
- break
1429
- case "fund-methods":
1430
- setCurrentScreen("fund-methods")
1431
- break
1432
- case "earn-pools":
1433
- setCurrentScreen("earn-pools")
1434
- break
1435
- case "swap":
1436
- setSelectedToken(null)
1437
- setTransactionStates([])
1438
- setCurrentScreen("swap")
1439
- break
1440
- }
1441
- }
1442
-
1443
1120
  const handleSelectWalletConnect = () => {
1444
1121
  // Store the current connector as previous before switching to WalletConnect
1445
1122
  if (connector && connector.name !== "WalletConnect") {
@@ -1788,7 +1465,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
1788
1465
  onAmountUpdate={(amount: string) => {
1789
1466
  if (
1790
1467
  selectedPool &&
1791
- mode === "earn" &&
1468
+ currentMode === "earn" &&
1792
1469
  amount &&
1793
1470
  amount !== ""
1794
1471
  ) {
@@ -1807,7 +1484,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
1807
1484
  setGeneratedCalldata(undefined)
1808
1485
  }
1809
1486
  }}
1810
- mode={mode}
1487
+ mode={currentMode}
1811
1488
  selectedPool={selectedPool}
1812
1489
  checkoutOnHandlers={checkoutOnHandlers}
1813
1490
  />
@@ -1865,6 +1542,8 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
1865
1542
  onElapsedTime={handleElapsedTime}
1866
1543
  transactionStates={transactionStates}
1867
1544
  quote={prepareSendQuote}
1545
+ mode={currentMode}
1546
+ onContinue={() => setCurrentScreen("receipt")}
1868
1547
  />
1869
1548
  )
1870
1549
  case "receipt":
@@ -1962,14 +1641,28 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
1962
1641
  fundMethod={selectedFundMethod}
1963
1642
  onNavigateToMeshConnect={handleNavigateToMeshConnect}
1964
1643
  onAmountUpdate={undefined}
1965
- mode={mode}
1644
+ mode={currentMode}
1966
1645
  checkoutOnHandlers={checkoutOnHandlers}
1646
+ recentTokens={recentTokens}
1647
+ onRecentTokenSelect={handleRecentTokenSelect}
1648
+ onTrackToken={handleTrackToken}
1967
1649
  />
1968
1650
  ) : (
1969
1651
  <div className="text-center p-4 rounded-lg text-gray-600 bg-gray-50 dark:text-gray-300 dark:bg-gray-800">
1970
1652
  Please connect wallet
1971
1653
  </div>
1972
1654
  )
1655
+ case "receive":
1656
+ return (
1657
+ <Receive
1658
+ accountAddress={toAddress || ""}
1659
+ onBack={handleBack}
1660
+ isConnected={isConnected}
1661
+ onConnectWallet={() => setCurrentScreen("connect")}
1662
+ onPay={() => setCurrentScreen("tokens")}
1663
+ toChainId={toChainId ? Number(toChainId) : undefined}
1664
+ />
1665
+ )
1973
1666
  case "wallet-connection-pending":
1974
1667
  return (
1975
1668
  <WalletConnectionPending
@@ -2024,11 +1717,17 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2024
1717
  layout
2025
1718
  >
2026
1719
  {renderScreenContent()}
1720
+ {/* Error Display */}
2027
1721
  {error && (
2028
- <div className="border rounded-lg p-4 mt-4 bg-red-50 border-red-200 dark:bg-red-900/20 dark:border-red-800">
2029
- <p className="text-sm break-words text-red-600 dark:text-red-200">
2030
- {error}
2031
- </p>
1722
+ <div className="mt-2">
1723
+ <ErrorDisplay
1724
+ errorPrettified={getPrettifiedErrorMessage(
1725
+ error,
1726
+ "An error occured",
1727
+ )}
1728
+ error={error}
1729
+ severity="error"
1730
+ />
2032
1731
  </div>
2033
1732
  )}
2034
1733
  </motion.div>
@@ -2042,6 +1741,25 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2042
1741
  return renderScreen()
2043
1742
  }
2044
1743
 
1744
+ const defaultButtonText = useMemo(() => {
1745
+ if (currentMode === "fund") {
1746
+ return "Fund"
1747
+ }
1748
+ if (currentMode === "swap") {
1749
+ return "Swap"
1750
+ }
1751
+ if (currentMode === "earn") {
1752
+ return "Earn"
1753
+ }
1754
+ if (currentMode === "receive") {
1755
+ return "Receive"
1756
+ }
1757
+ if (currentMode === "pay") {
1758
+ return "Pay"
1759
+ }
1760
+ return "Pay"
1761
+ }, [currentMode])
1762
+
2045
1763
  return (
2046
1764
  <div className="flex flex-col items-center justify-center space-y-8 py-12">
2047
1765
  {!children ? (
@@ -2051,8 +1769,7 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2051
1769
  onClick={() => setIsModalOpen(true)}
2052
1770
  className="trails-modal-button cursor-pointer font-semibold py-3 px-6 trails-font"
2053
1771
  >
2054
- {buttonText ||
2055
- (mode === "fund" ? "Fund" : mode === "swap" ? "Swap" : "Pay")}
1772
+ {buttonText || defaultButtonText}
2056
1773
  </motion.button>
2057
1774
  ) : (
2058
1775
  <motion.div
@@ -2118,20 +1835,20 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2118
1835
  const chains = [...Object.values(viemChains)] as any
2119
1836
  const baseConfig = {
2120
1837
  chains,
2121
- transports: (chains as Array<Chain>).reduce(
2122
- (acc, chain) => ({
1838
+ transports: (chains as Array<Chain>).reduce((acc, chain) => {
1839
+ const sequenceRpcUrl = getRpcUrl(chain.id, props.appId)
1840
+ return {
2123
1841
  ...acc,
2124
- [chain.id]: http(),
2125
- }),
2126
- {},
2127
- ) as Record<number, ReturnType<typeof http>>,
1842
+ [chain.id]: sequenceRpcUrl ? http(sequenceRpcUrl) : http(),
1843
+ }
1844
+ }, {}) as Record<number, ReturnType<typeof http>>,
2128
1845
  }
2129
1846
 
2130
1847
  return createConfig({
2131
1848
  ...baseConfig,
2132
1849
  connectors: connectors,
2133
1850
  })
2134
- }, [])
1851
+ }, [props.appId])
2135
1852
 
2136
1853
  // Create content with only the providers that don't exist in parent
2137
1854
  const content = (() => {