0xtrails 0.12.0 → 0.12.2

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 (205) hide show
  1. package/dist/analytics.d.ts +65 -50
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/{ccip-DtfgR432.js → ccip-62W6LwH2.js} +28 -28
  4. package/dist/chains.d.ts.map +1 -1
  5. package/dist/error.d.ts +2 -0
  6. package/dist/error.d.ts.map +1 -1
  7. package/dist/estimate.d.ts.map +1 -1
  8. package/dist/fees.d.ts.map +1 -1
  9. package/dist/{index-CHiCSmCD.js → index-C0QTNYIA.js} +43750 -41806
  10. package/dist/index.d.ts +5 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +199 -171
  13. package/dist/localeUtils.d.ts.map +1 -1
  14. package/dist/meld/components/MeldCountriesList.d.ts +0 -2
  15. package/dist/meld/components/MeldCountriesList.d.ts.map +1 -1
  16. package/dist/meld/components/MeldFundMethods.d.ts.map +1 -1
  17. package/dist/meld/components/MeldTokensList.d.ts.map +1 -1
  18. package/dist/meld/utils/meld.d.ts +2 -52
  19. package/dist/meld/utils/meld.d.ts.map +1 -1
  20. package/dist/poolUtils.d.ts.map +1 -1
  21. package/dist/prepareSend.d.ts.map +1 -1
  22. package/dist/prices.d.ts +1 -2
  23. package/dist/prices.d.ts.map +1 -1
  24. package/dist/query/balance.fetchers.d.ts +2 -2
  25. package/dist/query/balance.fetchers.d.ts.map +1 -1
  26. package/dist/query/fiat.fetchers.d.ts +11 -0
  27. package/dist/query/fiat.fetchers.d.ts.map +1 -0
  28. package/dist/query/fiat.hooks.d.ts +18 -0
  29. package/dist/query/fiat.hooks.d.ts.map +1 -0
  30. package/dist/query/fiat.queries.d.ts +24 -0
  31. package/dist/query/fiat.queries.d.ts.map +1 -0
  32. package/dist/query/meld.fetchers.d.ts +19 -0
  33. package/dist/query/meld.fetchers.d.ts.map +1 -0
  34. package/dist/query/meld.hooks.d.ts +4 -0
  35. package/dist/query/meld.hooks.d.ts.map +1 -0
  36. package/dist/query/meld.queries.d.ts +61 -0
  37. package/dist/query/meld.queries.d.ts.map +1 -0
  38. package/dist/recover.d.ts.map +1 -1
  39. package/dist/tokens.d.ts.map +1 -1
  40. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  41. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
  42. package/dist/transactionIntent/deposits/standardDeposit.d.ts +7 -1
  43. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  44. package/dist/transactionIntent/handlers/intentHandler.d.ts +2 -0
  45. package/dist/transactionIntent/handlers/intentHandler.d.ts.map +1 -1
  46. package/dist/transactionIntent/quote/normalizeQuote.d.ts +2 -2
  47. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  48. package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
  49. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
  50. package/dist/transactionIntent/types.d.ts +2 -0
  51. package/dist/transactionIntent/types.d.ts.map +1 -1
  52. package/dist/transactionIntent/utils/balanceChecker.d.ts +3 -1
  53. package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -1
  54. package/dist/transactions.d.ts +2 -9
  55. package/dist/transactions.d.ts.map +1 -1
  56. package/dist/umd/trails.min.js +206 -152
  57. package/dist/utils/fiat.d.ts +8 -0
  58. package/dist/utils/fiat.d.ts.map +1 -0
  59. package/dist/utils/format.d.ts.map +1 -1
  60. package/dist/utils/passthrough.d.ts +5 -2
  61. package/dist/utils/passthrough.d.ts.map +1 -1
  62. package/dist/utils/validation.d.ts +33 -0
  63. package/dist/utils/validation.d.ts.map +1 -1
  64. package/dist/utils.d.ts.map +1 -1
  65. package/dist/walletUtils.d.ts +1 -1
  66. package/dist/walletUtils.d.ts.map +1 -1
  67. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  68. package/dist/widget/components/DepositTracker.d.ts.map +1 -1
  69. package/dist/widget/components/Earn.d.ts +2 -0
  70. package/dist/widget/components/Earn.d.ts.map +1 -1
  71. package/dist/widget/components/FeeOption.d.ts.map +1 -1
  72. package/dist/widget/components/Fund.d.ts.map +1 -1
  73. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  74. package/dist/widget/components/HookModalContent.d.ts.map +1 -1
  75. package/dist/widget/components/MeldForm.d.ts.map +1 -1
  76. package/dist/widget/components/MeldHistory.d.ts.map +1 -1
  77. package/dist/widget/components/MeldStepsFlow.d.ts.map +1 -1
  78. package/dist/widget/components/OFTProgressBar.d.ts +2 -0
  79. package/dist/widget/components/OFTProgressBar.d.ts.map +1 -1
  80. package/dist/widget/components/OnRampProviderSelector.d.ts.map +1 -1
  81. package/dist/widget/components/OnrampHistoryRow.d.ts.map +1 -1
  82. package/dist/widget/components/Pay.d.ts.map +1 -1
  83. package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -1
  84. package/dist/widget/components/PoolDeposit.d.ts +2 -0
  85. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  86. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  87. package/dist/widget/components/Receipt.d.ts.map +1 -1
  88. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  89. package/dist/widget/components/Swap.d.ts +2 -0
  90. package/dist/widget/components/Swap.d.ts.map +1 -1
  91. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  92. package/dist/widget/components/Withdraw.d.ts.map +1 -1
  93. package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -1
  94. package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -1
  95. package/dist/widget/hooks/useDisplayCurrencyPreference.d.ts.map +1 -1
  96. package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts +3 -21
  97. package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts.map +1 -1
  98. package/dist/widget/hooks/useMeldTransactionHistory.d.ts.map +1 -1
  99. package/dist/widget/hooks/useOnRampCountryDefaults.d.ts +0 -18
  100. package/dist/widget/hooks/useOnRampCountryDefaults.d.ts.map +1 -1
  101. package/dist/widget/hooks/useOnRampPaymentMethods.d.ts +2 -18
  102. package/dist/widget/hooks/useOnRampPaymentMethods.d.ts.map +1 -1
  103. package/dist/widget/hooks/useOnRampQuote.d.ts.map +1 -1
  104. package/dist/widget/hooks/useQuote.d.ts +5 -1
  105. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  106. package/dist/widget/hooks/useSendForm.d.ts +3 -1
  107. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  108. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  109. package/dist/widget/hooks/useTokenWithFreshBalance.d.ts +3 -2
  110. package/dist/widget/hooks/useTokenWithFreshBalance.d.ts.map +1 -1
  111. package/dist/widget/index.js +1 -1
  112. package/dist/widget/types/commonProps.d.ts +2 -0
  113. package/dist/widget/types/commonProps.d.ts.map +1 -1
  114. package/dist/widget/utils/transactionFailure.d.ts +20 -0
  115. package/dist/widget/utils/transactionFailure.d.ts.map +1 -0
  116. package/dist/widget/widget.d.ts +44 -3
  117. package/dist/widget/widget.d.ts.map +1 -1
  118. package/dist/widget/workers/intentExecutionWorker.d.ts.map +1 -1
  119. package/package.json +22 -22
  120. package/src/analytics.ts +115 -79
  121. package/src/chains.ts +0 -1
  122. package/src/error.ts +11 -0
  123. package/src/estimate.ts +12 -7
  124. package/src/fees.ts +0 -1
  125. package/src/index.ts +11 -0
  126. package/src/localeUtils.ts +3 -1
  127. package/src/meld/components/MeldCountriesList.tsx +30 -15
  128. package/src/meld/components/MeldFundMethods.tsx +8 -4
  129. package/src/meld/components/MeldTokensList.tsx +90 -2
  130. package/src/meld/utils/meld.ts +3 -400
  131. package/src/poolUtils.ts +5 -19
  132. package/src/prepareSend.ts +32 -5
  133. package/src/prices.ts +7 -33
  134. package/src/query/balance.fetchers.ts +128 -168
  135. package/src/query/fiat.fetchers.ts +33 -0
  136. package/src/query/fiat.hooks.ts +71 -0
  137. package/src/query/fiat.queries.ts +67 -0
  138. package/src/query/meld.fetchers.ts +97 -0
  139. package/src/query/meld.hooks.ts +18 -0
  140. package/src/query/meld.queries.ts +184 -0
  141. package/src/recover.ts +6 -1
  142. package/src/tokens.ts +31 -6
  143. package/src/transactionIntent/deposits/depositOrchestrator.ts +2 -0
  144. package/src/transactionIntent/deposits/gaslessDeposit.ts +9 -2
  145. package/src/transactionIntent/deposits/standardDeposit.ts +35 -14
  146. package/src/transactionIntent/handlers/intentHandler.ts +134 -138
  147. package/src/transactionIntent/quote/normalizeQuote.ts +31 -22
  148. package/src/transactionIntent/quote/quoteHelpers.ts +24 -7
  149. package/src/transactionIntent/types.ts +2 -0
  150. package/src/transactionIntent/utils/balanceChecker.ts +10 -4
  151. package/src/transactions.ts +22 -13
  152. package/src/umd.tsx +1 -1
  153. package/src/utils/fiat.ts +32 -0
  154. package/src/utils/format.ts +1 -3
  155. package/src/utils/passthrough.ts +19 -3
  156. package/src/utils/validation.ts +88 -0
  157. package/src/utils.ts +2 -1
  158. package/src/walletUtils.ts +2 -2
  159. package/src/widget/components/AccountIntentTransactionHistory.tsx +2 -2
  160. package/src/widget/components/ClassicSwap.tsx +10 -4
  161. package/src/widget/components/DepositTracker.tsx +2 -5
  162. package/src/widget/components/Earn.tsx +6 -0
  163. package/src/widget/components/FeeOption.tsx +15 -8
  164. package/src/widget/components/Fund.tsx +16 -11
  165. package/src/widget/components/FundMethods.tsx +255 -192
  166. package/src/widget/components/HookModalContent.tsx +4 -0
  167. package/src/widget/components/MeldForm.tsx +44 -42
  168. package/src/widget/components/MeldHistory.tsx +4 -3
  169. package/src/widget/components/MeldStepsFlow.tsx +33 -71
  170. package/src/widget/components/OFTProgressBar.tsx +32 -12
  171. package/src/widget/components/OnRampProviderSelector.tsx +2 -1
  172. package/src/widget/components/OnrampHistoryRow.tsx +2 -1
  173. package/src/widget/components/Pay.tsx +8 -2
  174. package/src/widget/components/PercentageMaxButtons.tsx +5 -3
  175. package/src/widget/components/PoolDeposit.tsx +6 -0
  176. package/src/widget/components/PoolWithdraw.tsx +1 -1
  177. package/src/widget/components/QuoteDetails.tsx +5 -4
  178. package/src/widget/components/Receipt.tsx +4 -3
  179. package/src/widget/components/SlippageToleranceSettings.tsx +3 -2
  180. package/src/widget/components/Swap.tsx +2 -0
  181. package/src/widget/components/TransferPendingVertical.tsx +21 -28
  182. package/src/widget/components/UserPreferences.tsx +1 -1
  183. package/src/widget/components/Withdraw.tsx +20 -14
  184. package/src/widget/hooks/useAmountUsd.ts +3 -15
  185. package/src/widget/hooks/useCustomTokenSearch.tsx +2 -6
  186. package/src/widget/hooks/useDisplayCurrencyPreference.tsx +1 -2
  187. package/src/widget/hooks/useFiatOnRampCurrencies.ts +11 -76
  188. package/src/widget/hooks/useMeldTransactionHistory.ts +24 -89
  189. package/src/widget/hooks/useOnRampCountryDefaults.ts +3 -49
  190. package/src/widget/hooks/useOnRampPaymentMethods.ts +21 -100
  191. package/src/widget/hooks/useOnRampQuote.ts +2 -5
  192. package/src/widget/hooks/useQuote.ts +10 -12
  193. package/src/widget/hooks/useSendForm.ts +6 -0
  194. package/src/widget/hooks/useTokenList.ts +3 -6
  195. package/src/widget/hooks/useTokenWithFreshBalance.ts +141 -11
  196. package/src/widget/types/commonProps.ts +2 -0
  197. package/src/widget/utils/transactionFailure.ts +52 -0
  198. package/src/widget/widget.tsx +137 -59
  199. package/src/widget/workers/intentExecutionWorker.ts +3 -1
  200. package/dist/widget/hooks/useExchangeRate.d.ts +0 -31
  201. package/dist/widget/hooks/useExchangeRate.d.ts.map +0 -1
  202. package/dist/widget/hooks/useFiatCurrencyList.d.ts +0 -3
  203. package/dist/widget/hooks/useFiatCurrencyList.d.ts.map +0 -1
  204. package/src/widget/hooks/useExchangeRate.ts +0 -257
  205. package/src/widget/hooks/useFiatCurrencyList.ts +0 -66
@@ -0,0 +1,71 @@
1
+ import { useQuery } from "@tanstack/react-query"
2
+ import { useTrailsClient } from "../trailsClient.js"
3
+ import { fiatQueries } from "./fiat.queries.js"
4
+
5
+ // ============================================================================
6
+ // Fiat Currency List
7
+ // ============================================================================
8
+
9
+ export function useFiatCurrencyList() {
10
+ const trailsClient = useTrailsClient()
11
+ return useQuery(fiatQueries.currencyList(trailsClient))
12
+ }
13
+
14
+ // ============================================================================
15
+ // Exchange Rate
16
+ // ============================================================================
17
+
18
+ interface UseExchangeRateOptions {
19
+ fromCurrency?: string
20
+ toCurrency?: string
21
+ disabled?: boolean
22
+ }
23
+
24
+ interface UseExchangeRateResult {
25
+ exchangeRate: number | undefined
26
+ isLoading: boolean
27
+ error: Error | null
28
+ }
29
+
30
+ /**
31
+ * Fetch the exchange rate between two currencies.
32
+ * Handles same-currency (returns 1) and direction inversion (X→USD = 1/rate).
33
+ */
34
+ export function useExchangeRate(
35
+ options: UseExchangeRateOptions = {},
36
+ ): UseExchangeRateResult {
37
+ const { fromCurrency = "USD", toCurrency = "USD", disabled = false } = options
38
+ const trailsClient = useTrailsClient()
39
+
40
+ const isSameCurrency = fromCurrency === toCurrency
41
+ const targetCurrency = fromCurrency === "USD" ? toCurrency : fromCurrency
42
+
43
+ // Pass null when disabled or same-currency → factory uses skipToken
44
+ const { data, isLoading, error } = useQuery(
45
+ fiatQueries.exchangeRate(
46
+ trailsClient,
47
+ disabled || isSameCurrency ? null : targetCurrency,
48
+ ),
49
+ )
50
+
51
+ // Calculate the exchange rate based on the conversion direction
52
+ let exchangeRate: number | undefined
53
+
54
+ if (isSameCurrency) {
55
+ exchangeRate = 1
56
+ } else if (data?.value) {
57
+ if (fromCurrency === "USD" && toCurrency !== "USD") {
58
+ // USD to another currency — use the rate directly
59
+ exchangeRate = data.value
60
+ } else if (fromCurrency !== "USD" && toCurrency === "USD") {
61
+ // Currency to USD — invert the rate
62
+ exchangeRate = 1 / data.value
63
+ }
64
+ }
65
+
66
+ return {
67
+ exchangeRate,
68
+ isLoading: isSameCurrency ? false : isLoading,
69
+ error: isSameCurrency ? null : (error as Error | null),
70
+ }
71
+ }
@@ -0,0 +1,67 @@
1
+ import { queryOptions, skipToken } from "@tanstack/react-query"
2
+ import type { ExchangeRate, FiatCurrency } from "@0xtrails/api"
3
+ import type { TrailsClient } from "../trailsClient.js"
4
+ import { DAY_MS, MINUTE_MS, HOUR_MS } from "../utils/time.js"
5
+ import { createRetry, retryDelay } from "./helpers.js"
6
+ import { queryPersister } from "./persister.js"
7
+ import { getFiatCurrencyList, getExchangeRate } from "./fiat.fetchers.js"
8
+
9
+ // ============================================================================
10
+ // Fiat Query Factory
11
+ //
12
+ // Single factory following the TanStack Query v5 canonical pattern.
13
+ // Key-only entries (all, currencies, exchangeRates) enable hierarchical
14
+ // invalidation. Leaf entries return full queryOptions objects.
15
+ //
16
+ // Usage:
17
+ // useQuery(fiatQueries.currencyList(trailsClient))
18
+ // queryClient.invalidateQueries({ queryKey: fiatQueries.all })
19
+ // fiatQueries.exchangeRate(trailsClient, "EUR").queryKey
20
+ // ============================================================================
21
+
22
+ export const fiatQueries = {
23
+ // -- invalidation root (key-only) --
24
+ all: ["fiat"] as const,
25
+
26
+ // -- currency list --
27
+ currencies: () => [...fiatQueries.all, "currencies"] as const,
28
+
29
+ currencyList: (trailsClient: TrailsClient | null | undefined) => {
30
+ const canFetch = !!trailsClient
31
+ return queryOptions<FiatCurrency[]>({
32
+ queryKey: [...fiatQueries.currencies()] as const,
33
+ queryFn: canFetch ? () => getFiatCurrencyList(trailsClient) : skipToken,
34
+ staleTime: DAY_MS,
35
+ gcTime: DAY_MS,
36
+ retry: createRetry(3),
37
+ retryDelay,
38
+ persister: queryPersister.persisterFn,
39
+ refetchOnMount: false,
40
+ refetchOnReconnect: false,
41
+ })
42
+ },
43
+
44
+ // -- exchange rates --
45
+ exchangeRates: () => [...fiatQueries.all, "exchangeRate"] as const,
46
+
47
+ exchangeRate: (
48
+ trailsClient: TrailsClient | null | undefined,
49
+ targetCurrency: string | null | undefined,
50
+ ) => {
51
+ const canFetch = !!trailsClient && !!targetCurrency
52
+ return queryOptions<ExchangeRate>({
53
+ queryKey: [
54
+ ...fiatQueries.exchangeRates(),
55
+ targetCurrency ?? null,
56
+ ] as const,
57
+ queryFn: canFetch
58
+ ? () => getExchangeRate(trailsClient, targetCurrency)
59
+ : skipToken,
60
+ staleTime: 5 * MINUTE_MS,
61
+ gcTime: HOUR_MS,
62
+ retry: createRetry(2),
63
+ retryDelay,
64
+ persister: queryPersister.persisterFn,
65
+ })
66
+ },
67
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Pure async fetcher functions for Meld/onramp queries.
3
+ * This is a leaf module — NO React imports, NO queryClient.
4
+ */
5
+ import type { TrailsOnramp } from "../onrampClient.js"
6
+ import type {
7
+ MeldServiceProvider,
8
+ GetMeldServiceProvidersRequest,
9
+ MeldPaymentMethod,
10
+ MeldFiatCurrency,
11
+ MeldCryptoCurrency,
12
+ MeldCountryDefault,
13
+ MeldTransaction,
14
+ } from "../onramp-client/trails-onramp.gen.js"
15
+ import { normalizeAddress } from "../utils/address.js"
16
+
17
+ export interface MeldCountryDefaults {
18
+ defaultCurrencyCode: string | undefined
19
+ defaultPaymentMethods: string[]
20
+ }
21
+
22
+ export type {
23
+ MeldServiceProvider,
24
+ MeldPaymentMethod,
25
+ MeldFiatCurrency,
26
+ MeldCryptoCurrency,
27
+ MeldCountryDefault,
28
+ }
29
+
30
+ export type { MeldTransaction }
31
+
32
+ export async function fetchMeldPaymentMethods(
33
+ onrampClient: TrailsOnramp,
34
+ fiatCurrency: string,
35
+ ): Promise<MeldPaymentMethod[]> {
36
+ const response = await onrampClient.getMeldPaymentMethods({ fiatCurrency })
37
+ return Array.isArray(response.paymentMethods) ? response.paymentMethods : []
38
+ }
39
+
40
+ export async function fetchMeldCryptoCurrencies(
41
+ onrampClient: TrailsOnramp,
42
+ countryCode: string,
43
+ ): Promise<MeldCryptoCurrency[]> {
44
+ const response = await onrampClient.getMeldCryptoCurrencies({ countryCode })
45
+ return Array.isArray(response.cryptoCurrencies)
46
+ ? response.cryptoCurrencies
47
+ : []
48
+ }
49
+
50
+ export async function fetchMeldServiceProviders(
51
+ onrampClient: TrailsOnramp,
52
+ options: Partial<GetMeldServiceProvidersRequest> = {},
53
+ ): Promise<MeldServiceProvider[]> {
54
+ const response = await onrampClient.getMeldServiceProviders(options)
55
+ return response.serviceProviders || []
56
+ }
57
+
58
+ export async function fetchMeldFiatCurrencies(
59
+ onrampClient: TrailsOnramp,
60
+ countryCode: string,
61
+ ): Promise<MeldFiatCurrency[]> {
62
+ const response = await onrampClient.getMeldFiatCurrencies({ countryCode })
63
+ return Array.isArray(response.fiatCurrencies) ? response.fiatCurrencies : []
64
+ }
65
+
66
+ export async function fetchMeldCountryDefaults(
67
+ onrampClient: TrailsOnramp,
68
+ countryCode: string,
69
+ ): Promise<MeldCountryDefaults> {
70
+ const response = await onrampClient.getMeldCountryDefaults({ countryCode })
71
+ const defaults = response.defaults?.[0]
72
+ return {
73
+ defaultCurrencyCode: defaults?.defaultCurrencyCode ?? undefined,
74
+ defaultPaymentMethods: defaults?.defaultPaymentMethods || [],
75
+ }
76
+ }
77
+
78
+ export interface MeldTransactionHistoryResult {
79
+ transactions: MeldTransaction[]
80
+ hasMore: boolean
81
+ }
82
+
83
+ export async function fetchMeldTransactionHistory(
84
+ onrampClient: TrailsOnramp,
85
+ walletAddress: string,
86
+ limit: number,
87
+ ): Promise<MeldTransactionHistoryResult> {
88
+ const response = await onrampClient.searchMeldTransactions({
89
+ externalCustomerIds: normalizeAddress(walletAddress),
90
+ limit,
91
+ })
92
+ const transactions = response.transactions?.transactions || []
93
+ return {
94
+ transactions,
95
+ hasMore: transactions.length >= limit,
96
+ }
97
+ }
@@ -0,0 +1,18 @@
1
+ import { useQuery } from "@tanstack/react-query"
2
+ import { useOnrampClient } from "../onrampClient.js"
3
+ import type { GetMeldServiceProvidersRequest } from "../onramp-client/trails-onramp.gen.js"
4
+ import { meldQueries } from "./meld.queries.js"
5
+
6
+ export function useMeldPaymentMethods(fiatCurrency?: string) {
7
+ const onrampClient = useOnrampClient()
8
+ return useQuery(
9
+ meldQueries.paymentMethodList(onrampClient, fiatCurrency ?? null),
10
+ )
11
+ }
12
+
13
+ export function useMeldServiceProviders(
14
+ options?: Partial<GetMeldServiceProvidersRequest>,
15
+ ) {
16
+ const onrampClient = useOnrampClient()
17
+ return useQuery(meldQueries.serviceProviderList(onrampClient, options))
18
+ }
@@ -0,0 +1,184 @@
1
+ import { queryOptions, skipToken } from "@tanstack/react-query"
2
+ import type { TrailsOnramp } from "../onrampClient.js"
3
+ import type {
4
+ GetMeldServiceProvidersRequest,
5
+ MeldServiceProvider,
6
+ } from "../onramp-client/trails-onramp.gen.js"
7
+ import { DAY_MS, MINUTE_MS } from "../utils/time.js"
8
+ import { createRetry, retryDelay, STATIC_QUERY_OPTIONS } from "./helpers.js"
9
+ import { queryPersister } from "./persister.js"
10
+ import {
11
+ fetchMeldPaymentMethods,
12
+ fetchMeldCryptoCurrencies,
13
+ fetchMeldServiceProviders,
14
+ fetchMeldFiatCurrencies,
15
+ fetchMeldCountryDefaults,
16
+ fetchMeldTransactionHistory,
17
+ type MeldPaymentMethod,
18
+ type MeldCountryDefaults,
19
+ type MeldFiatCurrency,
20
+ type MeldCryptoCurrency,
21
+ type MeldTransactionHistoryResult,
22
+ } from "./meld.fetchers.js"
23
+
24
+ // ============================================================================
25
+ // Meld Query Factory
26
+ //
27
+ // Single factory following the TanStack Query v5 canonical pattern.
28
+ // Key-only entries (all, paymentMethods, etc.) enable hierarchical
29
+ // invalidation. Leaf entries return full queryOptions objects.
30
+ //
31
+ // Usage:
32
+ // useQuery(meldQueries.paymentMethodList(client, "USD"))
33
+ // queryClient.invalidateQueries({ queryKey: meldQueries.all })
34
+ // meldQueries.fiatCurrencyList(client, "US").queryKey
35
+ // ============================================================================
36
+
37
+ export const meldQueries = {
38
+ // -- invalidation root (key-only) --
39
+ all: ["meld"] as const,
40
+
41
+ // -- payment methods --
42
+ paymentMethods: () => [...meldQueries.all, "paymentMethods"] as const,
43
+
44
+ paymentMethodList: (
45
+ onrampClient: TrailsOnramp | null | undefined,
46
+ fiatCurrency: string | null | undefined,
47
+ ) => {
48
+ const canFetch = !!onrampClient && !!fiatCurrency
49
+ return queryOptions<MeldPaymentMethod[]>({
50
+ queryKey: [
51
+ ...meldQueries.paymentMethods(),
52
+ fiatCurrency ?? null,
53
+ ] as const,
54
+ queryFn: canFetch
55
+ ? () => fetchMeldPaymentMethods(onrampClient, fiatCurrency)
56
+ : skipToken,
57
+ staleTime: DAY_MS,
58
+ gcTime: DAY_MS,
59
+ retry: createRetry(2),
60
+ retryDelay,
61
+ persister: queryPersister.persisterFn,
62
+ ...STATIC_QUERY_OPTIONS,
63
+ })
64
+ },
65
+
66
+ // -- crypto currencies --
67
+ cryptoCurrencies: () => [...meldQueries.all, "cryptoCurrencies"] as const,
68
+
69
+ cryptoCurrencyList: (
70
+ onrampClient: TrailsOnramp | null | undefined,
71
+ countryCode: string | null | undefined,
72
+ ) => {
73
+ const canFetch = !!onrampClient && !!countryCode
74
+ return queryOptions<MeldCryptoCurrency[]>({
75
+ queryKey: [
76
+ ...meldQueries.cryptoCurrencies(),
77
+ countryCode ?? null,
78
+ ] as const,
79
+ queryFn: canFetch
80
+ ? () => fetchMeldCryptoCurrencies(onrampClient, countryCode)
81
+ : skipToken,
82
+ staleTime: DAY_MS,
83
+ gcTime: DAY_MS,
84
+ retry: createRetry(2),
85
+ retryDelay,
86
+ persister: queryPersister.persisterFn,
87
+ ...STATIC_QUERY_OPTIONS,
88
+ })
89
+ },
90
+
91
+ // -- service providers --
92
+ serviceProviders: () => [...meldQueries.all, "serviceProviders"] as const,
93
+
94
+ serviceProviderList: (
95
+ onrampClient: TrailsOnramp | null | undefined,
96
+ options?: Partial<GetMeldServiceProvidersRequest>,
97
+ ) => {
98
+ const canFetch = !!onrampClient
99
+ return queryOptions<MeldServiceProvider[]>({
100
+ queryKey: [...meldQueries.serviceProviders(), options ?? null] as const,
101
+ queryFn: canFetch
102
+ ? () => fetchMeldServiceProviders(onrampClient, options)
103
+ : skipToken,
104
+ staleTime: DAY_MS,
105
+ gcTime: DAY_MS,
106
+ retry: createRetry(2),
107
+ retryDelay,
108
+ persister: queryPersister.persisterFn,
109
+ ...STATIC_QUERY_OPTIONS,
110
+ })
111
+ },
112
+
113
+ // -- fiat currencies --
114
+ fiatCurrencies: () => [...meldQueries.all, "fiatCurrencies"] as const,
115
+
116
+ fiatCurrencyList: (
117
+ onrampClient: TrailsOnramp | null | undefined,
118
+ countryCode: string | null | undefined,
119
+ ) => {
120
+ const canFetch = !!onrampClient && !!countryCode
121
+ return queryOptions<MeldFiatCurrency[]>({
122
+ queryKey: [...meldQueries.fiatCurrencies(), countryCode ?? null] as const,
123
+ queryFn: canFetch
124
+ ? () => fetchMeldFiatCurrencies(onrampClient, countryCode)
125
+ : skipToken,
126
+ staleTime: DAY_MS,
127
+ gcTime: DAY_MS,
128
+ retry: createRetry(2),
129
+ retryDelay,
130
+ persister: queryPersister.persisterFn,
131
+ ...STATIC_QUERY_OPTIONS,
132
+ })
133
+ },
134
+
135
+ // -- country defaults --
136
+ countryDefaults: () => [...meldQueries.all, "countryDefaults"] as const,
137
+
138
+ countryDefaultsByCode: (
139
+ onrampClient: TrailsOnramp | null | undefined,
140
+ countryCode: string | null | undefined,
141
+ ) => {
142
+ const canFetch = !!onrampClient && !!countryCode
143
+ return queryOptions<MeldCountryDefaults>({
144
+ queryKey: [
145
+ ...meldQueries.countryDefaults(),
146
+ countryCode ?? null,
147
+ ] as const,
148
+ queryFn: canFetch
149
+ ? () => fetchMeldCountryDefaults(onrampClient, countryCode)
150
+ : skipToken,
151
+ staleTime: 10 * MINUTE_MS,
152
+ gcTime: 30 * MINUTE_MS,
153
+ retry: createRetry(2),
154
+ retryDelay,
155
+ persister: queryPersister.persisterFn,
156
+ ...STATIC_QUERY_OPTIONS,
157
+ })
158
+ },
159
+
160
+ // -- transaction history (no persister/STATIC_QUERY_OPTIONS — mutable user data that should refetch on focus) --
161
+ transactionHistory: () => [...meldQueries.all, "transactionHistory"] as const,
162
+
163
+ transactionHistoryList: (
164
+ onrampClient: TrailsOnramp | null | undefined,
165
+ walletAddress: string | null | undefined,
166
+ limit: number = 20,
167
+ ) => {
168
+ const canFetch = !!onrampClient && !!walletAddress
169
+ return queryOptions<MeldTransactionHistoryResult>({
170
+ queryKey: [
171
+ ...meldQueries.transactionHistory(),
172
+ walletAddress ?? null,
173
+ limit,
174
+ ] as const,
175
+ queryFn: canFetch
176
+ ? () => fetchMeldTransactionHistory(onrampClient, walletAddress, limit)
177
+ : skipToken,
178
+ staleTime: 5 * MINUTE_MS,
179
+ gcTime: 30 * MINUTE_MS,
180
+ retry: createRetry(2),
181
+ retryDelay,
182
+ })
183
+ },
184
+ }
package/src/recover.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  Payload,
6
6
  Signature,
7
7
  } from "@0xsequence/wallet-primitives"
8
+ import { isPositiveBigInt } from "./utils/validation.js"
8
9
  import {
9
10
  IntentProtocolVersion,
10
11
  type Intent,
@@ -620,7 +621,7 @@ function checkAnyIntentBalance(
620
621
  const hasBalance = (data: { tokens?: Token[] } | undefined): boolean => {
621
622
  if (!data?.tokens) return false
622
623
  for (const token of data.tokens) {
623
- if (BigInt(token.balance || "0") > 0n) return true
624
+ if (isPositiveBigInt(token.balance || "0")) return true
624
625
  }
625
626
  return false
626
627
  }
@@ -1066,6 +1067,8 @@ export function useIntentRecover({
1066
1067
  refundToAddress: refundToAddress || walletAddress,
1067
1068
  })
1068
1069
 
1070
+ // TODO: temporary ignore this Biome warning for now; do not refactor code in this pass.
1071
+ // biome-ignore lint/correctness/useExhaustiveDependencies: Preserve current dependency shape per requested no-code-change rollback.
1069
1072
  const signPayload = useCallback(async (): Promise<{
1070
1073
  signature: string
1071
1074
  payload: Payload.Calls
@@ -1098,6 +1101,8 @@ export function useIntentRecover({
1098
1101
  return { signature, payload, refundCall }
1099
1102
  }, [walletClient, inner.getDataToSign])
1100
1103
 
1104
+ // TODO: temporary ignore this Biome warning for now; do not refactor code in this pass.
1105
+ // biome-ignore lint/correctness/useExhaustiveDependencies: Preserve current dependency shape per requested no-code-change rollback.
1101
1106
  const getRecoverTx = useCallback(
1102
1107
  async (params: {
1103
1108
  signedHash: string
package/src/tokens.ts CHANGED
@@ -14,6 +14,16 @@ import {
14
14
  polygon,
15
15
  mainnet,
16
16
  avalanche,
17
+ gnosis,
18
+ zksync,
19
+ scroll,
20
+ blast,
21
+ sonic,
22
+ fantom,
23
+ hyperEvm,
24
+ ink,
25
+ katana,
26
+ berachain,
17
27
  etherlink,
18
28
  linea,
19
29
  unichain,
@@ -1739,13 +1749,28 @@ export const commonTokens: Token[] = [
1739
1749
  },
1740
1750
  ]
1741
1751
 
1752
+ // wrapped-native addresses
1742
1753
  export const wethAddresses: Record<string, string> = {
1743
- 1: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
1744
- 10: "0x4200000000000000000000000000000000000006",
1745
- 8453: "0x4200000000000000000000000000000000000006",
1746
- 42161: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
1747
- 137: "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619",
1748
- 100: "0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1",
1754
+ [mainnet.id]: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
1755
+ [optimism.id]: "0x4200000000000000000000000000000000000006",
1756
+ [bsc.id]: "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
1757
+ [gnosis.id]: "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d",
1758
+ [unichain.id]: "0x4200000000000000000000000000000000000006",
1759
+ [base.id]: "0x4200000000000000000000000000000000000006",
1760
+ [sonic.id]: "0x039e2fb66102314ce7b64ce5ce3e5183bc94ad38",
1761
+ [fantom.id]: "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83",
1762
+ [zksync.id]: "0x5aea5775959fbc2557cc8789bc1bf90a239d9a91",
1763
+ [worldchain.id]: "0x4200000000000000000000000000000000000006",
1764
+ [hyperEvm.id]: "0x5555555555555555555555555555555555555555",
1765
+ [polygon.id]: "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270",
1766
+ [ink.id]: "0x4200000000000000000000000000000000000006",
1767
+ [linea.id]: "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f",
1768
+ [arbitrum.id]: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
1769
+ [avalanche.id]: "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7",
1770
+ [scroll.id]: "0x5300000000000000000000000000000000000004",
1771
+ [katana.id]: "0xee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62",
1772
+ [berachain.id]: "0x6969696969696969696969696969696969696969",
1773
+ [blast.id]: "0x4300000000000000000000000000000000000004",
1749
1774
  }
1750
1775
 
1751
1776
  export function getWethAddress(chainId: number): string | null {
@@ -236,6 +236,8 @@ export async function attemptUserDepositTx({
236
236
  sequenceIndexerUrl,
237
237
  abortSignal,
238
238
  depositTransaction: depositTransaction,
239
+ intentId,
240
+ executeIntentFn,
239
241
  })
240
242
  }
241
243
 
@@ -32,7 +32,7 @@ import {
32
32
  getPermitSignature,
33
33
  validateGaslessSignature,
34
34
  } from "../../gasless.js"
35
- import { getIsUserRejectionError } from "../../error.js"
35
+ import { getIsPopupBlockedError, getIsUserRejectionError } from "../../error.js"
36
36
  import { getChainRpcClient } from "../../chains.js"
37
37
  import { TRAILS_CONTRACTS } from "../../constants.js"
38
38
 
@@ -524,7 +524,14 @@ export async function attemptGaslessDeposit({
524
524
  checkoutOnHandlers.triggerCheckoutSignatureRejected(error)
525
525
  }
526
526
  }
527
- throw error
527
+ if (getIsPopupBlockedError(error)) {
528
+ throw new Error(
529
+ "Wallet signature popup was blocked by your browser. " +
530
+ "Please allow pop-ups for this site and try again. " +
531
+ "More details: " +
532
+ error,
533
+ )
534
+ }
528
535
  }
529
536
  }
530
537
 
@@ -6,6 +6,7 @@ import type {
6
6
  TransactionReceipt,
7
7
  } from "viem"
8
8
  import { parseUnits } from "viem"
9
+ import type { ExecuteIntentResponse } from "@0xtrails/api"
9
10
  import type { TransactionState } from "../../transactions.js"
10
11
  import type { CheckoutOnHandlers } from "../../widget/hooks/useCheckout.js"
11
12
  import { logger } from "../../logger.js"
@@ -24,7 +25,10 @@ import { SECOND_MS } from "../../utils/time.js"
24
25
  import { updatePersistentToast } from "../../toast.js"
25
26
  import { getChainInfo } from "../../chains.js"
26
27
  import { trackTransactionConfirmed } from "../../analytics.js"
27
- import { getIsUserRejectionError } from "../../error.js"
28
+ import {
29
+ getIsAlreadyExecutingError,
30
+ getIsUserRejectionError,
31
+ } from "../../error.js"
28
32
  import {
29
33
  trackDepositResilient,
30
34
  isRecoverableDepositError,
@@ -67,6 +71,8 @@ export async function attemptStandardDeposit({
67
71
  sequenceProjectAccessKey,
68
72
  sequenceIndexerUrl,
69
73
  abortSignal,
74
+ intentId,
75
+ executeIntentFn,
70
76
  }: {
71
77
  queryClient?: QueryClient
72
78
  originTokenAddress: string
@@ -95,6 +101,11 @@ export async function attemptStandardDeposit({
95
101
  sequenceProjectAccessKey?: string
96
102
  sequenceIndexerUrl?: string
97
103
  abortSignal?: AbortSignal
104
+ intentId?: string
105
+ executeIntentFn?: (params: {
106
+ intentId: string
107
+ depositTransactionHash?: string
108
+ }) => Promise<ExecuteIntentResponse>
98
109
  depositTransaction?: {
99
110
  to: string
100
111
  data: string
@@ -393,20 +404,30 @@ export async function attemptStandardDeposit({
393
404
  ) // TODO: Add proper type
394
405
  logger.console.log("[trails-sdk] origin tx", txHash)
395
406
 
396
- // NOTE: executeIntent is called by the handler after receipt confirmation
397
- // Do not call it here to avoid duplicate execution errors
398
-
399
- // SIMULATE RPC ERROR: Throw error after successful transaction send
400
- // This simulates the scenario where tx is broadcast but RPC fails immediately after
401
- // if (true) { // Always enabled for testing
402
- // logger.console.warn(
403
- // "[trails-sdk] SIMULATING RPC ERROR after transaction send",
404
- // { txHash }
405
- // )
406
- // throw new Error("SIMULATED: RPC connection lost after transaction broadcast")
407
- // }
407
+ // Call executeIntent immediately after getting txHash (before waiting for receipt).
408
+ // This ensures the backend knows about the intent as soon as the tx is broadcast,
409
+ // allowing integrators to call WaitIntentReceipt right after onCheckoutSignatureConfirmed.
410
+ // Fire-and-forget: errors are logged but don't block the receipt wait.
411
+ if (intentId && txHash && executeIntentFn) {
412
+ executeIntentFn({
413
+ intentId,
414
+ depositTransactionHash: txHash,
415
+ }).catch((error) => {
416
+ // "EXECUTING" means the backend already picked up the intent — that's fine
417
+ if (getIsAlreadyExecutingError(error)) {
418
+ logger.console.log(
419
+ "[trails-sdk] Intent already executing after early executeIntent call, continuing...",
420
+ )
421
+ } else {
422
+ logger.console.error(
423
+ "[trails-sdk] Early executeIntent call failed (will retry after receipt):",
424
+ error,
425
+ )
426
+ }
427
+ })
428
+ }
408
429
 
409
- // Trigger signature confirmed callback after successful signing
430
+ // Trigger signature confirmed callback after early executeIntent
410
431
  if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
411
432
  checkoutOnHandlers?.triggerCheckoutSignatureConfirmed?.()
412
433
  }