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.
- package/dist/analytics.d.ts +65 -50
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-DtfgR432.js → ccip-62W6LwH2.js} +28 -28
- package/dist/chains.d.ts.map +1 -1
- package/dist/error.d.ts +2 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/estimate.d.ts.map +1 -1
- package/dist/fees.d.ts.map +1 -1
- package/dist/{index-CHiCSmCD.js → index-C0QTNYIA.js} +43750 -41806
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +199 -171
- package/dist/localeUtils.d.ts.map +1 -1
- package/dist/meld/components/MeldCountriesList.d.ts +0 -2
- package/dist/meld/components/MeldCountriesList.d.ts.map +1 -1
- package/dist/meld/components/MeldFundMethods.d.ts.map +1 -1
- package/dist/meld/components/MeldTokensList.d.ts.map +1 -1
- package/dist/meld/utils/meld.d.ts +2 -52
- package/dist/meld/utils/meld.d.ts.map +1 -1
- package/dist/poolUtils.d.ts.map +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +1 -2
- package/dist/prices.d.ts.map +1 -1
- package/dist/query/balance.fetchers.d.ts +2 -2
- package/dist/query/balance.fetchers.d.ts.map +1 -1
- package/dist/query/fiat.fetchers.d.ts +11 -0
- package/dist/query/fiat.fetchers.d.ts.map +1 -0
- package/dist/query/fiat.hooks.d.ts +18 -0
- package/dist/query/fiat.hooks.d.ts.map +1 -0
- package/dist/query/fiat.queries.d.ts +24 -0
- package/dist/query/fiat.queries.d.ts.map +1 -0
- package/dist/query/meld.fetchers.d.ts +19 -0
- package/dist/query/meld.fetchers.d.ts.map +1 -0
- package/dist/query/meld.hooks.d.ts +4 -0
- package/dist/query/meld.hooks.d.ts.map +1 -0
- package/dist/query/meld.queries.d.ts +61 -0
- package/dist/query/meld.queries.d.ts.map +1 -0
- package/dist/recover.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +7 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/intentHandler.d.ts +2 -0
- package/dist/transactionIntent/handlers/intentHandler.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +2 -2
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +2 -0
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/balanceChecker.d.ts +3 -1
- package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -9
- package/dist/transactions.d.ts.map +1 -1
- package/dist/umd/trails.min.js +206 -152
- package/dist/utils/fiat.d.ts +8 -0
- package/dist/utils/fiat.d.ts.map +1 -0
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/passthrough.d.ts +5 -2
- package/dist/utils/passthrough.d.ts.map +1 -1
- package/dist/utils/validation.d.ts +33 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +1 -1
- package/dist/walletUtils.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/DepositTracker.d.ts.map +1 -1
- package/dist/widget/components/Earn.d.ts +2 -0
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/HookModalContent.d.ts.map +1 -1
- package/dist/widget/components/MeldForm.d.ts.map +1 -1
- package/dist/widget/components/MeldHistory.d.ts.map +1 -1
- package/dist/widget/components/MeldStepsFlow.d.ts.map +1 -1
- package/dist/widget/components/OFTProgressBar.d.ts +2 -0
- package/dist/widget/components/OFTProgressBar.d.ts.map +1 -1
- package/dist/widget/components/OnRampProviderSelector.d.ts.map +1 -1
- package/dist/widget/components/OnrampHistoryRow.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +2 -0
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -0
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/Withdraw.d.ts.map +1 -1
- package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -1
- package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -1
- package/dist/widget/hooks/useDisplayCurrencyPreference.d.ts.map +1 -1
- package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts +3 -21
- package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts.map +1 -1
- package/dist/widget/hooks/useMeldTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useOnRampCountryDefaults.d.ts +0 -18
- package/dist/widget/hooks/useOnRampCountryDefaults.d.ts.map +1 -1
- package/dist/widget/hooks/useOnRampPaymentMethods.d.ts +2 -18
- package/dist/widget/hooks/useOnRampPaymentMethods.d.ts.map +1 -1
- package/dist/widget/hooks/useOnRampQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +5 -1
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +3 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenWithFreshBalance.d.ts +3 -2
- package/dist/widget/hooks/useTokenWithFreshBalance.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/types/commonProps.d.ts +2 -0
- package/dist/widget/types/commonProps.d.ts.map +1 -1
- package/dist/widget/utils/transactionFailure.d.ts +20 -0
- package/dist/widget/utils/transactionFailure.d.ts.map +1 -0
- package/dist/widget/widget.d.ts +44 -3
- package/dist/widget/widget.d.ts.map +1 -1
- package/dist/widget/workers/intentExecutionWorker.d.ts.map +1 -1
- package/package.json +22 -22
- package/src/analytics.ts +115 -79
- package/src/chains.ts +0 -1
- package/src/error.ts +11 -0
- package/src/estimate.ts +12 -7
- package/src/fees.ts +0 -1
- package/src/index.ts +11 -0
- package/src/localeUtils.ts +3 -1
- package/src/meld/components/MeldCountriesList.tsx +30 -15
- package/src/meld/components/MeldFundMethods.tsx +8 -4
- package/src/meld/components/MeldTokensList.tsx +90 -2
- package/src/meld/utils/meld.ts +3 -400
- package/src/poolUtils.ts +5 -19
- package/src/prepareSend.ts +32 -5
- package/src/prices.ts +7 -33
- package/src/query/balance.fetchers.ts +128 -168
- package/src/query/fiat.fetchers.ts +33 -0
- package/src/query/fiat.hooks.ts +71 -0
- package/src/query/fiat.queries.ts +67 -0
- package/src/query/meld.fetchers.ts +97 -0
- package/src/query/meld.hooks.ts +18 -0
- package/src/query/meld.queries.ts +184 -0
- package/src/recover.ts +6 -1
- package/src/tokens.ts +31 -6
- package/src/transactionIntent/deposits/depositOrchestrator.ts +2 -0
- package/src/transactionIntent/deposits/gaslessDeposit.ts +9 -2
- package/src/transactionIntent/deposits/standardDeposit.ts +35 -14
- package/src/transactionIntent/handlers/intentHandler.ts +134 -138
- package/src/transactionIntent/quote/normalizeQuote.ts +31 -22
- package/src/transactionIntent/quote/quoteHelpers.ts +24 -7
- package/src/transactionIntent/types.ts +2 -0
- package/src/transactionIntent/utils/balanceChecker.ts +10 -4
- package/src/transactions.ts +22 -13
- package/src/umd.tsx +1 -1
- package/src/utils/fiat.ts +32 -0
- package/src/utils/format.ts +1 -3
- package/src/utils/passthrough.ts +19 -3
- package/src/utils/validation.ts +88 -0
- package/src/utils.ts +2 -1
- package/src/walletUtils.ts +2 -2
- package/src/widget/components/AccountIntentTransactionHistory.tsx +2 -2
- package/src/widget/components/ClassicSwap.tsx +10 -4
- package/src/widget/components/DepositTracker.tsx +2 -5
- package/src/widget/components/Earn.tsx +6 -0
- package/src/widget/components/FeeOption.tsx +15 -8
- package/src/widget/components/Fund.tsx +16 -11
- package/src/widget/components/FundMethods.tsx +255 -192
- package/src/widget/components/HookModalContent.tsx +4 -0
- package/src/widget/components/MeldForm.tsx +44 -42
- package/src/widget/components/MeldHistory.tsx +4 -3
- package/src/widget/components/MeldStepsFlow.tsx +33 -71
- package/src/widget/components/OFTProgressBar.tsx +32 -12
- package/src/widget/components/OnRampProviderSelector.tsx +2 -1
- package/src/widget/components/OnrampHistoryRow.tsx +2 -1
- package/src/widget/components/Pay.tsx +8 -2
- package/src/widget/components/PercentageMaxButtons.tsx +5 -3
- package/src/widget/components/PoolDeposit.tsx +6 -0
- package/src/widget/components/PoolWithdraw.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +5 -4
- package/src/widget/components/Receipt.tsx +4 -3
- package/src/widget/components/SlippageToleranceSettings.tsx +3 -2
- package/src/widget/components/Swap.tsx +2 -0
- package/src/widget/components/TransferPendingVertical.tsx +21 -28
- package/src/widget/components/UserPreferences.tsx +1 -1
- package/src/widget/components/Withdraw.tsx +20 -14
- package/src/widget/hooks/useAmountUsd.ts +3 -15
- package/src/widget/hooks/useCustomTokenSearch.tsx +2 -6
- package/src/widget/hooks/useDisplayCurrencyPreference.tsx +1 -2
- package/src/widget/hooks/useFiatOnRampCurrencies.ts +11 -76
- package/src/widget/hooks/useMeldTransactionHistory.ts +24 -89
- package/src/widget/hooks/useOnRampCountryDefaults.ts +3 -49
- package/src/widget/hooks/useOnRampPaymentMethods.ts +21 -100
- package/src/widget/hooks/useOnRampQuote.ts +2 -5
- package/src/widget/hooks/useQuote.ts +10 -12
- package/src/widget/hooks/useSendForm.ts +6 -0
- package/src/widget/hooks/useTokenList.ts +3 -6
- package/src/widget/hooks/useTokenWithFreshBalance.ts +141 -11
- package/src/widget/types/commonProps.ts +2 -0
- package/src/widget/utils/transactionFailure.ts +52 -0
- package/src/widget/widget.tsx +137 -59
- package/src/widget/workers/intentExecutionWorker.ts +3 -1
- package/dist/widget/hooks/useExchangeRate.d.ts +0 -31
- package/dist/widget/hooks/useExchangeRate.d.ts.map +0 -1
- package/dist/widget/hooks/useFiatCurrencyList.d.ts +0 -3
- package/dist/widget/hooks/useFiatCurrencyList.d.ts.map +0 -1
- package/src/widget/hooks/useExchangeRate.ts +0 -257
- package/src/widget/hooks/useFiatCurrencyList.ts +0 -66
package/src/index.ts
CHANGED
|
@@ -137,6 +137,17 @@ export {
|
|
|
137
137
|
formatUsdAmountLocaleDisplay,
|
|
138
138
|
} from "./utils/format.js"
|
|
139
139
|
export { balanceQueries } from "./query/balance.queries.js"
|
|
140
|
+
export { fiatQueries } from "./query/fiat.queries.js"
|
|
141
|
+
export {
|
|
142
|
+
useFiatCurrencyList,
|
|
143
|
+
useExchangeRate,
|
|
144
|
+
} from "./query/fiat.hooks.js"
|
|
145
|
+
export { meldQueries } from "./query/meld.queries.js"
|
|
146
|
+
export {
|
|
147
|
+
useMeldPaymentMethods,
|
|
148
|
+
useMeldServiceProviders,
|
|
149
|
+
} from "./query/meld.hooks.js"
|
|
150
|
+
export { getCurrencyInfo } from "./utils/fiat.js"
|
|
140
151
|
export {
|
|
141
152
|
getTokenPrice,
|
|
142
153
|
getTokenPrices,
|
package/src/localeUtils.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Handles European format (1.234,56) vs US format (1,234.56)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { isValidNumber } from "./utils/validation.js"
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Detects if a string uses European number format
|
|
8
10
|
* European: uses comma as decimal separator and period/space for thousands
|
|
@@ -238,5 +240,5 @@ export function isValidLocaleNumber(value: string): boolean {
|
|
|
238
240
|
}
|
|
239
241
|
|
|
240
242
|
const parsed = parseLocaleNumber(value)
|
|
241
|
-
return
|
|
243
|
+
return isValidNumber(parsed)
|
|
242
244
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Search } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useMemo, useState } from "react"
|
|
4
|
-
import { useCountryCode } from "../../query/geo.hooks.js"
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
4
|
+
import { useCountryCode, useCountryList } from "../../query/geo.hooks.js"
|
|
5
|
+
import { getMeldSupportedCountries } from "../../widget/utils/countryUtils.js"
|
|
6
|
+
import type { Country } from "../utils/meld.js"
|
|
7
7
|
import { SimpleHeader } from "./SimpleHeader.js"
|
|
8
8
|
|
|
9
9
|
// Convert country code (e.g., "US") to flag emoji
|
|
@@ -22,17 +22,25 @@ export interface MeldCountriesListProps {
|
|
|
22
22
|
onBack?: () => void
|
|
23
23
|
onSelectCountry?: (country: Country) => void
|
|
24
24
|
selectedCountry?: Country | null
|
|
25
|
-
trailsClient: TrailsOnramp | null
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
29
28
|
onBack,
|
|
30
29
|
onSelectCountry,
|
|
31
30
|
selectedCountry,
|
|
32
|
-
trailsClient,
|
|
33
31
|
}) => {
|
|
34
|
-
const {
|
|
35
|
-
|
|
32
|
+
const {
|
|
33
|
+
data: apiCountries = [],
|
|
34
|
+
isLoading,
|
|
35
|
+
error,
|
|
36
|
+
refetch,
|
|
37
|
+
} = useCountryList()
|
|
38
|
+
|
|
39
|
+
const countries = useMemo(
|
|
40
|
+
() => getMeldSupportedCountries(apiCountries),
|
|
41
|
+
[apiCountries],
|
|
42
|
+
)
|
|
43
|
+
|
|
36
44
|
const [searchTerm, setSearchTerm] = useState("")
|
|
37
45
|
|
|
38
46
|
// Use proper geolocation hook
|
|
@@ -48,7 +56,7 @@ export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
|
48
56
|
filtered = countries.filter(
|
|
49
57
|
(country) =>
|
|
50
58
|
country.name.toLowerCase().includes(lowerSearchTerm) ||
|
|
51
|
-
country.
|
|
59
|
+
country.countryCode.toLowerCase().includes(lowerSearchTerm),
|
|
52
60
|
)
|
|
53
61
|
}
|
|
54
62
|
|
|
@@ -56,10 +64,16 @@ export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
|
56
64
|
return filtered.sort((a, b) => {
|
|
57
65
|
// If we have a detected user country, prioritize it
|
|
58
66
|
if (userCountryCode) {
|
|
59
|
-
if (
|
|
67
|
+
if (
|
|
68
|
+
a.countryCode === userCountryCode &&
|
|
69
|
+
b.countryCode !== userCountryCode
|
|
70
|
+
) {
|
|
60
71
|
return -1 // a (user's country) comes first
|
|
61
72
|
}
|
|
62
|
-
if (
|
|
73
|
+
if (
|
|
74
|
+
b.countryCode === userCountryCode &&
|
|
75
|
+
a.countryCode !== userCountryCode
|
|
76
|
+
) {
|
|
63
77
|
return 1 // b (user's country) comes first
|
|
64
78
|
}
|
|
65
79
|
}
|
|
@@ -123,7 +137,7 @@ export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
|
123
137
|
)}
|
|
124
138
|
<button
|
|
125
139
|
type="button"
|
|
126
|
-
onClick={refetch}
|
|
140
|
+
onClick={() => refetch()}
|
|
127
141
|
className="mt-3 px-4 py-2 text-sm bg-red-100 hover:bg-red-200 dark:bg-red-800 dark:hover:bg-red-700 text-red-700 dark:text-red-200 rounded-md transition-colors"
|
|
128
142
|
>
|
|
129
143
|
Retry
|
|
@@ -143,12 +157,13 @@ export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
|
143
157
|
</div>
|
|
144
158
|
) : (
|
|
145
159
|
filteredCountries.map((country) => {
|
|
146
|
-
const isSelected =
|
|
147
|
-
|
|
160
|
+
const isSelected =
|
|
161
|
+
selectedCountry?.countryCode === country.countryCode
|
|
162
|
+
const isUserCountry = userCountryCode === country.countryCode
|
|
148
163
|
|
|
149
164
|
return (
|
|
150
165
|
<button
|
|
151
|
-
key={country.
|
|
166
|
+
key={country.countryCode}
|
|
152
167
|
type="button"
|
|
153
168
|
onClick={() => handleCountrySelect(country)}
|
|
154
169
|
className={`w-full flex items-center justify-between cursor-pointer font-semibold py-4 px-6 rounded-lg transition-all duration-200 ${
|
|
@@ -159,7 +174,7 @@ export const MeldCountriesList: React.FC<MeldCountriesListProps> = ({
|
|
|
159
174
|
>
|
|
160
175
|
<div className="flex items-center space-x-3 flex-1">
|
|
161
176
|
<div className="w-10 h-10 rounded-lg flex items-center justify-center text-2xl">
|
|
162
|
-
{getCountryFlag(country.
|
|
177
|
+
{getCountryFlag(country.countryCode)}
|
|
163
178
|
</div>
|
|
164
179
|
<div className="flex-1 text-left">
|
|
165
180
|
<div className="flex items-center gap-2">
|
|
@@ -3,7 +3,8 @@ import type React from "react"
|
|
|
3
3
|
import { useMemo, useState } from "react"
|
|
4
4
|
import { logger } from "../../logger.js"
|
|
5
5
|
import type { TrailsOnramp } from "../../onrampClient.js"
|
|
6
|
-
import {
|
|
6
|
+
import { useQuery } from "@tanstack/react-query"
|
|
7
|
+
import { meldQueries } from "../../query/meld.queries.js"
|
|
7
8
|
import { SimpleHeader } from "./SimpleHeader.js"
|
|
8
9
|
|
|
9
10
|
export type MeldPaymentMethod =
|
|
@@ -33,9 +34,12 @@ export const MeldFundMethods: React.FC<MeldFundMethodsProps> = ({
|
|
|
33
34
|
fiatCurrency = "USD",
|
|
34
35
|
onNavigateToFund,
|
|
35
36
|
}) => {
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const {
|
|
38
|
+
data: paymentMethods = [],
|
|
39
|
+
isLoading,
|
|
40
|
+
error,
|
|
41
|
+
} = useQuery(
|
|
42
|
+
meldQueries.paymentMethodList(trailsClient || null, fiatCurrency),
|
|
39
43
|
)
|
|
40
44
|
const [searchTerm, setSearchTerm] = useState("")
|
|
41
45
|
const [failedImages, setFailedImages] = useState<Set<string>>(new Set())
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { Search } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useMemo, useState } from "react"
|
|
4
|
+
import { useQuery } from "@tanstack/react-query"
|
|
5
|
+
import { zeroAddress } from "viem"
|
|
4
6
|
import type { TrailsOnramp } from "../../onrampClient.js"
|
|
5
7
|
import { TokenImage } from "../../widget/components/TokenImage.js"
|
|
6
|
-
import {
|
|
8
|
+
import { getChainInfo } from "../../chains.js"
|
|
9
|
+
import { commonTokens } from "../../tokens.js"
|
|
10
|
+
import { useSupportedChains } from "../../query/chains.hooks.js"
|
|
11
|
+
import { meldQueries } from "../../query/meld.queries.js"
|
|
12
|
+
import { MELD_CHAIN_SUFFIX_TO_ID, type MeldToken } from "../utils/meld.js"
|
|
7
13
|
import { SimpleHeader } from "./SimpleHeader.js"
|
|
8
14
|
|
|
9
15
|
// Get chain badge color
|
|
@@ -40,7 +46,89 @@ export const MeldTokensList: React.FC<MeldTokensListProps> = ({
|
|
|
40
46
|
trailsClient,
|
|
41
47
|
countryCode,
|
|
42
48
|
}) => {
|
|
43
|
-
const {
|
|
49
|
+
const {
|
|
50
|
+
data: rawCurrencies = [],
|
|
51
|
+
isLoading: isLoadingCurrencies,
|
|
52
|
+
error: currenciesError,
|
|
53
|
+
} = useQuery(
|
|
54
|
+
meldQueries.cryptoCurrencyList(trailsClient, countryCode ?? null),
|
|
55
|
+
)
|
|
56
|
+
const { data: supportedChains = [] } = useSupportedChains()
|
|
57
|
+
const supportedChainIds = useMemo(
|
|
58
|
+
() => supportedChains.map((c) => c.id),
|
|
59
|
+
[supportedChains],
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
// Transform raw API data into MeldToken[] with filtering
|
|
63
|
+
const tokens = useMemo(() => {
|
|
64
|
+
const allowedSymbols = new Set([
|
|
65
|
+
"ETH",
|
|
66
|
+
"MATIC",
|
|
67
|
+
"AVAX",
|
|
68
|
+
"BNB",
|
|
69
|
+
"USDC",
|
|
70
|
+
"USDT",
|
|
71
|
+
"DAI",
|
|
72
|
+
])
|
|
73
|
+
const stablecoins = ["USDC", "USDT", "DAI"]
|
|
74
|
+
|
|
75
|
+
return rawCurrencies
|
|
76
|
+
.map((crypto) => {
|
|
77
|
+
const code = crypto.currencyCode || ""
|
|
78
|
+
const name = crypto.name || code
|
|
79
|
+
const parts = code.split("_")
|
|
80
|
+
const symbol = parts[0] || code
|
|
81
|
+
const chain = parts[1] || ""
|
|
82
|
+
const chainId = MELD_CHAIN_SUFFIX_TO_ID[chain]
|
|
83
|
+
let contractAddress: string | undefined
|
|
84
|
+
|
|
85
|
+
if (chainId && symbol) {
|
|
86
|
+
const isNativeToken =
|
|
87
|
+
(symbol === "ETH" && [1, 10, 8453, 42161].includes(chainId)) ||
|
|
88
|
+
(symbol === "MATIC" && chainId === 137) ||
|
|
89
|
+
(symbol === "AVAX" && chainId === 43114) ||
|
|
90
|
+
(symbol === "BNB" && chainId === 56)
|
|
91
|
+
|
|
92
|
+
if (isNativeToken) {
|
|
93
|
+
contractAddress = zeroAddress
|
|
94
|
+
} else {
|
|
95
|
+
const commonToken = commonTokens.find(
|
|
96
|
+
(token) => token.symbol === symbol && token.chainId === chainId,
|
|
97
|
+
)
|
|
98
|
+
contractAddress = commonToken?.contractAddress
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
code,
|
|
104
|
+
name,
|
|
105
|
+
symbol,
|
|
106
|
+
chain,
|
|
107
|
+
chainName: chainId ? (getChainInfo(chainId)?.name ?? chain) : chain,
|
|
108
|
+
chainId,
|
|
109
|
+
contractAddress,
|
|
110
|
+
} satisfies MeldToken
|
|
111
|
+
})
|
|
112
|
+
.filter((token) => allowedSymbols.has(token.symbol))
|
|
113
|
+
.filter(
|
|
114
|
+
(token) =>
|
|
115
|
+
token.chainId != null && supportedChainIds.includes(token.chainId),
|
|
116
|
+
)
|
|
117
|
+
.filter(
|
|
118
|
+
(token, index, self) =>
|
|
119
|
+
index === self.findIndex((t) => t.code === token.code),
|
|
120
|
+
)
|
|
121
|
+
.sort((a, b) => {
|
|
122
|
+
const aIsStable = stablecoins.includes(a.symbol)
|
|
123
|
+
const bIsStable = stablecoins.includes(b.symbol)
|
|
124
|
+
if (aIsStable && !bIsStable) return -1
|
|
125
|
+
if (!aIsStable && bIsStable) return 1
|
|
126
|
+
return a.symbol.localeCompare(b.symbol)
|
|
127
|
+
})
|
|
128
|
+
}, [rawCurrencies, supportedChainIds])
|
|
129
|
+
|
|
130
|
+
const isLoading = isLoadingCurrencies
|
|
131
|
+
const error = currenciesError
|
|
44
132
|
const [searchTerm, setSearchTerm] = useState("")
|
|
45
133
|
|
|
46
134
|
// Filter tokens based on search term and put selected token at the top
|
package/src/meld/utils/meld.ts
CHANGED
|
@@ -2,17 +2,7 @@
|
|
|
2
2
|
* Utility functions for Meld integration
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { useQuery } from "@tanstack/react-query"
|
|
7
|
-
import { DAY_MS } from "../../utils/time.js"
|
|
8
|
-
import {
|
|
9
|
-
getOnrampClient,
|
|
10
|
-
useOnrampClient,
|
|
11
|
-
type TrailsOnramp,
|
|
12
|
-
} from "../../onrampClient.js"
|
|
13
|
-
import { getChainInfo, getSupportedSequenceChains } from "../../chains.js"
|
|
14
|
-
import { commonTokens } from "../../tokens.js"
|
|
15
|
-
import { zeroAddress } from "viem"
|
|
5
|
+
import { getOnrampClient, type TrailsOnramp } from "../../onrampClient.js"
|
|
16
6
|
import {
|
|
17
7
|
mainnet,
|
|
18
8
|
base,
|
|
@@ -24,15 +14,8 @@ import {
|
|
|
24
14
|
} from "viem/chains"
|
|
25
15
|
import { getConfig } from "../../config.js"
|
|
26
16
|
import { PROD_TRAILS_API_URL } from "../../constants.js"
|
|
27
|
-
import { useCountryList } from "../../query/geo.hooks.js"
|
|
28
|
-
import { getMeldSupportedCountries } from "../../widget/utils/countryUtils.js"
|
|
29
|
-
import type {
|
|
30
|
-
MeldServiceProvider,
|
|
31
|
-
GetMeldServiceProvidersRequest,
|
|
32
|
-
} from "../../onramp-client/trails-onramp.gen.js"
|
|
33
|
-
import { logger } from "../../index.js"
|
|
34
17
|
|
|
35
|
-
const MELD_CHAIN_SUFFIX_TO_ID: Record<string, number> = {
|
|
18
|
+
export const MELD_CHAIN_SUFFIX_TO_ID: Record<string, number> = {
|
|
36
19
|
ETH: mainnet.id,
|
|
37
20
|
BASE: base.id,
|
|
38
21
|
OP: optimism.id,
|
|
@@ -57,127 +40,10 @@ export function getMeldOnrampClient(
|
|
|
57
40
|
}
|
|
58
41
|
|
|
59
42
|
export interface Country {
|
|
60
|
-
|
|
43
|
+
countryCode: string
|
|
61
44
|
name: string
|
|
62
45
|
}
|
|
63
46
|
|
|
64
|
-
/**
|
|
65
|
-
* Hook to fetch list of countries from API
|
|
66
|
-
* Returns a list of countries that support Meld
|
|
67
|
-
*/
|
|
68
|
-
export function useMeldCountries(_trailsClient: TrailsOnramp | null): {
|
|
69
|
-
countries: Country[]
|
|
70
|
-
isLoading: boolean
|
|
71
|
-
error: Error | null
|
|
72
|
-
refetch: () => void
|
|
73
|
-
} {
|
|
74
|
-
// Use the country list from the API
|
|
75
|
-
const {
|
|
76
|
-
data: apiCountries = [],
|
|
77
|
-
isLoading,
|
|
78
|
-
error,
|
|
79
|
-
refetch,
|
|
80
|
-
} = useCountryList()
|
|
81
|
-
|
|
82
|
-
// Convert API countries to Meld format and filter for Meld-supported countries
|
|
83
|
-
const countries = useMemo(() => {
|
|
84
|
-
const meldSupportedCountries = getMeldSupportedCountries(apiCountries)
|
|
85
|
-
return meldSupportedCountries.map((country) => ({
|
|
86
|
-
code: country.countryCode,
|
|
87
|
-
name: country.name,
|
|
88
|
-
}))
|
|
89
|
-
}, [apiCountries])
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
countries,
|
|
93
|
-
isLoading,
|
|
94
|
-
error: error as Error | null,
|
|
95
|
-
refetch,
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Hook to fetch payment methods for Meld (for use in MeldFundMethods component)
|
|
101
|
-
* Uses a default fiat currency (USD) or can accept a country code to get the default currency
|
|
102
|
-
*
|
|
103
|
-
* @note Results are cached for 24 hours as payment methods are stable and don't change frequently.
|
|
104
|
-
*/
|
|
105
|
-
export function useMeldPaymentMethods(
|
|
106
|
-
trailsClient: TrailsOnramp | null,
|
|
107
|
-
fiatCurrency: string = "USD",
|
|
108
|
-
): {
|
|
109
|
-
paymentMethods: Array<{
|
|
110
|
-
paymentMethod: string
|
|
111
|
-
name: string
|
|
112
|
-
paymentType: string
|
|
113
|
-
logos?: { dark?: string; light?: string }
|
|
114
|
-
}>
|
|
115
|
-
isLoading: boolean
|
|
116
|
-
error: Error | null
|
|
117
|
-
} {
|
|
118
|
-
const { data, isLoading, error } = useQuery({
|
|
119
|
-
queryKey: ["meld-payment-methods", fiatCurrency],
|
|
120
|
-
queryFn: async () => {
|
|
121
|
-
if (!trailsClient) {
|
|
122
|
-
throw new Error("No trails client available")
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
logger.console.log(
|
|
126
|
-
"[useMeldPaymentMethods] Fetching payment methods for:",
|
|
127
|
-
fiatCurrency,
|
|
128
|
-
)
|
|
129
|
-
const response = await trailsClient.getMeldPaymentMethods({
|
|
130
|
-
fiatCurrency,
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
// Parse payment methods from response
|
|
134
|
-
const methods = Array.isArray(response.paymentMethods)
|
|
135
|
-
? response.paymentMethods
|
|
136
|
-
: []
|
|
137
|
-
|
|
138
|
-
const parsedMethods = methods.map(
|
|
139
|
-
(method: {
|
|
140
|
-
paymentMethod?: string
|
|
141
|
-
payment_method?: string
|
|
142
|
-
name?: string
|
|
143
|
-
paymentType?: string
|
|
144
|
-
payment_type?: string
|
|
145
|
-
logos?: { dark?: string; light?: string }
|
|
146
|
-
}) => ({
|
|
147
|
-
paymentMethod: method.paymentMethod || method.payment_method || "",
|
|
148
|
-
name: method.name || "",
|
|
149
|
-
paymentType: method.paymentType || method.payment_type || "",
|
|
150
|
-
logos: method.logos
|
|
151
|
-
? {
|
|
152
|
-
dark: method.logos.dark,
|
|
153
|
-
light: method.logos.light,
|
|
154
|
-
}
|
|
155
|
-
: undefined,
|
|
156
|
-
}),
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
logger.console.log(
|
|
160
|
-
"[useMeldPaymentMethods] Fetched",
|
|
161
|
-
parsedMethods.length,
|
|
162
|
-
"methods",
|
|
163
|
-
)
|
|
164
|
-
return parsedMethods
|
|
165
|
-
},
|
|
166
|
-
enabled: !!trailsClient,
|
|
167
|
-
staleTime: DAY_MS, // 24 hours - payment methods don't change frequently
|
|
168
|
-
gcTime: DAY_MS, // 24 hours cache time
|
|
169
|
-
retry: 2,
|
|
170
|
-
refetchOnWindowFocus: false,
|
|
171
|
-
refetchOnReconnect: false, // Don't refetch on reconnect since data is stable for 24h
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
return {
|
|
175
|
-
paymentMethods: data || [],
|
|
176
|
-
isLoading,
|
|
177
|
-
error: error as Error | null,
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
47
|
export interface MeldToken {
|
|
182
48
|
code: string // e.g., "USDC_ETH"
|
|
183
49
|
name: string // e.g., "USD Coin"
|
|
@@ -209,266 +75,3 @@ export interface MeldQuote {
|
|
|
209
75
|
lowKyc: boolean | null
|
|
210
76
|
partnerFee: number
|
|
211
77
|
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Hook to fetch and filter crypto tokens from Meld
|
|
215
|
-
* Filters to show only: Native tokens (ETH, MATIC, AVAX, BNB) + stablecoins (USDC, USDT, DAI)
|
|
216
|
-
*/
|
|
217
|
-
export function useMeldTokens(
|
|
218
|
-
trailsClient: TrailsOnramp | null,
|
|
219
|
-
countryCode?: string,
|
|
220
|
-
): {
|
|
221
|
-
tokens: MeldToken[]
|
|
222
|
-
isLoading: boolean
|
|
223
|
-
error: Error | null
|
|
224
|
-
} {
|
|
225
|
-
const [tokens, setTokens] = useState<MeldToken[]>([])
|
|
226
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
227
|
-
const [error, setError] = useState<Error | null>(null)
|
|
228
|
-
const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
229
|
-
const abortControllerRef = useRef<AbortController | null>(null)
|
|
230
|
-
|
|
231
|
-
useEffect(() => {
|
|
232
|
-
if (!trailsClient) {
|
|
233
|
-
setTokens([])
|
|
234
|
-
return
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Clear any existing debounce timer
|
|
238
|
-
if (debounceTimerRef.current) {
|
|
239
|
-
clearTimeout(debounceTimerRef.current)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Abort any in-flight requests
|
|
243
|
-
if (abortControllerRef.current) {
|
|
244
|
-
abortControllerRef.current.abort()
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Create new abort controller
|
|
248
|
-
abortControllerRef.current = new AbortController()
|
|
249
|
-
|
|
250
|
-
// Debounce the fetch
|
|
251
|
-
debounceTimerRef.current = setTimeout(() => {
|
|
252
|
-
setIsLoading(true)
|
|
253
|
-
setError(null)
|
|
254
|
-
|
|
255
|
-
const fetchTokens = async () => {
|
|
256
|
-
try {
|
|
257
|
-
// If no country code provided, don't fetch
|
|
258
|
-
if (!countryCode) {
|
|
259
|
-
logger.console.log("[useMeldTokens] No country code provided")
|
|
260
|
-
setTokens([])
|
|
261
|
-
setIsLoading(false)
|
|
262
|
-
return
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
logger.console.log(
|
|
266
|
-
"[useMeldTokens] Fetching tokens for country:",
|
|
267
|
-
countryCode,
|
|
268
|
-
)
|
|
269
|
-
const response = await trailsClient.getMeldCryptoCurrencies({
|
|
270
|
-
countryCode: countryCode,
|
|
271
|
-
})
|
|
272
|
-
logger.console.log("[useMeldTokens] API response:", response)
|
|
273
|
-
|
|
274
|
-
// Check if request was aborted
|
|
275
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Parse crypto currencies from response
|
|
280
|
-
const cryptos = Array.isArray(response.cryptoCurrencies)
|
|
281
|
-
? response.cryptoCurrencies
|
|
282
|
-
: []
|
|
283
|
-
|
|
284
|
-
// Allowed tokens: native tokens + major stablecoins
|
|
285
|
-
const allowedSymbols = new Set([
|
|
286
|
-
"ETH",
|
|
287
|
-
"MATIC",
|
|
288
|
-
"AVAX",
|
|
289
|
-
"BNB",
|
|
290
|
-
"USDC",
|
|
291
|
-
"USDT",
|
|
292
|
-
"DAI",
|
|
293
|
-
])
|
|
294
|
-
|
|
295
|
-
// Get supported Sequence chain IDs
|
|
296
|
-
const supportedChainIds = (await getSupportedSequenceChains()).map(
|
|
297
|
-
(chain) => chain.id,
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
const parsedTokens: MeldToken[] = cryptos
|
|
301
|
-
.map((crypto) => {
|
|
302
|
-
const code = crypto.currencyCode || ""
|
|
303
|
-
const name = crypto.name || code
|
|
304
|
-
|
|
305
|
-
// Parse token code (e.g., "USDC_ETH" -> symbol: "USDC", chain: "ETH")
|
|
306
|
-
const parts = code.split("_")
|
|
307
|
-
const symbol = parts[0] || code
|
|
308
|
-
const chain = parts[1] || ""
|
|
309
|
-
|
|
310
|
-
const chainId = MELD_CHAIN_SUFFIX_TO_ID[chain]
|
|
311
|
-
let contractAddress: string | undefined
|
|
312
|
-
|
|
313
|
-
if (chainId && symbol) {
|
|
314
|
-
// For native tokens, use zero address
|
|
315
|
-
const isNativeToken =
|
|
316
|
-
(symbol === "ETH" &&
|
|
317
|
-
[1, 10, 8453, 42161].includes(chainId)) ||
|
|
318
|
-
(symbol === "MATIC" && chainId === 137) ||
|
|
319
|
-
(symbol === "AVAX" && chainId === 43114) ||
|
|
320
|
-
(symbol === "BNB" && chainId === 56)
|
|
321
|
-
|
|
322
|
-
if (isNativeToken) {
|
|
323
|
-
contractAddress = zeroAddress
|
|
324
|
-
} else {
|
|
325
|
-
// Look up contract address in commonTokens
|
|
326
|
-
const commonToken = commonTokens.find(
|
|
327
|
-
(token) =>
|
|
328
|
-
token.symbol === symbol && token.chainId === chainId,
|
|
329
|
-
)
|
|
330
|
-
contractAddress = commonToken?.contractAddress
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return {
|
|
335
|
-
code,
|
|
336
|
-
name,
|
|
337
|
-
symbol,
|
|
338
|
-
chain,
|
|
339
|
-
chainName: chainId
|
|
340
|
-
? (getChainInfo(chainId)?.name ?? chain)
|
|
341
|
-
: chain,
|
|
342
|
-
chainId,
|
|
343
|
-
contractAddress,
|
|
344
|
-
}
|
|
345
|
-
})
|
|
346
|
-
.filter((token) => allowedSymbols.has(token.symbol)) // Only allowed tokens
|
|
347
|
-
.filter(
|
|
348
|
-
(token) =>
|
|
349
|
-
token.chainId && supportedChainIds.includes(token.chainId),
|
|
350
|
-
) // Only Sequence-supported chains
|
|
351
|
-
.filter(
|
|
352
|
-
(token, index, self) =>
|
|
353
|
-
// Remove duplicates by code
|
|
354
|
-
index === self.findIndex((t) => t.code === token.code),
|
|
355
|
-
)
|
|
356
|
-
// Sort: Stablecoins first (USDC, USDT, DAI), then native tokens
|
|
357
|
-
.sort((a, b) => {
|
|
358
|
-
const stablecoins = ["USDC", "USDT", "DAI"]
|
|
359
|
-
const aIsStable = stablecoins.includes(a.symbol)
|
|
360
|
-
const bIsStable = stablecoins.includes(b.symbol)
|
|
361
|
-
|
|
362
|
-
if (aIsStable && !bIsStable) return -1
|
|
363
|
-
if (!aIsStable && bIsStable) return 1
|
|
364
|
-
|
|
365
|
-
// Within same category, sort alphabetically
|
|
366
|
-
return a.symbol.localeCompare(b.symbol)
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
// Check if aborted before setting state
|
|
370
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
371
|
-
return
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
logger.console.log(
|
|
375
|
-
"[useMeldTokens] Setting tokens:",
|
|
376
|
-
parsedTokens.length,
|
|
377
|
-
"tokens",
|
|
378
|
-
)
|
|
379
|
-
logger.console.log("[useMeldTokens] Tokens:", parsedTokens)
|
|
380
|
-
setTokens(parsedTokens)
|
|
381
|
-
} catch (err) {
|
|
382
|
-
// Ignore abort errors
|
|
383
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
384
|
-
return
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Check if aborted before setting error
|
|
388
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
389
|
-
return
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
setError(err instanceof Error ? err : new Error(String(err)))
|
|
393
|
-
setTokens([])
|
|
394
|
-
} finally {
|
|
395
|
-
// Only update loading state if not aborted
|
|
396
|
-
if (!abortControllerRef.current?.signal.aborted) {
|
|
397
|
-
setIsLoading(false)
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
fetchTokens()
|
|
403
|
-
}, 300)
|
|
404
|
-
|
|
405
|
-
// Cleanup function
|
|
406
|
-
return () => {
|
|
407
|
-
if (debounceTimerRef.current) {
|
|
408
|
-
clearTimeout(debounceTimerRef.current)
|
|
409
|
-
}
|
|
410
|
-
if (abortControllerRef.current) {
|
|
411
|
-
abortControllerRef.current.abort()
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}, [trailsClient, countryCode])
|
|
415
|
-
|
|
416
|
-
return { tokens, isLoading, error }
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* Hook to fetch list of Meld service providers
|
|
421
|
-
* Supports filtering by country, currencies, payment methods, etc.
|
|
422
|
-
*
|
|
423
|
-
* @note Results are cached for 24 hours as service providers are stable and don't change frequently.
|
|
424
|
-
*/
|
|
425
|
-
export function useMeldProviders(
|
|
426
|
-
trailsClient?: TrailsOnramp | null,
|
|
427
|
-
options?: Partial<GetMeldServiceProvidersRequest>,
|
|
428
|
-
): {
|
|
429
|
-
providers: MeldServiceProvider[]
|
|
430
|
-
isLoading: boolean
|
|
431
|
-
error: Error | null
|
|
432
|
-
refetch: () => void
|
|
433
|
-
} {
|
|
434
|
-
const defaultOnrampClient = useOnrampClient()
|
|
435
|
-
const onrampClient = trailsClient ?? defaultOnrampClient
|
|
436
|
-
|
|
437
|
-
const { data, isLoading, error, refetch } = useQuery({
|
|
438
|
-
queryKey: ["meld-service-providers", options],
|
|
439
|
-
queryFn: async () => {
|
|
440
|
-
if (!onrampClient) {
|
|
441
|
-
throw new Error("No onramp client available")
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
logger.console.log(
|
|
445
|
-
"[useMeldProviders] Fetching service providers with options:",
|
|
446
|
-
options,
|
|
447
|
-
)
|
|
448
|
-
|
|
449
|
-
const response = await onrampClient.getMeldServiceProviders(options || {})
|
|
450
|
-
|
|
451
|
-
const providersData = response.serviceProviders || []
|
|
452
|
-
|
|
453
|
-
logger.console.log(
|
|
454
|
-
`[useMeldProviders] Found ${providersData.length} providers:`,
|
|
455
|
-
providersData,
|
|
456
|
-
)
|
|
457
|
-
|
|
458
|
-
return providersData
|
|
459
|
-
},
|
|
460
|
-
enabled: !!onrampClient,
|
|
461
|
-
staleTime: DAY_MS, // 24 hours - service providers don't change frequently
|
|
462
|
-
gcTime: DAY_MS, // 24 hours cache time
|
|
463
|
-
retry: 2,
|
|
464
|
-
refetchOnWindowFocus: false,
|
|
465
|
-
refetchOnReconnect: false, // Don't refetch on reconnect since data is stable for 24h
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
return {
|
|
469
|
-
providers: data || [],
|
|
470
|
-
isLoading,
|
|
471
|
-
error: error as Error | null,
|
|
472
|
-
refetch,
|
|
473
|
-
}
|
|
474
|
-
}
|