0xtrails 0.2.5 → 0.3.0

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 (267) hide show
  1. package/dist/aave.d.ts +2 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/abortController.d.ts +8 -0
  4. package/dist/abortController.d.ts.map +1 -0
  5. package/dist/{ccip-CXlshvBY.js → ccip-BMB3uDZt.js} +1 -1
  6. package/dist/config.d.ts +0 -5
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/constants.d.ts +4 -4
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/error.d.ts +4 -1
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/fees.d.ts +19 -0
  13. package/dist/fees.d.ts.map +1 -0
  14. package/dist/{index-_QuyGrjU.js → index-QXPUrZVv.js} +48719 -50852
  15. package/dist/index.d.ts +9 -8
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +811 -784
  18. package/dist/intentReceiptMonitor.d.ts +24 -0
  19. package/dist/intentReceiptMonitor.d.ts.map +1 -0
  20. package/dist/intentReceiptPoller.d.ts +69 -0
  21. package/dist/intentReceiptPoller.d.ts.map +1 -0
  22. package/dist/intents.d.ts +15 -11
  23. package/dist/intents.d.ts.map +1 -1
  24. package/dist/morpho.d.ts +6 -5
  25. package/dist/morpho.d.ts.map +1 -1
  26. package/dist/mutations.d.ts +16 -0
  27. package/dist/mutations.d.ts.map +1 -0
  28. package/dist/preconditions.d.ts +5 -4
  29. package/dist/preconditions.d.ts.map +1 -1
  30. package/dist/prepareSend.d.ts +7 -258
  31. package/dist/prepareSend.d.ts.map +1 -1
  32. package/dist/prices.d.ts +9 -6
  33. package/dist/prices.d.ts.map +1 -1
  34. package/dist/sequenceWallet.d.ts +3 -16
  35. package/dist/sequenceWallet.d.ts.map +1 -1
  36. package/dist/tokenBalances.d.ts +17 -13
  37. package/dist/tokenBalances.d.ts.map +1 -1
  38. package/dist/trails.d.ts +24 -40
  39. package/dist/trails.d.ts.map +1 -1
  40. package/dist/transactionIntent/constants.d.ts +7 -0
  41. package/dist/transactionIntent/constants.d.ts.map +1 -0
  42. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +44 -0
  43. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -0
  44. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +30 -0
  45. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -0
  46. package/dist/transactionIntent/deposits/index.d.ts +4 -0
  47. package/dist/transactionIntent/deposits/index.d.ts.map +1 -0
  48. package/dist/transactionIntent/deposits/standardDeposit.d.ts +30 -0
  49. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -0
  50. package/dist/transactionIntent/execution/index.d.ts +2 -0
  51. package/dist/transactionIntent/execution/index.d.ts.map +1 -0
  52. package/dist/transactionIntent/execution/transactionState.d.ts +5 -0
  53. package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -0
  54. package/dist/transactionIntent/handlers/crossChain.d.ts +82 -0
  55. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -0
  56. package/dist/transactionIntent/handlers/index.d.ts +4 -0
  57. package/dist/transactionIntent/handlers/index.d.ts.map +1 -0
  58. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +62 -0
  59. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +1 -0
  60. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +72 -0
  61. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -0
  62. package/dist/transactionIntent/index.d.ts +9 -0
  63. package/dist/transactionIntent/index.d.ts.map +1 -0
  64. package/dist/transactionIntent/quote/feeExtractors.d.ts +17 -0
  65. package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -0
  66. package/dist/transactionIntent/quote/index.d.ts +4 -0
  67. package/dist/transactionIntent/quote/index.d.ts.map +1 -0
  68. package/dist/transactionIntent/quote/normalizeQuote.d.ts +34 -0
  69. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -0
  70. package/dist/transactionIntent/quote/quoteHelpers.d.ts +5 -0
  71. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -0
  72. package/dist/transactionIntent/types.d.ts +131 -0
  73. package/dist/transactionIntent/types.d.ts.map +1 -0
  74. package/dist/transactionIntent/utils/balanceChecker.d.ts +18 -0
  75. package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -0
  76. package/dist/transactionIntent/utils/index.d.ts +4 -0
  77. package/dist/transactionIntent/utils/index.d.ts.map +1 -0
  78. package/dist/transactionIntent/utils/lifiHelpers.d.ts +10 -0
  79. package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +1 -0
  80. package/dist/transactionIntent/utils/testnetHelpers.d.ts +3 -0
  81. package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -0
  82. package/dist/transactionIntent/validators.d.ts +6 -0
  83. package/dist/transactionIntent/validators.d.ts.map +1 -0
  84. package/dist/transactions.d.ts +6 -3
  85. package/dist/transactions.d.ts.map +1 -1
  86. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
  87. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
  88. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  89. package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
  90. package/dist/widget/components/ClassicSwap.d.ts +2 -3
  91. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  92. package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
  93. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  94. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  95. package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
  96. package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
  97. package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
  98. package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
  99. package/dist/widget/components/Earn.d.ts +2 -3
  100. package/dist/widget/components/Earn.d.ts.map +1 -1
  101. package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
  102. package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
  103. package/dist/widget/components/FeeBreakdown.d.ts +9 -0
  104. package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
  105. package/dist/widget/components/FeeOptions.d.ts +5 -13
  106. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  107. package/dist/widget/components/Fund.d.ts +2 -3
  108. package/dist/widget/components/Fund.d.ts.map +1 -1
  109. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  110. package/dist/widget/components/FundSwap.d.ts +2 -3
  111. package/dist/widget/components/FundSwap.d.ts.map +1 -1
  112. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
  113. package/dist/widget/components/Identicon.d.ts.map +1 -1
  114. package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
  115. package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
  116. package/dist/widget/components/Modal.d.ts.map +1 -1
  117. package/dist/widget/components/Pay.d.ts +2 -3
  118. package/dist/widget/components/Pay.d.ts.map +1 -1
  119. package/dist/widget/components/PoolDeposit.d.ts +3 -3
  120. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  121. package/dist/widget/components/PoolWithdraw.d.ts +3 -20
  122. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
  123. package/dist/widget/components/QuoteDetails.d.ts +2 -0
  124. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  125. package/dist/widget/components/Receipt.d.ts.map +1 -1
  126. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
  127. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  128. package/dist/widget/components/Swap.d.ts +2 -3
  129. package/dist/widget/components/Swap.d.ts.map +1 -1
  130. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  131. package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
  132. package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
  133. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  134. package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
  135. package/dist/widget/components/Tooltip.d.ts +9 -0
  136. package/dist/widget/components/Tooltip.d.ts.map +1 -0
  137. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  138. package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
  139. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
  140. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  141. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  142. package/dist/widget/css/compiled.css +2 -2
  143. package/dist/widget/hooks/useCheckout.d.ts +17 -4
  144. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  145. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  146. package/dist/widget/hooks/useQuote.d.ts +82 -0
  147. package/dist/widget/hooks/useQuote.d.ts.map +1 -0
  148. package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
  149. package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
  150. package/dist/widget/hooks/useSendForm.d.ts +5 -6
  151. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  152. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  153. package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
  154. package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
  155. package/dist/widget/index.js +2 -2
  156. package/dist/widget/widget.d.ts +17 -7
  157. package/dist/widget/widget.d.ts.map +1 -1
  158. package/package.json +19 -21
  159. package/src/aave.ts +54 -1
  160. package/src/abortController.ts +35 -0
  161. package/src/config.ts +57 -58
  162. package/src/constants.ts +11 -9
  163. package/src/error.ts +21 -3
  164. package/src/fees.ts +210 -0
  165. package/src/index.ts +35 -13
  166. package/src/intentReceiptMonitor.ts +102 -0
  167. package/src/intentReceiptPoller.ts +299 -0
  168. package/src/intents.ts +205 -171
  169. package/src/morpho.ts +58 -9
  170. package/src/mutations.ts +129 -0
  171. package/src/preconditions.ts +16 -21
  172. package/src/prepareSend.ts +92 -4699
  173. package/src/prices.ts +26 -22
  174. package/src/relaySdk.ts +2 -2
  175. package/src/sequenceWallet.ts +6 -73
  176. package/src/tokenBalances.ts +175 -69
  177. package/src/trails.ts +230 -722
  178. package/src/transactionIntent/constants.ts +11 -0
  179. package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
  180. package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
  181. package/src/transactionIntent/deposits/index.ts +3 -0
  182. package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
  183. package/src/transactionIntent/execution/index.ts +1 -0
  184. package/src/transactionIntent/execution/transactionState.ts +35 -0
  185. package/src/transactionIntent/handlers/crossChain.ts +1707 -0
  186. package/src/transactionIntent/handlers/index.ts +3 -0
  187. package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
  188. package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
  189. package/src/transactionIntent/index.ts +9 -0
  190. package/src/transactionIntent/quote/feeExtractors.ts +81 -0
  191. package/src/transactionIntent/quote/index.ts +3 -0
  192. package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
  193. package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
  194. package/src/transactionIntent/types.ts +157 -0
  195. package/src/transactionIntent/utils/balanceChecker.ts +96 -0
  196. package/src/transactionIntent/utils/index.ts +3 -0
  197. package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
  198. package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
  199. package/src/transactionIntent/validators.ts +57 -0
  200. package/src/transactions.ts +98 -71
  201. package/src/widget/compiled.css +2 -2
  202. package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
  203. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
  204. package/src/widget/components/AccountSettings.tsx +70 -41
  205. package/src/widget/components/ChainFilterDropdown.tsx +24 -3
  206. package/src/widget/components/ClassicSwap.tsx +44 -107
  207. package/src/widget/components/ConfigDisplay.tsx +0 -11
  208. package/src/widget/components/ConnectWallet.tsx +4 -1
  209. package/src/widget/components/ConnectedWallets.tsx +51 -25
  210. package/src/widget/components/DynamicInputStyles.tsx +76 -0
  211. package/src/widget/components/DynamicSizeInputField.tsx +109 -0
  212. package/src/widget/components/Earn.tsx +34 -45
  213. package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
  214. package/src/widget/components/FeeBreakdown.tsx +155 -0
  215. package/src/widget/components/FeeOption.tsx +2 -2
  216. package/src/widget/components/FeeOptions.tsx +151 -112
  217. package/src/widget/components/Fund.tsx +10 -29
  218. package/src/widget/components/FundMethods.tsx +4 -3
  219. package/src/widget/components/FundSwap.tsx +2 -3
  220. package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
  221. package/src/widget/components/Identicon.tsx +164 -95
  222. package/src/widget/components/MeshConnectExchanges.tsx +2 -15
  223. package/src/widget/components/Modal.tsx +0 -12
  224. package/src/widget/components/Pay.tsx +72 -75
  225. package/src/widget/components/PoolDeposit.tsx +221 -242
  226. package/src/widget/components/PoolWithdraw.tsx +347 -469
  227. package/src/widget/components/PriceImpactWarning.tsx +1 -1
  228. package/src/widget/components/QuoteDetails.tsx +906 -484
  229. package/src/widget/components/Receipt.tsx +16 -2
  230. package/src/widget/components/RecipientSelectorButton.tsx +7 -5
  231. package/src/widget/components/Recipients.tsx +1 -1
  232. package/src/widget/components/ScreenHeader.tsx +60 -36
  233. package/src/widget/components/Swap.tsx +2 -3
  234. package/src/widget/components/ThemeProvider.tsx +2 -1
  235. package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
  236. package/src/widget/components/TokenImage.tsx +1 -1
  237. package/src/widget/components/TokenSelector.tsx +62 -53
  238. package/src/widget/components/TokenSelectorButton.tsx +38 -15
  239. package/src/widget/components/Tooltip.tsx +51 -0
  240. package/src/widget/components/TransferPendingVertical.tsx +12 -8
  241. package/src/widget/components/WaasFeeOptions.tsx +139 -4
  242. package/src/widget/components/WalletConfirmation.tsx +23 -13
  243. package/src/widget/components/WalletConnect.tsx +93 -29
  244. package/src/widget/hooks/useAmountUsd.ts +9 -9
  245. package/src/widget/hooks/useCheckout.ts +97 -9
  246. package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
  247. package/src/widget/hooks/useQuote.ts +466 -0
  248. package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
  249. package/src/widget/hooks/useSendForm.ts +45 -51
  250. package/src/widget/hooks/useTokenList.ts +34 -26
  251. package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
  252. package/src/widget/widget.tsx +365 -390
  253. package/dist/apiClient.d.ts +0 -9
  254. package/dist/apiClient.d.ts.map +0 -1
  255. package/dist/intentEntrypoint.d.ts +0 -114
  256. package/dist/intentEntrypoint.d.ts.map +0 -1
  257. package/dist/metaTxnMonitor.d.ts +0 -15
  258. package/dist/metaTxnMonitor.d.ts.map +0 -1
  259. package/dist/metaTxns.d.ts +0 -11
  260. package/dist/metaTxns.d.ts.map +0 -1
  261. package/dist/relayer.d.ts +0 -43
  262. package/dist/relayer.d.ts.map +0 -1
  263. package/src/apiClient.ts +0 -35
  264. package/src/intentEntrypoint.ts +0 -203
  265. package/src/metaTxnMonitor.ts +0 -171
  266. package/src/metaTxns.ts +0 -45
  267. package/src/relayer.ts +0 -289
@@ -4,6 +4,7 @@ import { AaveClient, AaveProvider } from "@aave/react"
4
4
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
5
5
  import { AnimatePresence, motion } from "motion/react"
6
6
  import React, {
7
+ createContext,
7
8
  forwardRef,
8
9
  StrictMode,
9
10
  useCallback,
@@ -16,13 +17,7 @@ import React, {
16
17
  } from "react"
17
18
  import { createPortal } from "react-dom"
18
19
  import type { Chain, WalletClient } from "viem"
19
- import {
20
- createWalletClient,
21
- custom,
22
- encodeFunctionData,
23
- http,
24
- isAddress,
25
- } from "viem"
20
+ import { createWalletClient, custom, http, isAddress } from "viem"
26
21
  import type { Connector } from "wagmi"
27
22
  import {
28
23
  createConfig,
@@ -31,6 +26,7 @@ import {
31
26
  useConnect,
32
27
  useConnections,
33
28
  useDisconnect,
29
+ useSwitchAccount,
34
30
  WagmiContext,
35
31
  WagmiProvider,
36
32
  } from "wagmi"
@@ -45,15 +41,10 @@ import { getAllChains, getChainInfo, getRpcUrl } from "../chains.js"
45
41
  import {
46
42
  getCommitHash,
47
43
  getDebug,
48
- getSequenceApiUrl,
49
- getSequenceEnv,
50
44
  getSequenceIndexerUrl,
51
45
  getSequenceNodeGatewayUrl,
52
- getSequenceProjectAccessKey,
53
46
  getTrailsApiUrl,
54
47
  setDebug,
55
- setSequenceApiUrl,
56
- setSequenceEnv,
57
48
  setSequenceIndexerUrl,
58
49
  setSequenceNodeGatewayUrl,
59
50
  setSequenceProjectAccessKey,
@@ -67,7 +58,7 @@ import {
67
58
  getIsApiError,
68
59
  getIsBalanceTooLowError,
69
60
  getIsRateLimitedError,
70
- getIsWalletRejectedError,
61
+ getIsUserRejectionError,
71
62
  getPrettifiedErrorMessage,
72
63
  } from "../error.js"
73
64
  import { logger } from "../logger.js"
@@ -76,7 +67,7 @@ import type { Pool } from "../pools.js"
76
67
  import { usePools } from "../pools.js"
77
68
  import type { PrepareSendQuote } from "../prepareSend.js"
78
69
  import { isValidInteger, isValidNumeric } from "../prices.js"
79
- import type { MetaTxnReceipt, RelayerEnv } from "../relayer.js"
70
+ import type { MetaTxnReceipt } from "../transactionIntent/types.js"
80
71
  import type { Theme } from "../theme.js"
81
72
  import type { SupportedToken } from "../tokens.js"
82
73
  import { getWethAddress } from "../tokens.js"
@@ -124,6 +115,10 @@ import {
124
115
  useCurrentScreen,
125
116
  type Screen,
126
117
  } from "./hooks/useCurrentScreen.js"
118
+ import {
119
+ WalletConnectionProvider,
120
+ useWalletConnectionContext,
121
+ } from "./hooks/useWalletConnectionContext.js"
127
122
  import { useDebugScreens } from "./hooks/useDebugScreens.js"
128
123
  import { DefaultTokenSelectionProvider } from "./hooks/useDefaultTokenSelection.js"
129
124
  import { DestinationSelectedTokenProvider } from "./hooks/useDestinationSelectedToken.js"
@@ -142,7 +137,10 @@ import {
142
137
  SelectedMeshExchangeProvider,
143
138
  useSelectedMeshExchange,
144
139
  } from "./hooks/useSelectedMeshExchange.js"
145
- import { SelectedRecipientProvider } from "./hooks/useSelectedRecipient.js"
140
+ import {
141
+ SelectedRecipientProvider,
142
+ useSelectedRecipient,
143
+ } from "./hooks/useSelectedRecipient.js"
146
144
  import type { OnCompleteProps } from "./hooks/useSendForm.js"
147
145
  import { SwapAmountProvider } from "./hooks/useSwapAmount.js"
148
146
  import { useTargetAmount } from "./hooks/useTargetAmount.js"
@@ -152,9 +150,44 @@ import {
152
150
  SelectedFundMethodProvider,
153
151
  useSelectedFundMethod,
154
152
  } from "./hooks/useSelectedFundMethod.js"
153
+ import { DEFAULT_MODE } from "../constants.js"
154
+ import { generateMorphoDepositCalldata } from "../morpho.js"
155
+ import { generateAaveDepositCalldata } from "../aave.js"
155
156
 
156
157
  export const aaveClient = AaveClient.create()
157
158
 
159
+ // Modal Context
160
+ interface ModalContextType {
161
+ closeModal: () => void
162
+ isModalOpen: boolean
163
+ }
164
+
165
+ const ModalContext = createContext<ModalContextType | null>(null)
166
+
167
+ // Modal Provider Component
168
+ const ModalProvider: React.FC<{
169
+ children: React.ReactNode
170
+ closeModal: () => void
171
+ isModalOpen: boolean
172
+ }> = ({ children, closeModal, isModalOpen }) => (
173
+ <ModalContext.Provider value={{ closeModal, isModalOpen }}>
174
+ {children}
175
+ </ModalContext.Provider>
176
+ )
177
+
178
+ // useModal Hook
179
+ export const useModal = (): ModalContextType => {
180
+ const context = useContext(ModalContext)
181
+ if (!context) {
182
+ // Return a no-op function when not in modal context (e.g., renderInline)
183
+ return {
184
+ closeModal: () => {},
185
+ isModalOpen: false,
186
+ }
187
+ }
188
+ return context
189
+ }
190
+
158
191
  // Validate toToken - must be "ETH", "USDC", or a valid hex address
159
192
  const isValidToToToken = (toToken: string | null | undefined) => {
160
193
  if (toToken === null || toToken === undefined || toToken === "") {
@@ -169,13 +202,10 @@ const isValidToToToken = (toToken: string | null | undefined) => {
169
202
  }
170
203
 
171
204
  export type TrailsWidgetProps = {
172
- appId?: string
173
- projectAccessKey?: string
205
+ apiKey: string
174
206
  sequenceIndexerUrl?: string | null
175
- sequenceApiUrl?: string | null
176
207
  trailsApiUrl?: string | null
177
208
  sequenceNodeGatewayUrl?: string | null
178
- sequenceEnv?: RelayerEnv
179
209
  toAddress?: string | null
180
210
  toAmount?: string | null
181
211
  toChainId?: number | string | null
@@ -198,8 +228,14 @@ export type TrailsWidgetProps = {
198
228
  }) => void
199
229
  onCheckoutStart?: (data: { sessionId: string }) => void
200
230
  onCheckoutQuote?: (data: { sessionId: string; quote: any }) => void
231
+ onCheckoutSignatureRequest?: (data: { sessionId: string }) => void
232
+ onCheckoutSignatureConfirmed?: (data: { sessionId: string }) => void
233
+ onCheckoutSignatureRejected?: (data: {
234
+ sessionId: string
235
+ error: unknown
236
+ }) => void
201
237
  onCheckoutComplete?: (data: { sessionId: string }) => void
202
- onCheckoutError?: (data: { sessionId: string; error: string }) => void
238
+ onCheckoutError?: (data: { sessionId: string; error: unknown }) => void
203
239
  onCheckoutStatusUpdate?: (data: {
204
240
  sessionId: string
205
241
  transactionStates: TransactionState[]
@@ -209,7 +245,6 @@ export type TrailsWidgetProps = {
209
245
 
210
246
  walletConnectProjectId?: string
211
247
  paymasterUrls?: Array<{ chainId: number; url: string }>
212
- gasless?: boolean
213
248
  buttonText?: string
214
249
  customCss?: string | Record<string, string>
215
250
  disableCss?: boolean
@@ -252,7 +287,11 @@ const useWalletManager = (
252
287
  if (!connector) {
253
288
  return
254
289
  }
255
- const activeProvider = await connector.getProvider?.()
290
+ if (typeof connector?.getProvider !== "function") {
291
+ return
292
+ }
293
+
294
+ const activeProvider = await connector.getProvider()
256
295
 
257
296
  if (activeProvider && address && chainId) {
258
297
  const chain = getChainInfo(chainId)
@@ -428,18 +467,20 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
428
467
  toCalldata,
429
468
  children,
430
469
  renderInline = false,
431
- mode = "pay",
470
+ mode = DEFAULT_MODE,
432
471
  onOriginConfirmation,
433
472
  onDestinationConfirmation,
434
473
  onCheckoutStart,
435
474
  onCheckoutQuote,
475
+ onCheckoutSignatureRequest,
476
+ onCheckoutSignatureConfirmed,
477
+ onCheckoutSignatureRejected,
436
478
  onCheckoutComplete,
437
479
  onCheckoutError,
438
480
  onCheckoutStatusUpdate,
439
481
  onOpen,
440
482
  onClose,
441
483
  paymasterUrls,
442
- gasless,
443
484
  buttonText,
444
485
  quoteProvider,
445
486
  priceImpactWarningThresholdBps,
@@ -448,7 +489,7 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
448
489
  decoupleWagmi,
449
490
  hideDisconnect,
450
491
  } = useWidgetProps()
451
- const { address, isConnected, chainId, connector } = useAccount()
492
+ const { address, chainId, connector } = useAccount()
452
493
  // const { setOpenConnectModal } = useOpenConnectModal()
453
494
 
454
495
  // Helper function to detect if the current connector is a Sequence wallet
@@ -470,6 +511,10 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
470
511
  }, [connector])
471
512
  const connections = useConnections()
472
513
  const { disconnectAsync } = useDisconnect()
514
+ const { switchAccount } = useSwitchAccount()
515
+
516
+ // Check if there are any connected accounts across all connectors
517
+ const isConnected = connections.length > 0
473
518
  const { recentTokens, addRecentToken } = useRecentTokens(address)
474
519
  const { wallets: allWallets } = useWallets()
475
520
  const { selectedToken, setSelectedToken } = useSelectedToken()
@@ -477,13 +522,11 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
477
522
  const [isModalOpen, setIsModalOpen] = useState(false)
478
523
  const [currentMode, setCurrentMode] = useState<Mode>(mode)
479
524
  const { currentScreen, setCurrentScreen } = useCurrentScreen()
480
- const {
481
- goBack,
482
- clearHistory,
483
- isNavigatingBack,
484
- setCurrentScreenWithBack,
485
- getPreviousScreen,
486
- } = useBack()
525
+ const { goBack, clearHistory, setCurrentScreenWithBack, getPreviousScreen } =
526
+ useBack()
527
+ const { connectionContext, clearConnectionContext, isRecipientSelection } =
528
+ useWalletConnectionContext()
529
+ const { setSelectedRecipient } = useSelectedRecipient()
487
530
 
488
531
  // Wrapper function that clears errors when going back
489
532
  const handleBack = () => {
@@ -532,7 +575,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
532
575
  number | null
533
576
  >(null)
534
577
  const { connectAsync } = useConnect()
535
- const [isInitialScreenSet, setIsInitialScreenSet] = useState(false)
536
578
 
537
579
  const getInitialScreenForMode = useCallback((mode: Mode) => {
538
580
  if (mode === "swap") {
@@ -546,7 +588,7 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
546
588
  } else if (mode === "pay") {
547
589
  return "send-form"
548
590
  } else {
549
- return "account-settings"
591
+ return "send-form"
550
592
  }
551
593
  }, [])
552
594
 
@@ -556,55 +598,27 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
556
598
 
557
599
  // If connected, navigate to the appropriate screen for the new mode
558
600
  if (isConnected) {
559
- const newScreen = getInitialScreenForMode(mode)
560
- setCurrentScreen(newScreen)
601
+ setCurrentScreen("home")
561
602
  }
562
- }, [mode, isConnected, setCurrentScreen, getInitialScreenForMode])
603
+ }, [mode, isConnected, setCurrentScreen])
563
604
 
564
- // Use the simple initial redirect hook
565
- const { hasConnectedBefore } = useInitialRedirect(
566
- isConnected,
567
- currentMode,
568
- getInitialScreenForMode,
569
- )
605
+ const goHome = useCallback(() => {
606
+ const initialScreen = getInitialScreenForMode(currentMode)
607
+ setCurrentScreen(initialScreen)
608
+ }, [currentMode, setCurrentScreen, getInitialScreenForMode])
570
609
 
571
- // Set proper initial screen based on connection state and mode
572
610
  useEffect(() => {
573
- if (isInitialScreenSet) {
574
- return
575
- }
576
-
577
- let properInitialScreen: Screen = "connect"
578
-
579
- if (isConnected) {
580
- // For initial load, always go to the appropriate mode screen
581
- properInitialScreen = getInitialScreenForMode(currentMode)
582
- logger.console.log(
583
- "[trails-sdk] Initial load with connected wallet, going to mode screen:",
584
- properInitialScreen,
585
- )
586
- } else if (currentMode === "receive") {
587
- properInitialScreen = "receive"
588
- }
589
-
590
- // Only update if the current screen is still the default
591
- if (currentScreen === "connect" || currentScreen === "receive") {
592
- logger.console.log(
593
- "[trails-sdk] setting currentScreen to",
594
- properInitialScreen,
595
- )
596
- setCurrentScreen(properInitialScreen)
611
+ if (currentScreen === "home") {
612
+ goHome()
597
613
  }
614
+ }, [currentScreen, goHome])
598
615
 
599
- setIsInitialScreenSet(true)
600
- }, [
616
+ // Use the simple initial redirect hook
617
+ const { hasConnectedBefore } = useInitialRedirect(
601
618
  isConnected,
602
619
  currentMode,
603
- currentScreen,
604
- setCurrentScreen,
605
- isInitialScreenSet,
606
620
  getInitialScreenForMode,
607
- ])
621
+ )
608
622
 
609
623
  const defaultButtonText = useMemo(() => {
610
624
  if (currentMode === "fund") {
@@ -632,11 +646,27 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
632
646
  const isValidToToken = isValidToToToken(toToken)
633
647
  const isValidToAddress = toAddress ? isAddress(toAddress) : true
634
648
 
649
+ // Validate paymasterUrls - each url must be a valid URL
650
+ let isValidPaymasterUrls = true
651
+ let invalidPaymasterUrl = ""
652
+ if (paymasterUrls && Array.isArray(paymasterUrls)) {
653
+ for (const paymaster of paymasterUrls) {
654
+ try {
655
+ new URL(paymaster.url)
656
+ } catch {
657
+ isValidPaymasterUrls = false
658
+ invalidPaymasterUrl = paymaster.url
659
+ break
660
+ }
661
+ }
662
+ }
663
+
635
664
  if (
636
665
  isValidToAmount &&
637
666
  isValidToChainId &&
638
667
  isValidToToken &&
639
- isValidToAddress
668
+ isValidToAddress &&
669
+ isValidPaymasterUrls
640
670
  ) {
641
671
  setError(null)
642
672
  return
@@ -680,6 +710,17 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
680
710
  toAddress,
681
711
  )
682
712
  setError("Invalid toAddress: must be a valid hex address")
713
+ return
714
+ }
715
+
716
+ // Validate paymasterUrls
717
+ if (!isValidPaymasterUrls) {
718
+ logger.console.error(
719
+ "[trails-sdk] Invalid paymasterUrls prop: url must be a valid URL. Received:",
720
+ invalidPaymasterUrl,
721
+ )
722
+ setError("Invalid paymasterUrls: url must be a valid URL")
723
+ return
683
724
  }
684
725
 
685
726
  if (currentMode === "fund") {
@@ -706,7 +747,7 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
706
747
  return
707
748
  }
708
749
  }
709
- }, [toAmount, toChainId, toToken, currentMode, toAddress])
750
+ }, [toAmount, toChainId, toToken, currentMode, toAddress, paymasterUrls])
710
751
 
711
752
  const walletClient = useWalletManager(address, chainId, connector)
712
753
 
@@ -836,6 +877,9 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
836
877
  const { checkoutOnHandlers } = useCheckout({
837
878
  onCheckoutStart,
838
879
  onCheckoutQuote,
880
+ onCheckoutSignatureRequest,
881
+ onCheckoutSignatureConfirmed,
882
+ onCheckoutSignatureRejected,
839
883
  onCheckoutComplete,
840
884
  onCheckoutError,
841
885
  onCheckoutStatusUpdate,
@@ -857,28 +901,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
857
901
  isConnected,
858
902
  })
859
903
 
860
- // Simple post-connection navigation - let the hook handle the logic
861
- useEffect(() => {
862
- if (isNavigatingBack) {
863
- return
864
- }
865
-
866
- // Handle disconnection
867
- if (!isConnected) {
868
- if (
869
- currentScreen !== "connect" &&
870
- currentScreen !== "wallet-connect" &&
871
- currentScreen !== "wallet-list" &&
872
- currentScreen !== "wallet-connection-pending" &&
873
- currentScreen !== "receive"
874
- ) {
875
- setTimeout(() => {
876
- setCurrentScreen("connect")
877
- }, 0)
878
- }
879
- }
880
- }, [isConnected, currentScreen, isNavigatingBack, setCurrentScreen])
881
-
882
904
  // Auto-detect mode changes and switch screens accordingly
883
905
  useEffect(() => {
884
906
  if (
@@ -1003,35 +1025,83 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1003
1025
  }
1004
1026
 
1005
1027
  if (config.connector !== walletConnectConnector) {
1028
+ // Store the current active connector BEFORE connecting new wallet
1029
+ const originalConnector = connector
1030
+
1006
1031
  logger.console.log(
1007
1032
  "[trails-sdk] Initiating connection to walletId",
1008
1033
  walletId,
1009
1034
  )
1010
- await connectAsync({ connector: config.connector })
1035
+ const result = await connectAsync({ connector: config.connector })
1011
1036
  logger.console.log(
1012
1037
  `[trails-sdk] Successfully connected to ${config.name}`,
1038
+ result,
1013
1039
  )
1014
1040
  // Set the last clicked wallet after successful connection
1015
1041
  saveLastClickedWallet(walletId)
1016
1042
 
1017
- // Check if this is the first wallet connection
1018
- if (!hasConnectedBefore) {
1019
- // First connection - go to initial screen for the mode
1020
- const initialScreen = getInitialScreenForMode(currentMode)
1043
+ // Check the wallet connection context to determine behavior
1044
+ if (isRecipientSelection) {
1045
+ // User connected wallet for recipient selection - switch back to original wallet
1021
1046
  logger.console.log(
1022
- "[trails-sdk] First wallet connection, going to initial screen:",
1023
- initialScreen,
1047
+ "[trails-sdk] Connected wallet for recipient selection, setting as recipient:",
1048
+ result.accounts[0],
1024
1049
  )
1025
- setCurrentScreen(initialScreen)
1050
+
1051
+ // Set the newly connected wallet as the recipient
1052
+ if (result.accounts[0]) {
1053
+ setSelectedRecipient(result.accounts[0])
1054
+ }
1055
+
1056
+ // Switch back to the original active wallet (if there was one)
1057
+ if (originalConnector && address) {
1058
+ try {
1059
+ logger.console.log(
1060
+ "[trails-sdk] Switching back to original active wallet:",
1061
+ address,
1062
+ )
1063
+ await switchAccount({ connector: originalConnector })
1064
+ } catch (switchError) {
1065
+ logger.console.error(
1066
+ "[trails-sdk] Failed to switch back to original wallet:",
1067
+ switchError,
1068
+ )
1069
+ }
1070
+ }
1071
+
1072
+ // Clear the connection context
1073
+ clearConnectionContext()
1074
+
1075
+ // Navigate back to the origin screen (recipients)
1076
+ const originScreen = connectionContext.originScreen
1077
+ if (originScreen) {
1078
+ setCurrentScreen(originScreen)
1079
+ } else {
1080
+ setCurrentScreen("recipients")
1081
+ }
1026
1082
  } else {
1027
- // Subsequent connection - go to account-settings
1083
+ // Normal connection - switch active wallet and navigate home
1028
1084
  logger.console.log(
1029
- "[trails-sdk] Subsequent wallet connection, going to account-settings",
1030
- )
1031
- setCurrentScreenWithBack(
1032
- "account-settings",
1033
- getInitialScreenForMode(currentMode),
1085
+ "[trails-sdk] Normal wallet connection, switching active wallet",
1034
1086
  )
1087
+
1088
+ // Clear the connection context
1089
+ clearConnectionContext()
1090
+
1091
+ // Check if this is the first wallet connection
1092
+ if (!hasConnectedBefore) {
1093
+ // First connection - go to initial screen for the mode
1094
+ logger.console.log(
1095
+ "[trails-sdk] First wallet connection, going home",
1096
+ )
1097
+ goHome()
1098
+ } else {
1099
+ // Subsequent connection - go to home which will route to the appropriate screen
1100
+ logger.console.log(
1101
+ "[trails-sdk] Subsequent wallet connection, going to home",
1102
+ )
1103
+ goHome()
1104
+ }
1035
1105
  }
1036
1106
  } else if (config.connector === walletConnectConnector) {
1037
1107
  // Store the current connector as previous before switching to WalletConnect
@@ -1094,19 +1164,62 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1094
1164
  }
1095
1165
  }
1096
1166
 
1097
- const handleContinue = () => {
1098
- if (currentMode === "swap") {
1099
- setCurrentScreen("swap")
1100
- } else if (currentMode === "receive") {
1101
- setCurrentScreen("receive")
1102
- } else if (currentMode === "earn") {
1103
- setCurrentScreen("earn")
1104
- } else if (currentMode === "fund") {
1105
- setCurrentScreen("fund-form")
1106
- } else if (currentMode === "pay") {
1107
- setCurrentScreen("send-form")
1167
+ const handleContinue = async () => {
1168
+ // Check if this was a recipient selection connection
1169
+ if (isRecipientSelection) {
1170
+ logger.console.log(
1171
+ "[trails-sdk] WalletConnect completed for recipient selection, setting as recipient:",
1172
+ address,
1173
+ )
1174
+
1175
+ // Set the newly connected wallet as the recipient
1176
+ if (address) {
1177
+ setSelectedRecipient(address)
1178
+ }
1179
+
1180
+ // Switch back to the original active wallet (if there was one)
1181
+ const originalConnector = connectionContext.originalActiveConnector
1182
+ const originalAddress = connectionContext.originalActiveWalletAddress
1183
+ if (originalConnector && originalAddress) {
1184
+ try {
1185
+ logger.console.log(
1186
+ "[trails-sdk] Switching back to original active wallet after WalletConnect:",
1187
+ originalAddress,
1188
+ )
1189
+ await switchAccount({ connector: originalConnector })
1190
+ } catch (switchError) {
1191
+ logger.console.error(
1192
+ "[trails-sdk] Failed to switch back to original wallet after WalletConnect:",
1193
+ switchError,
1194
+ )
1195
+ }
1196
+ }
1197
+
1198
+ // Clear the connection context
1199
+ clearConnectionContext()
1200
+
1201
+ // Navigate back to the origin screen (recipients)
1202
+ const originScreen = connectionContext.originScreen
1203
+ if (originScreen) {
1204
+ setCurrentScreen(originScreen)
1205
+ } else {
1206
+ setCurrentScreen("recipients")
1207
+ }
1108
1208
  } else {
1109
- setCurrentScreen("account-settings")
1209
+ // Normal flow - navigate based on mode
1210
+ if (currentMode === "swap") {
1211
+ setCurrentScreen("swap")
1212
+ } else if (currentMode === "receive") {
1213
+ setCurrentScreen("receive")
1214
+ } else if (currentMode === "earn") {
1215
+ setCurrentScreen("earn")
1216
+ } else if (currentMode === "fund") {
1217
+ setCurrentScreen("fund-form")
1218
+ } else if (currentMode === "pay") {
1219
+ setCurrentScreen("send-form")
1220
+ } else {
1221
+ setCurrentScreen("account-settings")
1222
+ }
1110
1223
  }
1111
1224
  }
1112
1225
 
@@ -1191,7 +1304,7 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1191
1304
  const resetState = useCallback(() => {
1192
1305
  setSelectedFundMethod("wallet")
1193
1306
  // Reset to appropriate screen based on mode
1194
- setCurrentScreen(currentMode === "receive" ? "receive" : "connect")
1307
+ setCurrentScreen("home")
1195
1308
  setSelectedToken(null)
1196
1309
  setSelectedPool(null)
1197
1310
  setSelectedWalletId(null)
@@ -1215,7 +1328,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1215
1328
  setOriginChainId,
1216
1329
  setSelectedToken,
1217
1330
  setSelectedPool,
1218
- currentMode,
1219
1331
  setCurrentScreen,
1220
1332
  clearHistory,
1221
1333
  ])
@@ -1269,7 +1381,8 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1269
1381
  ) {
1270
1382
  setDestinationTxHash(
1271
1383
  lastTransactionState?.transactionHash ||
1272
- (lastTransactionState as unknown as MetaTxnReceipt)?.txnHash,
1384
+ (lastTransactionState as unknown as MetaTxnReceipt)?.txnHash ||
1385
+ "",
1273
1386
  )
1274
1387
  setDestinationChainId(lastTransactionState?.chainId)
1275
1388
  }
@@ -1341,102 +1454,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1341
1454
  }
1342
1455
  }
1343
1456
 
1344
- // Generate deposit calldata for Aave pool
1345
- const generateAaveDepositCalldata = (pool: Pool, amount: string) => {
1346
- try {
1347
- const userAddress =
1348
- walletClient?.account?.address || walletClient?.account
1349
- if (!userAddress) {
1350
- throw new Error("User address not found")
1351
- }
1352
-
1353
- // Validate amount
1354
- if (
1355
- !amount ||
1356
- amount === "" ||
1357
- Number.isNaN(Number(amount)) ||
1358
- Number(amount) <= 0
1359
- ) {
1360
- throw new Error("Invalid amount")
1361
- }
1362
-
1363
- // Aave V3 Pool contract deposit function
1364
- // function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)
1365
- const calldata = encodeFunctionData({
1366
- abi: [
1367
- {
1368
- name: "supply",
1369
- type: "function",
1370
- inputs: [
1371
- { name: "asset", type: "address" },
1372
- { name: "amount", type: "uint256" },
1373
- { name: "onBehalfOf", type: "address" },
1374
- { name: "referralCode", type: "uint16" },
1375
- ],
1376
- outputs: [],
1377
- stateMutability: "nonpayable",
1378
- },
1379
- ],
1380
- args: [
1381
- pool.token.address as `0x${string}`, // asset address
1382
- BigInt(amount), // amount to deposit
1383
- userAddress as `0x${string}`, // onBehalfOf (user's address)
1384
- 0, // referralCode (0 for no referral)
1385
- ],
1386
- })
1387
- return calldata
1388
- } catch (error) {
1389
- logger.console.error("Error generating Aave deposit calldata:", error)
1390
- return undefined
1391
- }
1392
- }
1393
-
1394
- // Generate deposit calldata for Morpho pool
1395
- const generateMorphoDepositCalldata = (_pool: Pool, amount: string) => {
1396
- try {
1397
- const userAddress =
1398
- walletClient?.account?.address || walletClient?.account
1399
- if (!userAddress) {
1400
- throw new Error("User address not found")
1401
- }
1402
-
1403
- // Validate amount
1404
- if (
1405
- !amount ||
1406
- amount === "" ||
1407
- Number.isNaN(Number(amount)) ||
1408
- Number(amount) <= 0
1409
- ) {
1410
- throw new Error("Invalid amount")
1411
- }
1412
-
1413
- // Morpho Vault deposit function
1414
- // function deposit(uint256 amount, address receiver)
1415
- const calldata = encodeFunctionData({
1416
- abi: [
1417
- {
1418
- name: "deposit",
1419
- type: "function",
1420
- inputs: [
1421
- { name: "amount", type: "uint256" },
1422
- { name: "receiver", type: "address" },
1423
- ],
1424
- outputs: [{ name: "shares", type: "uint256" }],
1425
- stateMutability: "nonpayable",
1426
- },
1427
- ],
1428
- args: [
1429
- BigInt(amount), // amount to deposit
1430
- userAddress as `0x${string}`, // receiver (user's address)
1431
- ],
1432
- })
1433
- return calldata
1434
- } catch (error) {
1435
- logger.console.error("Error generating Morpho deposit calldata:", error)
1436
- return undefined
1437
- }
1438
- }
1439
-
1440
1457
  // Generate deposit calldata based on pool protocol
1441
1458
  const generateDepositCalldata = (pool: Pool, amount: string) => {
1442
1459
  try {
@@ -1445,11 +1462,15 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1445
1462
  pool.name,
1446
1463
  )
1447
1464
 
1465
+ if (!walletClient) {
1466
+ throw new Error("Wallet client not found")
1467
+ }
1468
+
1448
1469
  switch (pool.protocol.toLowerCase()) {
1449
1470
  case "aave":
1450
- return generateAaveDepositCalldata(pool, amount)
1471
+ return generateAaveDepositCalldata(walletClient, pool, amount)
1451
1472
  case "morpho":
1452
- return generateMorphoDepositCalldata(pool, amount)
1473
+ return generateMorphoDepositCalldata(walletClient, amount)
1453
1474
  default:
1454
1475
  logger.console.warn(`Unsupported protocol: ${pool.protocol}`)
1455
1476
  return undefined
@@ -1484,7 +1505,7 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1484
1505
  logger.console.error("[trails-sdk] Error sending transaction", error)
1485
1506
  }
1486
1507
  const errorMessage = getFullErrorMessage(error)
1487
- const isRejected = getIsWalletRejectedError(error)
1508
+ const isRejected = getIsUserRejectionError(error)
1488
1509
  const isBalanceTooLow = getIsBalanceTooLowError(error)
1489
1510
  const isApiError = getIsApiError(error)
1490
1511
  const isRateLimited = getIsRateLimitedError(error)
@@ -1583,17 +1604,16 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1583
1604
  case "fund-methods":
1584
1605
  return (
1585
1606
  <FundMethods
1586
- onBack={handleBack}
1607
+ onBack={() => goHome()}
1587
1608
  onSelectWalletConnect={handleSelectWalletConnect}
1588
1609
  onSelectExchangeList={handleSelectExchangeList}
1589
1610
  onSelectConnectedAccount={() => {
1590
1611
  setSelectedFundMethod("connected-account")
1591
- const initialScreen = getInitialScreenForMode(currentMode)
1592
- setCurrentScreen(initialScreen)
1612
+ setCurrentScreen("home")
1593
1613
  }}
1594
1614
  onSelectQrCode={() => {
1595
1615
  setSelectedFundMethod("qr-code")
1596
- setCurrentScreen(getInitialScreenForMode(currentMode))
1616
+ setCurrentScreen("home")
1597
1617
  }}
1598
1618
  />
1599
1619
  )
@@ -1613,14 +1633,14 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1613
1633
  />
1614
1634
  )
1615
1635
  case "send-form":
1616
- return walletClient?.account ? (
1636
+ return (
1617
1637
  <Pay
1618
1638
  selectedToken={selectedToken}
1619
1639
  onSend={handleOnSend}
1620
1640
  onWaitingForWalletConfirm={handleWaitingForWalletConfirm}
1621
1641
  onConfirm={() => setCurrentScreen("pending")}
1622
1642
  onComplete={handleTransferComplete}
1623
- account={walletClient.account}
1643
+ account={walletClient?.account}
1624
1644
  toRecipient={
1625
1645
  selectedPool
1626
1646
  ? selectedPool.depositAddress
@@ -1640,12 +1660,11 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1640
1660
  toCalldata={
1641
1661
  selectedPool ? generatedCalldata : toCalldata || undefined
1642
1662
  }
1643
- walletClient={walletClient}
1663
+ walletClient={walletClient ?? undefined}
1644
1664
  isSequenceWallet={isSequenceWallet}
1645
1665
  onTransactionStateChange={handleTransactionStateChange}
1646
1666
  onError={handleSendError}
1647
1667
  paymasterUrls={paymasterUrls}
1648
- gasless={gasless}
1649
1668
  setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
1650
1669
  quoteProvider={quoteProvider}
1651
1670
  fundMethod={selectedFundMethod}
@@ -1681,31 +1700,26 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1681
1700
  onRecentTokenSelect={handleRecentTokenSelect}
1682
1701
  onTrackToken={handleTrackToken}
1683
1702
  />
1684
- ) : (
1685
- <div className="text-center p-4 rounded-lg text-gray-600 bg-gray-50 dark:text-gray-300 dark:bg-gray-800">
1686
- Please connect wallet
1687
- </div>
1688
1703
  )
1689
1704
  case "fund-form":
1690
- return walletClient?.account ? (
1705
+ return (
1691
1706
  <Fund
1692
1707
  selectedToken={selectedToken}
1693
1708
  onSend={handleOnSend}
1694
1709
  onWaitingForWalletConfirm={handleWaitingForWalletConfirm}
1695
1710
  onConfirm={() => setCurrentScreen("pending")}
1696
1711
  onComplete={handleTransferComplete}
1697
- account={walletClient.account}
1712
+ account={walletClient?.account}
1698
1713
  toAmount={toAmount || undefined}
1699
1714
  toRecipient={toAddress || undefined}
1700
1715
  toChainId={toChainId ? Number(toChainId) : undefined}
1701
1716
  toToken={toToken || undefined}
1702
1717
  toCalldata={toCalldata || undefined}
1703
- walletClient={walletClient}
1718
+ walletClient={walletClient ?? undefined}
1704
1719
  isSequenceWallet={isSequenceWallet}
1705
1720
  onTransactionStateChange={handleTransactionStateChange}
1706
1721
  onError={handleSendError}
1707
1722
  paymasterUrls={paymasterUrls}
1708
- gasless={gasless}
1709
1723
  setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
1710
1724
  quoteProvider={quoteProvider}
1711
1725
  fundMethod={selectedFundMethod}
@@ -1715,10 +1729,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1715
1729
  onRecentTokenSelect={handleRecentTokenSelect}
1716
1730
  onTrackToken={handleTrackToken}
1717
1731
  />
1718
- ) : (
1719
- <div className="text-center p-4 rounded-lg text-gray-600 bg-gray-50 dark:text-gray-300 dark:bg-gray-800">
1720
- Please connect wallet
1721
- </div>
1722
1732
  )
1723
1733
  case "wallet-confirmation":
1724
1734
  return (
@@ -1821,11 +1831,11 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1821
1831
  />
1822
1832
  )
1823
1833
  case "earn":
1824
- return walletClient?.account ? (
1834
+ return (
1825
1835
  <Earn
1826
1836
  onContinue={() => setCurrentScreen("send-form")}
1827
- account={walletClient.account}
1828
- walletClient={walletClient}
1837
+ account={walletClient?.account}
1838
+ walletClient={walletClient ?? undefined}
1829
1839
  onTransactionStateChange={handleTransactionStateChange}
1830
1840
  onError={handleSendError}
1831
1841
  onWaitingForWalletConfirm={handleWaitingForWalletConfirm}
@@ -1833,7 +1843,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1833
1843
  onComplete={handleTransferComplete}
1834
1844
  onSend={handleOnSend}
1835
1845
  paymasterUrls={paymasterUrls}
1836
- gasless={gasless}
1837
1846
  setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
1838
1847
  quoteProvider={quoteProvider}
1839
1848
  fundMethod={selectedFundMethod}
@@ -1843,10 +1852,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1843
1852
  onRecentTokenSelect={handleRecentTokenSelect}
1844
1853
  onTrackToken={handleTrackToken}
1845
1854
  />
1846
- ) : (
1847
- <div className="text-center p-4 rounded-lg text-gray-600 bg-gray-50 dark:text-gray-300 dark:bg-gray-800">
1848
- Please connect wallet
1849
- </div>
1850
1855
  )
1851
1856
  case "earn-pools":
1852
1857
  return (
@@ -1860,25 +1865,24 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1860
1865
  />
1861
1866
  )
1862
1867
  case "swap":
1863
- return walletClient?.account ? (
1868
+ return (
1864
1869
  <Swap
1865
1870
  onSend={handleOnSend}
1866
1871
  onWaitingForWalletConfirm={handleWaitingForWalletConfirm}
1867
1872
  onConfirm={() => setCurrentScreen("pending")}
1868
1873
  onComplete={handleTransferComplete}
1869
1874
  selectedToken={selectedToken}
1870
- account={walletClient.account}
1875
+ account={walletClient?.account}
1871
1876
  toRecipient={toAddress || undefined}
1872
1877
  toAmount={toAmount || undefined}
1873
1878
  toChainId={toChainId ? Number(toChainId) : undefined}
1874
1879
  toToken={toToken || undefined}
1875
1880
  toCalldata={toCalldata || undefined}
1876
- walletClient={walletClient}
1881
+ walletClient={walletClient ?? undefined}
1877
1882
  isSequenceWallet={isSequenceWallet}
1878
1883
  onTransactionStateChange={handleTransactionStateChange}
1879
1884
  onError={handleSendError}
1880
1885
  paymasterUrls={paymasterUrls}
1881
- gasless={gasless}
1882
1886
  setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
1883
1887
  quoteProvider={quoteProvider}
1884
1888
  fundMethod={selectedFundMethod}
@@ -1889,10 +1893,6 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1889
1893
  onRecentTokenSelect={handleRecentTokenSelect}
1890
1894
  onTrackToken={handleTrackToken}
1891
1895
  />
1892
- ) : (
1893
- <div className="text-center p-4 rounded-lg text-gray-600 bg-gray-50 dark:text-gray-300 dark:bg-gray-800">
1894
- Please connect wallet
1895
- </div>
1896
1896
  )
1897
1897
  case "receive":
1898
1898
  return (
@@ -1928,6 +1928,10 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1928
1928
  />
1929
1929
  )
1930
1930
  case "account-settings":
1931
+ if (!isConnected) {
1932
+ setCurrentScreen("connect")
1933
+ return
1934
+ }
1931
1935
  return <AccountSettings onBack={handleBack} />
1932
1936
  case "user-preferences":
1933
1937
  return <UserPreferences onBack={handleBack} />
@@ -1943,16 +1947,9 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1943
1947
  />
1944
1948
  )
1945
1949
  case "mesh-connect-exchanges":
1946
- return (
1947
- <MeshConnectExchanges
1948
- onBack={handleBack}
1949
- getInitialScreenForMode={getInitialScreenForMode}
1950
- />
1951
- )
1950
+ return <MeshConnectExchanges onBack={handleBack} />
1952
1951
  case "home": {
1953
- // Redirect to the appropriate screen for the current mode
1954
- const homeScreen = getInitialScreenForMode(currentMode)
1955
- setCurrentScreen(homeScreen)
1952
+ // Navigation handled by useEffect above, otherwise it would cause a loop
1956
1953
  return null
1957
1954
  }
1958
1955
  default:
@@ -1962,68 +1959,70 @@ const WidgetContent = forwardRef<TrailsWidgetRef>((_, ref) => {
1962
1959
 
1963
1960
  const renderScreen = () => {
1964
1961
  return (
1965
- <ModeProvider
1966
- value={{
1967
- mode: currentMode,
1968
- }}
1969
- >
1970
- <PriceImpactWarningProvider
1962
+ <ModalProvider closeModal={handleCloseModal} isModalOpen={isModalOpen}>
1963
+ <ModeProvider
1971
1964
  value={{
1972
- thresholdBps: priceImpactWarningThresholdBps,
1973
- warningMessage: priceImpactWarningMessage,
1974
- fallbackBridgeUrl: priceImpactFallbackBridgeUrl,
1965
+ mode: currentMode,
1975
1966
  }}
1976
1967
  >
1977
- <motion.div
1978
- initial={{ opacity: 0, scale: 0.95 }}
1979
- animate={{ opacity: 1, scale: 1 }}
1980
- exit={{ opacity: 0, scale: 0.95 }}
1981
- transition={{
1982
- type: "spring",
1983
- stiffness: 200,
1984
- damping: 30,
1985
- mass: 1,
1968
+ <PriceImpactWarningProvider
1969
+ value={{
1970
+ thresholdBps: priceImpactWarningThresholdBps,
1971
+ warningMessage: priceImpactWarningMessage,
1972
+ fallbackBridgeUrl: priceImpactFallbackBridgeUrl,
1986
1973
  }}
1987
- className="flex flex-col min-h-[400px] shadow-xl p-4 sm:p-6 relative w-full sm:w-[400px] mx-auto custom-scrollbar trails-bg-primary trails-text-primary trails-font trails-border-radius-widget trails-widget-border"
1988
- layout
1989
- layoutId="modal-container"
1990
- onClick={(e) => e.stopPropagation()}
1991
1974
  >
1992
- <AnimatePresence mode="wait">
1993
- <motion.div
1994
- key={currentScreen}
1995
- initial={{ opacity: 0, x: 20 }}
1996
- animate={{ opacity: 1, x: 0 }}
1997
- exit={{ opacity: 0, x: -20 }}
1998
- transition={{
1999
- type: "spring",
2000
- stiffness: 500,
2001
- damping: 30,
2002
- mass: 0.6,
2003
- }}
2004
- className="flex-1 flex flex-col w-full"
2005
- layout
2006
- >
2007
- {renderScreenContent()}
2008
- {/* Error Display */}
2009
- {error && (
2010
- <div className="mt-2">
2011
- <ErrorDisplay
2012
- errorPrettified={getPrettifiedErrorMessage(
2013
- error,
2014
- "An error occured",
2015
- )}
2016
- error={error}
2017
- severity="error"
2018
- />
2019
- </div>
2020
- )}
2021
- </motion.div>
2022
- </AnimatePresence>
2023
- <Footer onDebugScreenSelect={handleDebugScreenSelect} />
2024
- </motion.div>
2025
- </PriceImpactWarningProvider>
2026
- </ModeProvider>
1975
+ <motion.div
1976
+ initial={{ opacity: 0, scale: 0.95 }}
1977
+ animate={{ opacity: 1, scale: 1 }}
1978
+ exit={{ opacity: 0, scale: 0.95 }}
1979
+ transition={{
1980
+ type: "spring",
1981
+ stiffness: 200,
1982
+ damping: 30,
1983
+ mass: 1,
1984
+ }}
1985
+ className="flex flex-col min-h-[400px] shadow-xl p-4 sm:p-6 relative w-full sm:w-[400px] mx-auto custom-scrollbar trails-bg-primary trails-text-primary trails-font trails-border-radius-widget trails-widget-border"
1986
+ layout
1987
+ layoutId="modal-container"
1988
+ onClick={(e) => e.stopPropagation()}
1989
+ >
1990
+ <AnimatePresence mode="wait">
1991
+ <motion.div
1992
+ key={currentScreen}
1993
+ initial={{ opacity: 0, x: 20 }}
1994
+ animate={{ opacity: 1, x: 0 }}
1995
+ exit={{ opacity: 0, x: -20 }}
1996
+ transition={{
1997
+ type: "spring",
1998
+ stiffness: 500,
1999
+ damping: 30,
2000
+ mass: 0.6,
2001
+ }}
2002
+ className="flex-1 flex flex-col w-full"
2003
+ layout
2004
+ >
2005
+ {renderScreenContent()}
2006
+ {/* Error Display */}
2007
+ {error && (
2008
+ <div className="mt-2">
2009
+ <ErrorDisplay
2010
+ errorPrettified={getPrettifiedErrorMessage(
2011
+ error,
2012
+ "An error occured",
2013
+ )}
2014
+ error={error}
2015
+ severity="error"
2016
+ />
2017
+ </div>
2018
+ )}
2019
+ </motion.div>
2020
+ </AnimatePresence>
2021
+ <Footer onDebugScreenSelect={handleDebugScreenSelect} />
2022
+ </motion.div>
2023
+ </PriceImpactWarningProvider>
2024
+ </ModeProvider>
2025
+ </ModalProvider>
2027
2026
  )
2028
2027
  }
2029
2028
 
@@ -2069,40 +2068,41 @@ const WidgetInner = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2069
2068
  // Calculate initial screen based on mode and connection state
2070
2069
  // Note: We can't use useAccount here as it needs to be inside WagmiProvider
2071
2070
  // So we'll use a default and let the WidgetContent handle the logic
2072
- const initialScreen: Screen =
2073
- props.mode === "receive" ? "receive" : "connect"
2071
+ const initialScreen: Screen = "home"
2074
2072
 
2075
2073
  return (
2076
2074
  <WidgetPropsProvider props={props}>
2077
2075
  <ToastProvider>
2078
2076
  <CurrentScreenProvider initialScreen={initialScreen}>
2079
2077
  <BackProvider>
2080
- <SelectedTokenProvider>
2081
- <DestinationSelectedTokenProvider>
2082
- <SelectedFeeTokenProvider>
2083
- <SelectedRecipientProvider>
2084
- <SwapAmountProvider>
2085
- <ChainFilterProvider>
2086
- <BalanceVisibleProvider>
2087
- <ThemePreferenceProvider>
2088
- <SelectedFundMethodProvider>
2089
- <ThemeSyncer />
2090
- <EarnPoolProvider>
2091
- <SelectedMeshExchangeProvider>
2092
- <DefaultTokenSelectionProvider>
2093
- <WidgetContent ref={ref} />
2094
- </DefaultTokenSelectionProvider>
2095
- </SelectedMeshExchangeProvider>
2096
- </EarnPoolProvider>
2097
- </SelectedFundMethodProvider>
2098
- </ThemePreferenceProvider>
2099
- </BalanceVisibleProvider>
2100
- </ChainFilterProvider>
2101
- </SwapAmountProvider>
2102
- </SelectedRecipientProvider>
2103
- </SelectedFeeTokenProvider>
2104
- </DestinationSelectedTokenProvider>
2105
- </SelectedTokenProvider>
2078
+ <WalletConnectionProvider>
2079
+ <SelectedTokenProvider>
2080
+ <DestinationSelectedTokenProvider>
2081
+ <SelectedFeeTokenProvider>
2082
+ <SelectedRecipientProvider>
2083
+ <SwapAmountProvider>
2084
+ <ChainFilterProvider>
2085
+ <BalanceVisibleProvider>
2086
+ <ThemePreferenceProvider>
2087
+ <SelectedFundMethodProvider>
2088
+ <ThemeSyncer />
2089
+ <EarnPoolProvider>
2090
+ <SelectedMeshExchangeProvider>
2091
+ <DefaultTokenSelectionProvider>
2092
+ <WidgetContent ref={ref} />
2093
+ </DefaultTokenSelectionProvider>
2094
+ </SelectedMeshExchangeProvider>
2095
+ </EarnPoolProvider>
2096
+ </SelectedFundMethodProvider>
2097
+ </ThemePreferenceProvider>
2098
+ </BalanceVisibleProvider>
2099
+ </ChainFilterProvider>
2100
+ </SwapAmountProvider>
2101
+ </SelectedRecipientProvider>
2102
+ </SelectedFeeTokenProvider>
2103
+ </DestinationSelectedTokenProvider>
2104
+ </SelectedTokenProvider>
2105
+ </WalletConnectionProvider>
2106
2106
  </BackProvider>
2107
2107
  </CurrentScreenProvider>
2108
2108
  </ToastProvider>
@@ -2116,28 +2116,16 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2116
2116
  const sequenceHooksContext = useContext(SequenceHooksContext)
2117
2117
  const wagmiContext = useContext(WagmiContext)
2118
2118
 
2119
- // Set global configuration immediately when component renders
2120
- // This ensures the config is available before sequenceConfig is created
2121
- if (props.appId) {
2122
- logger.console.warn("appId is deprecated. Use projectAccessKey instead.")
2123
- setSequenceProjectAccessKey(props.appId)
2124
- }
2125
- if (props.sequenceEnv && props.sequenceEnv !== getSequenceEnv()) {
2126
- logger.console.log("props.sequenceEnv", props.sequenceEnv)
2127
- setSequenceEnv(props.sequenceEnv)
2128
- }
2129
- if (props.projectAccessKey) {
2130
- logger.console.log("props.projectAccessKey", props.projectAccessKey)
2131
- setSequenceProjectAccessKey(props.projectAccessKey)
2119
+ if (props.apiKey) {
2120
+ logger.console.log("props.apiKey", props.apiKey)
2121
+ setSequenceProjectAccessKey(props.apiKey)
2122
+ } else {
2123
+ throw new Error("apiKey is required")
2132
2124
  }
2133
2125
  if (props.sequenceIndexerUrl) {
2134
2126
  logger.console.log("props.sequenceIndexerUrl", props.sequenceIndexerUrl)
2135
2127
  setSequenceIndexerUrl(props.sequenceIndexerUrl)
2136
2128
  }
2137
- if (props.sequenceApiUrl) {
2138
- logger.console.log("props.sequenceApiUrl", props.sequenceApiUrl)
2139
- setSequenceApiUrl(props.sequenceApiUrl)
2140
- }
2141
2129
  if (props.trailsApiUrl) {
2142
2130
  logger.console.log("props.trailsApiUrl", props.trailsApiUrl)
2143
2131
  setTrailsApiUrl(props.trailsApiUrl)
@@ -2160,7 +2148,7 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2160
2148
  logger.console.log("props.slippageTolerance", props.slippageTolerance)
2161
2149
  setSlippageTolerance(String(props.slippageTolerance))
2162
2150
  }
2163
- if (typeof props.debug === "boolean" && props.debug === getDebug()) {
2151
+ if (typeof props.debug === "boolean" && props.debug !== getDebug()) {
2164
2152
  logger.console.log("props.debug", props.debug)
2165
2153
  setDebug(props.debug)
2166
2154
  }
@@ -2170,10 +2158,7 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2170
2158
  const baseConfig = {
2171
2159
  chains,
2172
2160
  transports: (chains as Array<Chain>).reduce((acc, chain) => {
2173
- const sequenceRpcUrl = getRpcUrl(
2174
- chain.id,
2175
- props.projectAccessKey || props.appId,
2176
- )
2161
+ const sequenceRpcUrl = getRpcUrl(chain.id, props.apiKey)
2177
2162
  return {
2178
2163
  ...acc,
2179
2164
  [chain.id]: sequenceRpcUrl ? http(sequenceRpcUrl) : http(),
@@ -2196,12 +2181,7 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2196
2181
  : connectors,
2197
2182
  storage,
2198
2183
  })
2199
- }, [
2200
- props.projectAccessKey,
2201
- props.appId,
2202
- props.decoupleWagmi,
2203
- props.wagmiConnectors,
2204
- ])
2184
+ }, [props.apiKey, props.decoupleWagmi, props.wagmiConnectors])
2205
2185
 
2206
2186
  // Create content with only the providers that don't exist in parent
2207
2187
  const content = (() => {
@@ -2213,18 +2193,13 @@ export const TrailsWidget = forwardRef<TrailsWidgetRef, TrailsWidgetProps>(
2213
2193
 
2214
2194
  const sequenceConfig = {
2215
2195
  commitHash: getCommitHash(),
2216
- projectAccessKey:
2217
- props.projectAccessKey ||
2218
- props.appId ||
2219
- getSequenceProjectAccessKey(),
2196
+ projectAccessKey: props.apiKey,
2220
2197
  env: {
2221
- env: props.sequenceEnv || getSequenceEnv(),
2222
2198
  indexerUrl: props.sequenceIndexerUrl || getSequenceIndexerUrl(),
2223
2199
  indexerGatewayUrl:
2224
2200
  props.sequenceIndexerUrl || getSequenceIndexerUrl(),
2225
2201
  nodeGatewayUrl:
2226
2202
  props.sequenceNodeGatewayUrl || getSequenceNodeGatewayUrl(),
2227
- apiUrl: props.sequenceApiUrl || getSequenceApiUrl(),
2228
2203
  trailsApiUrl: props.trailsApiUrl || getTrailsApiUrl(),
2229
2204
  },
2230
2205
  }