0xtrails 0.13.0 → 0.13.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/{ccip-Cg9-lJ6K.js → ccip-CT_An6eM.js} +39 -39
- package/dist/chains.d.ts +4 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/customTokens.d.ts.map +1 -1
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/gasless.d.ts +1 -2
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-DEojZg7b.js → index-RfqL5Foz.js} +56672 -43550
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +385 -333
- package/dist/intents.d.ts +8 -2
- package/dist/intents.d.ts.map +1 -1
- package/dist/keyMachineClient.d.ts +9 -0
- package/dist/keyMachineClient.d.ts.map +1 -0
- package/dist/keymachine/index.d.ts +14 -0
- package/dist/keymachine/index.d.ts.map +1 -0
- package/dist/keymachine/key-machine.gen.d.ts +461 -0
- package/dist/keymachine/key-machine.gen.d.ts.map +1 -0
- package/dist/onramp/MeshConnectFlow.d.ts +18 -0
- package/dist/onramp/MeshConnectFlow.d.ts.map +1 -0
- package/dist/onramp/MeshConnectIframe.d.ts +13 -0
- package/dist/onramp/MeshConnectIframe.d.ts.map +1 -0
- package/dist/onramp/SendFromExchangeButton.d.ts +16 -0
- package/dist/onramp/SendFromExchangeButton.d.ts.map +1 -0
- package/dist/onramp/TrailsOnRampProvider.d.ts +31 -0
- package/dist/onramp/TrailsOnRampProvider.d.ts.map +1 -0
- package/dist/onramp/index.d.ts +13 -0
- package/dist/onramp/index.d.ts.map +1 -0
- package/dist/onramp/meshconnect.d.ts +30 -0
- package/dist/onramp/meshconnect.d.ts.map +1 -0
- package/dist/onramp/trailsOnramp.d.ts +24 -0
- package/dist/onramp/trailsOnramp.d.ts.map +1 -0
- package/dist/onramp-client/index.d.ts +3 -3
- package/dist/onramp-client/index.d.ts.map +1 -1
- package/dist/paymasterSend.d.ts.map +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/query/balance.fetchers.d.ts +31 -2
- package/dist/query/balance.fetchers.d.ts.map +1 -1
- package/dist/query/balance.hooks.d.ts +21 -2
- package/dist/query/balance.hooks.d.ts.map +1 -1
- package/dist/query/balance.queries.d.ts +18 -1
- package/dist/query/balance.queries.d.ts.map +1 -1
- package/dist/query/chains.queries.d.ts.map +1 -1
- package/dist/query/meld.fetchers.d.ts +1 -1
- package/dist/query/meld.fetchers.d.ts.map +1 -1
- package/dist/query/meld.hooks.d.ts +3 -3
- package/dist/query/meld.hooks.d.ts.map +1 -1
- package/dist/query/meld.queries.d.ts +1 -1
- package/dist/query/meld.queries.d.ts.map +1 -1
- package/dist/query/price.fetchers.d.ts +15 -0
- package/dist/query/price.fetchers.d.ts.map +1 -0
- package/dist/query/price.hooks.d.ts +352 -0
- package/dist/query/price.hooks.d.ts.map +1 -0
- package/dist/query/price.queries.d.ts +34 -0
- package/dist/query/price.queries.d.ts.map +1 -0
- package/dist/query/tokenList.queries.d.ts +54 -0
- package/dist/query/tokenList.queries.d.ts.map +1 -0
- package/dist/recover.d.ts +6 -4
- package/dist/recover.d.ts.map +1 -1
- package/dist/tokens.d.ts +13 -0
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +2 -2
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +2 -2
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/intentHandler.d.ts.map +1 -1
- package/dist/transactionIntent/helpers/transactionStateHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +1 -1
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/umd/trails.min.js +291 -202
- package/dist/utils/format.d.ts +7 -0
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +2 -1
- package/dist/walletUtils.d.ts.map +1 -1
- package/dist/wallets.d.ts +13 -54
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/DirectTransfer.d.ts +1 -1
- package/dist/widget/components/DirectTransfer.d.ts.map +1 -1
- package/dist/widget/components/EarnPools.d.ts.map +1 -1
- package/dist/widget/components/ExecutionStatusBadge.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/HighPriceImpactBlock.d.ts +7 -0
- package/dist/widget/components/HighPriceImpactBlock.d.ts.map +1 -0
- package/dist/widget/components/MeldHistory.d.ts.map +1 -1
- package/dist/widget/components/MeshExchangeSelection.d.ts +11 -0
- package/dist/widget/components/MeshExchangeSelection.d.ts.map +1 -0
- package/dist/widget/components/OnrampHistoryRow.d.ts +1 -1
- package/dist/widget/components/OnrampHistoryRow.d.ts.map +1 -1
- package/dist/widget/components/OnrampProviderConfirmation.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QRCodeWalletSelect.d.ts +1 -1
- package/dist/widget/components/QRCodeWalletSelect.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/Recipients.d.ts.map +1 -1
- package/dist/widget/components/RefundWarning.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
- package/dist/widget/components/TransactionHistoryItem.d.ts +2 -0
- package/dist/widget/components/TransactionHistoryItem.d.ts.map +1 -1
- package/dist/widget/components/TransferPendingVertical.d.ts +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WalletImage.d.ts.map +1 -1
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/components/Withdraw.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useAddressWalletIcon.d.ts.map +1 -1
- package/dist/widget/hooks/useCombinedHistory.d.ts +6 -5
- package/dist/widget/hooks/useCombinedHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useCustomTokenSearch.d.ts +6 -1
- package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultDestinationToken.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultOriginToken.d.ts.map +1 -1
- package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts +1 -1
- package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts.map +1 -1
- package/dist/widget/hooks/useGetIntent.d.ts +3 -2
- package/dist/widget/hooks/useGetIntent.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentReceiptBalances.d.ts +1 -1
- package/dist/widget/hooks/useIntentReceiptBalances.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts +3 -2
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useMeldTransactionHistory.d.ts +1 -1
- package/dist/widget/hooks/useMeldTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useMeldTransactionStatus.d.ts +1 -1
- package/dist/widget/hooks/useMeldTransactionStatus.d.ts.map +1 -1
- package/dist/widget/hooks/useOnRampQuote.d.ts +1 -1
- package/dist/widget/hooks/useOnRampQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useOnRampTransactionStatus.d.ts +1 -1
- package/dist/widget/hooks/useOnRampTransactionStatus.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +2 -2
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +7 -0
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +0 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +7 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useViewManager.d.ts +1 -1
- package/dist/widget/hooks/useViewManager.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +2 -0
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/utils/createWagmiConfig.d.ts +2 -2
- package/dist/widget/utils/createWagmiConfig.d.ts.map +1 -1
- package/dist/widget/utils/fundMethodSwitchState.d.ts +1 -0
- package/dist/widget/utils/fundMethodSwitchState.d.ts.map +1 -1
- package/dist/widget/utils/historyFilters.d.ts +13 -0
- package/dist/widget/utils/historyFilters.d.ts.map +1 -0
- package/dist/widget/utils/meldProviderUtils.d.ts +1 -1
- package/dist/widget/utils/meldProviderUtils.d.ts.map +1 -1
- package/dist/widget/utils/meshSupportedTokens.d.ts +4 -0
- package/dist/widget/utils/meshSupportedTokens.d.ts.map +1 -0
- package/dist/widget/utils/onrampConfig.d.ts +11 -0
- package/dist/widget/utils/onrampConfig.d.ts.map +1 -0
- package/dist/widget/utils/statusLabel.d.ts +2 -0
- package/dist/widget/utils/statusLabel.d.ts.map +1 -0
- package/dist/widget/utils/trailsOnrampConfig.d.ts +18 -0
- package/dist/widget/utils/trailsOnrampConfig.d.ts.map +1 -0
- package/dist/widget/widget.d.ts +24 -8
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +9 -7
- package/src/chains.ts +26 -9
- package/src/constants.ts +2 -0
- package/src/customTokens.ts +22 -7
- package/src/error.ts +7 -0
- package/src/gasless.ts +5 -2
- package/src/index.ts +8 -5
- package/src/intents.ts +56 -60
- package/src/keyMachineClient.ts +29 -0
- package/src/keymachine/index.ts +175 -0
- package/src/keymachine/key-machine.gen.ts +993 -0
- package/src/onramp/MeshConnectFlow.tsx +86 -0
- package/src/onramp/MeshConnectIframe.tsx +661 -0
- package/src/onramp/SendFromExchangeButton.tsx +81 -0
- package/src/onramp/TrailsOnRampProvider.tsx +59 -0
- package/src/onramp/index.ts +31 -0
- package/src/onramp/meshconnect.ts +277 -0
- package/src/onramp/trailsOnramp.tsx +130 -0
- package/src/onramp-client/index.ts +4 -6
- package/src/paymasterSend.ts +0 -5
- package/src/prepareSend.ts +45 -44
- package/src/query/balance.fetchers.ts +172 -17
- package/src/query/balance.hooks.ts +69 -6
- package/src/query/balance.queries.ts +63 -0
- package/src/query/chains.queries.ts +1 -6
- package/src/query/meld.fetchers.ts +1 -1
- package/src/query/meld.hooks.ts +1 -1
- package/src/query/meld.queries.ts +1 -1
- package/src/query/price.fetchers.ts +53 -0
- package/src/query/price.hooks.ts +46 -0
- package/src/query/price.queries.ts +364 -0
- package/src/query/tokenList.queries.ts +118 -0
- package/src/recover.ts +89 -26
- package/src/tokens.ts +108 -26
- package/src/transactionIntent/deposits/depositOrchestrator.ts +11 -11
- package/src/transactionIntent/deposits/gaslessDeposit.ts +38 -39
- package/src/transactionIntent/deposits/standardDeposit.ts +5 -30
- package/src/transactionIntent/handlers/intentHandler.ts +29 -12
- package/src/transactionIntent/helpers/transactionStateHelpers.ts +5 -2
- package/src/transactionIntent/quote/normalizeQuote.ts +11 -5
- package/src/transactionIntent/types.ts +1 -1
- package/src/transactions.ts +5 -1
- package/src/utils/format.ts +85 -1
- package/src/walletUtils.ts +2 -1
- package/src/wallets.ts +184 -380
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +134 -109
- package/src/widget/components/ClassicSwap.tsx +26 -24
- package/src/widget/components/ConnectWallet.tsx +4 -2
- package/src/widget/components/ConnectedWallets.tsx +2 -5
- package/src/widget/components/DirectTransfer.tsx +5 -2
- package/src/widget/components/EarnPools.tsx +1 -2
- package/src/widget/components/ExecutionStatusBadge.tsx +10 -4
- package/src/widget/components/Fund.tsx +169 -110
- package/src/widget/components/FundMethods.tsx +5 -9
- package/src/widget/components/HighPriceImpactBlock.tsx +44 -0
- package/src/widget/components/MeldHistory.tsx +4 -28
- package/src/widget/components/MeshExchangeSelection.tsx +218 -0
- package/src/widget/components/OnrampHistoryRow.tsx +3 -27
- package/src/widget/components/OnrampProviderConfirmation.tsx +0 -25
- package/src/widget/components/Pay.tsx +20 -36
- package/src/widget/components/PoolDeposit.tsx +14 -24
- package/src/widget/components/PoolWithdraw.tsx +1 -63
- package/src/widget/components/QRCodeWalletSelect.tsx +5 -2
- package/src/widget/components/QuoteDetails.tsx +113 -106
- package/src/widget/components/Receipt.tsx +0 -11
- package/src/widget/components/Recipients.tsx +2 -1
- package/src/widget/components/RefundWarning.tsx +5 -10
- package/src/widget/components/ThemeProvider.tsx +4 -4
- package/src/widget/components/TokenSelector.tsx +85 -16
- package/src/widget/components/TransactionDetails.tsx +46 -0
- package/src/widget/components/TransactionHistoryItem.tsx +14 -23
- package/src/widget/components/TransferPendingVertical.tsx +17 -11
- package/src/widget/components/WaasFeeOptions.tsx +4 -42
- package/src/widget/components/WalletConnect.tsx +2 -5
- package/src/widget/components/WalletImage.tsx +6 -18
- package/src/widget/components/WalletList.tsx +1 -1
- package/src/widget/components/Withdraw.tsx +22 -23
- package/src/widget/hooks/useAddressWalletIcon.ts +2 -1
- package/src/widget/hooks/useAmountUsd.ts +1 -1
- package/src/widget/hooks/useCombinedHistory.ts +37 -93
- package/src/widget/hooks/useCustomTokenSearch.tsx +63 -33
- package/src/widget/hooks/useDefaultDestinationToken.tsx +2 -5
- package/src/widget/hooks/useDefaultOriginToken.tsx +2 -5
- package/src/widget/hooks/useFiatOnRampCurrencies.ts +1 -1
- package/src/widget/hooks/useGetIntent.ts +5 -4
- package/src/widget/hooks/useIntentReceiptBalances.ts +3 -3
- package/src/widget/hooks/useIntentTransactionHistory.ts +24 -47
- package/src/widget/hooks/useMeldTransactionHistory.ts +4 -2
- package/src/widget/hooks/useMeldTransactionStatus.ts +13 -11
- package/src/widget/hooks/useOnRampQuote.ts +3 -3
- package/src/widget/hooks/useOnRampTransactionStatus.ts +8 -6
- package/src/widget/hooks/useQuote.ts +56 -48
- package/src/widget/hooks/useSelectedFundMethod.tsx +14 -1
- package/src/widget/hooks/useSendForm.ts +52 -31
- package/src/widget/hooks/useTokenList.ts +209 -140
- package/src/widget/hooks/useTrailsSendTransaction.ts +1 -1
- package/src/widget/hooks/useViewManager.tsx +1 -0
- package/src/widget/providers/TrailsProvider.tsx +5 -0
- package/src/widget/styles.ts +1 -1
- package/src/widget/utils/createWagmiConfig.ts +7 -2
- package/src/widget/utils/fundMethodSwitchState.ts +2 -0
- package/src/widget/utils/historyFilters.ts +157 -0
- package/src/widget/utils/meldProviderUtils.ts +8 -2
- package/src/widget/utils/meshSupportedTokens.ts +28 -0
- package/src/widget/utils/onrampConfig.ts +15 -0
- package/src/widget/utils/statusLabel.ts +3 -0
- package/src/widget/utils/trailsOnrampConfig.ts +39 -0
- package/src/widget/widget.tsx +235 -185
- package/dist/onramp-client/trails-onramp.gen.d.ts +0 -570
- package/dist/onramp-client/trails-onramp.gen.d.ts.map +0 -1
- package/dist/prices.d.ts +0 -34
- package/dist/prices.d.ts.map +0 -1
- package/dist/useGasEstimation.d.ts +0 -34
- package/dist/useGasEstimation.d.ts.map +0 -1
- package/dist/widget/hooks/useCustomTokenFetch.d.ts +0 -19
- package/dist/widget/hooks/useCustomTokenFetch.d.ts.map +0 -1
- package/dist/widget/hooks/useTokenWithFreshBalance.d.ts +0 -18
- package/dist/widget/hooks/useTokenWithFreshBalance.d.ts.map +0 -1
- package/src/onramp-client/trails-onramp.gen.ts +0 -1320
- package/src/prices.ts +0 -528
- package/src/useGasEstimation.ts +0 -147
- package/src/widget/assets/Binance_Icon_Logo.svg +0 -14
- package/src/widget/assets/Bitfinex_Icon_Logo.svg +0 -5
- package/src/widget/assets/Coinbase_Icon_Logo.svg +0 -1
- package/src/widget/assets/WalletConnect-logo-blue-bg.svg +0 -11
- package/src/widget/assets/sequence-logo.svg +0 -15
- package/src/widget/hooks/useCustomTokenFetch.tsx +0 -74
- package/src/widget/hooks/useTokenWithFreshBalance.ts +0 -246
package/src/prices.ts
DELETED
|
@@ -1,528 +0,0 @@
|
|
|
1
|
-
import type { Token, TokenPrice } from "@0xtrails/api"
|
|
2
|
-
import { type QueryClient, useQuery } from "@tanstack/react-query"
|
|
3
|
-
import { zeroAddress } from "viem"
|
|
4
|
-
import { logger } from "./logger.js"
|
|
5
|
-
import { parseLocaleNumber } from "./localeUtils.js"
|
|
6
|
-
import { queryClient as defaultQueryClient } from "./query/client.js"
|
|
7
|
-
import { useTrailsClient, type TrailsClient } from "./trailsClient.js"
|
|
8
|
-
import { MINUTE_MS, SECOND_MS, retryDelay } from "./utils/time.js"
|
|
9
|
-
import { useUserActivityContext } from "./widget/providers/UserActivityProvider.js"
|
|
10
|
-
import { isValidNumber, isNonNegativeNumber } from "./utils/validation.js"
|
|
11
|
-
|
|
12
|
-
import { normalizeAddress } from "./utils/address.js"
|
|
13
|
-
|
|
14
|
-
export const priceKeys = {
|
|
15
|
-
all: ["tokenPrices"] as const,
|
|
16
|
-
}
|
|
17
|
-
// Local storage cache configuration
|
|
18
|
-
const LOCAL_STORAGE_CACHE_KEY = "trails_token_prices_cache"
|
|
19
|
-
const LOCAL_STORAGE_CACHE_DURATION = MINUTE_MS
|
|
20
|
-
|
|
21
|
-
// Global caching configuration
|
|
22
|
-
const CACHE_CONFIG = {
|
|
23
|
-
// Time configurations - matches API cache of 90 seconds
|
|
24
|
-
staleTime: 90 * SECOND_MS,
|
|
25
|
-
gcTime: 90 * SECOND_MS,
|
|
26
|
-
refetchInterval: 90 * SECOND_MS,
|
|
27
|
-
|
|
28
|
-
// Retry configurations
|
|
29
|
-
retry: 2,
|
|
30
|
-
retryDelay,
|
|
31
|
-
|
|
32
|
-
// Refetch behaviors
|
|
33
|
-
refetchOnWindowFocus: false,
|
|
34
|
-
refetchOnReconnect: true,
|
|
35
|
-
refetchIntervalInBackground: false,
|
|
36
|
-
|
|
37
|
-
// Retry logic for specific error types
|
|
38
|
-
shouldRetry: (failureCount: number, error: any) => {
|
|
39
|
-
if (error && "status" in error && error.status === 404) return false
|
|
40
|
-
if (failureCount < 2) return true
|
|
41
|
-
return false
|
|
42
|
-
},
|
|
43
|
-
} as const
|
|
44
|
-
|
|
45
|
-
// Extract common query options for reuse
|
|
46
|
-
const COMMON_QUERY_OPTIONS = {
|
|
47
|
-
staleTime: CACHE_CONFIG.staleTime,
|
|
48
|
-
gcTime: CACHE_CONFIG.gcTime,
|
|
49
|
-
retry: CACHE_CONFIG.shouldRetry,
|
|
50
|
-
retryDelay: CACHE_CONFIG.retryDelay,
|
|
51
|
-
refetchOnWindowFocus: CACHE_CONFIG.refetchOnWindowFocus,
|
|
52
|
-
refetchOnReconnect: CACHE_CONFIG.refetchOnReconnect,
|
|
53
|
-
refetchInterval: CACHE_CONFIG.refetchInterval,
|
|
54
|
-
refetchIntervalInBackground: CACHE_CONFIG.refetchIntervalInBackground,
|
|
55
|
-
} as const
|
|
56
|
-
|
|
57
|
-
// Local storage cache helpers
|
|
58
|
-
interface TokenPriceEntry {
|
|
59
|
-
price: TokenPrice
|
|
60
|
-
timestamp: number
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
interface TokenPriceCache {
|
|
64
|
-
// Indexed by chainId -> tokenAddress (lowercase) -> price data
|
|
65
|
-
prices: Record<number, Record<string, TokenPriceEntry>>
|
|
66
|
-
lastCleanup: number
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const getLocalStorageCache = (): TokenPriceCache => {
|
|
70
|
-
try {
|
|
71
|
-
const cached = localStorage.getItem(LOCAL_STORAGE_CACHE_KEY)
|
|
72
|
-
if (!cached) {
|
|
73
|
-
return {
|
|
74
|
-
prices: {},
|
|
75
|
-
lastCleanup: Date.now(),
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const parsed = JSON.parse(cached) as TokenPriceCache
|
|
80
|
-
// Ensure structure is correct
|
|
81
|
-
if (!parsed.prices) {
|
|
82
|
-
return {
|
|
83
|
-
prices: {},
|
|
84
|
-
lastCleanup: Date.now(),
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return parsed
|
|
88
|
-
} catch (error) {
|
|
89
|
-
logger.console.warn(
|
|
90
|
-
"[trails-sdk] Failed to parse localStorage cache:",
|
|
91
|
-
error,
|
|
92
|
-
)
|
|
93
|
-
return {
|
|
94
|
-
prices: {},
|
|
95
|
-
lastCleanup: Date.now(),
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const setLocalStorageCache = (cache: TokenPriceCache): void => {
|
|
101
|
-
try {
|
|
102
|
-
localStorage.setItem(LOCAL_STORAGE_CACHE_KEY, JSON.stringify(cache))
|
|
103
|
-
} catch (error) {
|
|
104
|
-
logger.console.warn(
|
|
105
|
-
"[trails-sdk] Failed to save localStorage cache:",
|
|
106
|
-
error,
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const getCachedTokenPrice = (
|
|
112
|
-
chainId: number,
|
|
113
|
-
tokenAddress: string,
|
|
114
|
-
): TokenPrice | null => {
|
|
115
|
-
const cache = getLocalStorageCache()
|
|
116
|
-
const chainPrices = cache.prices[chainId]
|
|
117
|
-
if (!chainPrices) return null
|
|
118
|
-
|
|
119
|
-
const entry = chainPrices[normalizeAddress(tokenAddress)]
|
|
120
|
-
if (!entry) return null
|
|
121
|
-
|
|
122
|
-
const now = Date.now()
|
|
123
|
-
const age = now - entry.timestamp
|
|
124
|
-
|
|
125
|
-
// Check if cache is still valid (within 60 seconds)
|
|
126
|
-
if (age > LOCAL_STORAGE_CACHE_DURATION) {
|
|
127
|
-
logger.console.debug(
|
|
128
|
-
`[trails-sdk] Cache expired for ${chainId}:${tokenAddress}, age: ${age}ms`,
|
|
129
|
-
)
|
|
130
|
-
return null
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
logger.console.debug(
|
|
134
|
-
`[trails-sdk] Using cached price for ${chainId}:${tokenAddress}, age: ${age}ms`,
|
|
135
|
-
)
|
|
136
|
-
return entry.price
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const getCachedPricesForTokens = (tokens: Token[]): TokenPrice[] | null => {
|
|
140
|
-
if (tokens.length === 0) return []
|
|
141
|
-
|
|
142
|
-
const cache = getLocalStorageCache()
|
|
143
|
-
const now = Date.now()
|
|
144
|
-
const results: TokenPrice[] = []
|
|
145
|
-
|
|
146
|
-
// Check if all tokens have valid cached prices
|
|
147
|
-
for (const token of tokens) {
|
|
148
|
-
const chainPrices = cache.prices[token.chainId]
|
|
149
|
-
if (!chainPrices) return null // Missing chain data
|
|
150
|
-
|
|
151
|
-
const tokenAddress = (token.tokenAddress || zeroAddress).toLowerCase()
|
|
152
|
-
const entry = chainPrices[tokenAddress]
|
|
153
|
-
|
|
154
|
-
if (!entry) return null // Missing token price
|
|
155
|
-
|
|
156
|
-
const age = now - entry.timestamp
|
|
157
|
-
if (age > LOCAL_STORAGE_CACHE_DURATION) {
|
|
158
|
-
return null // Expired price found
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
results.push(entry.price)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
logger.console.debug(
|
|
165
|
-
`[trails-sdk] Using ${results.length} cached prices for batch request`,
|
|
166
|
-
)
|
|
167
|
-
return results
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const setCachedTokenPrices = (prices: TokenPrice[]): void => {
|
|
171
|
-
const cache = getLocalStorageCache()
|
|
172
|
-
const now = Date.now()
|
|
173
|
-
|
|
174
|
-
// Store each price individually
|
|
175
|
-
for (const price of prices) {
|
|
176
|
-
const chainId = price.token.chainId
|
|
177
|
-
const tokenAddress = (price.token.tokenAddress || zeroAddress).toLowerCase()
|
|
178
|
-
|
|
179
|
-
// Ensure chain object exists
|
|
180
|
-
if (!cache.prices[chainId]) {
|
|
181
|
-
cache.prices[chainId] = {}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Store the price entry
|
|
185
|
-
cache.prices[chainId][tokenAddress] = {
|
|
186
|
-
price,
|
|
187
|
-
timestamp: now,
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Clean up old entries periodically (every 5 minutes)
|
|
192
|
-
if (now - cache.lastCleanup > 5 * MINUTE_MS) {
|
|
193
|
-
cleanupExpiredEntries(cache)
|
|
194
|
-
cache.lastCleanup = now
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
setLocalStorageCache(cache)
|
|
198
|
-
logger.console.debug(`[trails-sdk] Cached ${prices.length} token prices`)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const cleanupExpiredEntries = (cache: TokenPriceCache): void => {
|
|
202
|
-
const now = Date.now()
|
|
203
|
-
let removed = 0
|
|
204
|
-
|
|
205
|
-
for (const chainId in cache.prices) {
|
|
206
|
-
const chainPrices = cache.prices[chainId]
|
|
207
|
-
if (!chainPrices) continue
|
|
208
|
-
|
|
209
|
-
for (const tokenAddress in chainPrices) {
|
|
210
|
-
const entry = chainPrices[tokenAddress]
|
|
211
|
-
if (entry && now - entry.timestamp > LOCAL_STORAGE_CACHE_DURATION) {
|
|
212
|
-
delete chainPrices[tokenAddress]
|
|
213
|
-
removed++
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// Remove empty chain objects
|
|
217
|
-
if (Object.keys(chainPrices).length === 0) {
|
|
218
|
-
delete cache.prices[chainId]
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (removed > 0) {
|
|
223
|
-
logger.console.debug(
|
|
224
|
-
`[trails-sdk] Cleaned up ${removed} expired cache entries`,
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Periodic cleanup is now handled in setCachedTokenPrices when needed
|
|
230
|
-
|
|
231
|
-
// Cache key generation methods
|
|
232
|
-
const createTokenCacheKey = (token: Token): string => {
|
|
233
|
-
const tokenAddress = (token.tokenAddress || "").toLowerCase()
|
|
234
|
-
const chainId = Number(token.chainId || 0)
|
|
235
|
-
const tokenSymbol = (token.tokenSymbol || "").toUpperCase()
|
|
236
|
-
return `${tokenAddress}-${chainId}-${tokenSymbol}`
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const createBatchCacheKey = (
|
|
240
|
-
tokens: Token[],
|
|
241
|
-
): (string | number | string[])[] => {
|
|
242
|
-
return [
|
|
243
|
-
"tokenPrices",
|
|
244
|
-
"batch",
|
|
245
|
-
tokens.length,
|
|
246
|
-
tokens.map(createTokenCacheKey).sort(),
|
|
247
|
-
]
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const createSingleCacheKey = (token?: Token | null): (string | null)[] => {
|
|
251
|
-
return ["tokenPrices", "single", token ? createTokenCacheKey(token) : null]
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Separate fetch function for token prices
|
|
255
|
-
export const fetchGetTokenPrices = async (
|
|
256
|
-
trailsClient: TrailsClient,
|
|
257
|
-
tokens: Token[],
|
|
258
|
-
): Promise<TokenPrice[]> => {
|
|
259
|
-
if (!trailsClient) {
|
|
260
|
-
throw new Error("Trails client is required")
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (tokens.length === 0) {
|
|
264
|
-
return [] as TokenPrice[]
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// First, check if all tokens have cached prices
|
|
268
|
-
const cachedPrices = getCachedPricesForTokens(tokens)
|
|
269
|
-
if (cachedPrices) {
|
|
270
|
-
return cachedPrices
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// If not all cached, check which ones we need to fetch
|
|
274
|
-
const tokensToFetch: Token[] = []
|
|
275
|
-
const cachedResults: TokenPrice[] = []
|
|
276
|
-
|
|
277
|
-
for (const token of tokens) {
|
|
278
|
-
const cached = getCachedTokenPrice(
|
|
279
|
-
token.chainId,
|
|
280
|
-
token.tokenAddress || zeroAddress,
|
|
281
|
-
)
|
|
282
|
-
if (cached) {
|
|
283
|
-
cachedResults.push(cached)
|
|
284
|
-
} else {
|
|
285
|
-
tokensToFetch.push(token)
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// If all tokens were cached individually
|
|
290
|
-
if (tokensToFetch.length === 0) {
|
|
291
|
-
logger.console.debug(
|
|
292
|
-
`[trails-sdk] All ${tokens.length} token prices found in cache`,
|
|
293
|
-
)
|
|
294
|
-
return cachedResults
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Fetch only the missing prices
|
|
298
|
-
logger.console.debug(
|
|
299
|
-
`[trails-sdk] Fetching ${tokensToFetch.length} prices, ${cachedResults.length} from cache`,
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
try {
|
|
303
|
-
const res = await trailsClient.getTokenPrices({ tokens: tokensToFetch })
|
|
304
|
-
const fetchedPrices = res?.tokenPrices || []
|
|
305
|
-
|
|
306
|
-
// Store all fetched prices in cache
|
|
307
|
-
if (fetchedPrices.length > 0) {
|
|
308
|
-
setCachedTokenPrices(fetchedPrices)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Combine cached and fetched results, maintaining original order
|
|
312
|
-
const allPrices: TokenPrice[] = []
|
|
313
|
-
for (const token of tokens) {
|
|
314
|
-
const cached = cachedResults.find(
|
|
315
|
-
(p) =>
|
|
316
|
-
p.token.chainId === token.chainId &&
|
|
317
|
-
p.token.tokenAddress?.toLowerCase() ===
|
|
318
|
-
(token.tokenAddress || zeroAddress).toLowerCase(),
|
|
319
|
-
)
|
|
320
|
-
if (cached) {
|
|
321
|
-
allPrices.push(cached)
|
|
322
|
-
} else {
|
|
323
|
-
const fetched = fetchedPrices.find(
|
|
324
|
-
(p) =>
|
|
325
|
-
p.token.chainId === token.chainId &&
|
|
326
|
-
p.token.tokenAddress?.toLowerCase() ===
|
|
327
|
-
(token.tokenAddress || zeroAddress).toLowerCase(),
|
|
328
|
-
)
|
|
329
|
-
if (fetched) {
|
|
330
|
-
allPrices.push(fetched)
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return allPrices
|
|
336
|
-
} catch (error) {
|
|
337
|
-
logger.console.error("[trails-sdk] Failed to fetch token prices:", error)
|
|
338
|
-
throw error
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export function normalizeToken(
|
|
343
|
-
token: Token & {
|
|
344
|
-
tokenID?: string
|
|
345
|
-
symbol?: string
|
|
346
|
-
contractAddress?: string
|
|
347
|
-
tokenId?: string
|
|
348
|
-
},
|
|
349
|
-
): Token {
|
|
350
|
-
return {
|
|
351
|
-
chainId: token.chainId,
|
|
352
|
-
tokenAddress: token.tokenAddress || token.contractAddress || zeroAddress,
|
|
353
|
-
tokenSymbol:
|
|
354
|
-
token.tokenSymbol || token.tokenId || token.tokenID || token.symbol,
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export const getTokenPrices = async (
|
|
359
|
-
trailsClient: TrailsClient,
|
|
360
|
-
tokens: Token[],
|
|
361
|
-
): Promise<TokenPrice[]> => {
|
|
362
|
-
tokens = tokens.map(normalizeToken)
|
|
363
|
-
return fetchGetTokenPrices(trailsClient, tokens)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export const getTokenPrice = async (
|
|
367
|
-
trailsClient: TrailsClient,
|
|
368
|
-
token: Token,
|
|
369
|
-
): Promise<TokenPrice | null> => {
|
|
370
|
-
token = normalizeToken(token)
|
|
371
|
-
const prices = await fetchGetTokenPrices(trailsClient, [token])
|
|
372
|
-
return prices?.length ? (prices[0] ?? null) : null
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export const useTokenPrices = (tokens: Token[], disabled?: boolean) => {
|
|
376
|
-
const trailsClient = useTrailsClient()
|
|
377
|
-
const { isUserActive } = useUserActivityContext()
|
|
378
|
-
tokens = tokens.map(normalizeToken)
|
|
379
|
-
|
|
380
|
-
const { data: tokenPrices, isLoading: isLoadingTokenPrices } = useQuery({
|
|
381
|
-
queryKey: createBatchCacheKey(tokens),
|
|
382
|
-
queryFn: () => getTokenPrices(trailsClient, tokens),
|
|
383
|
-
enabled: !disabled && tokens.length > 0 && !!trailsClient,
|
|
384
|
-
...COMMON_QUERY_OPTIONS,
|
|
385
|
-
refetchInterval: isUserActive ? CACHE_CONFIG.refetchInterval : false, // Pause polling when user is inactive
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
return {
|
|
389
|
-
tokenPrices,
|
|
390
|
-
isLoadingTokenPrices,
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
export const useTokenPrice = (token?: Token | null) => {
|
|
395
|
-
const trailsClient = useTrailsClient()
|
|
396
|
-
const { isUserActive } = useUserActivityContext()
|
|
397
|
-
|
|
398
|
-
const { data: tokenPrice, isLoading: isLoadingTokenPrice } = useQuery({
|
|
399
|
-
queryKey: createSingleCacheKey(token),
|
|
400
|
-
queryFn: () =>
|
|
401
|
-
token && trailsClient ? getTokenPrice(trailsClient, token) : null,
|
|
402
|
-
enabled: !!token && !!trailsClient,
|
|
403
|
-
...COMMON_QUERY_OPTIONS,
|
|
404
|
-
refetchInterval: isUserActive ? CACHE_CONFIG.refetchInterval : false, // Pause polling when user is inactive
|
|
405
|
-
})
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
tokenPrice,
|
|
409
|
-
isLoadingTokenPrice,
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Cache invalidation utility function
|
|
414
|
-
export function invalidateTokenPricesCache(token?: Token, qc?: QueryClient) {
|
|
415
|
-
const client = qc ?? defaultQueryClient
|
|
416
|
-
if (token) {
|
|
417
|
-
// Invalidate specific token price using consistent cache key
|
|
418
|
-
client.invalidateQueries({
|
|
419
|
-
queryKey: createSingleCacheKey(token),
|
|
420
|
-
})
|
|
421
|
-
} else {
|
|
422
|
-
// Invalidate all token price queries
|
|
423
|
-
client.invalidateQueries({
|
|
424
|
-
queryKey: ["tokenPrices"],
|
|
425
|
-
})
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// Also clear localStorage cache
|
|
429
|
-
clearLocalStoragePriceCache()
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Clear all localStorage price cache
|
|
433
|
-
export function clearLocalStoragePriceCache(): void {
|
|
434
|
-
try {
|
|
435
|
-
localStorage.removeItem(LOCAL_STORAGE_CACHE_KEY)
|
|
436
|
-
logger.console.debug("[trails-sdk] Cleared localStorage price cache")
|
|
437
|
-
} catch (error) {
|
|
438
|
-
logger.console.warn(
|
|
439
|
-
"[trails-sdk] Failed to clear localStorage cache:",
|
|
440
|
-
error,
|
|
441
|
-
)
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Export function to manually trigger cleanup if needed
|
|
446
|
-
export function cleanupExpiredPriceCache(): void {
|
|
447
|
-
const cache = getLocalStorageCache()
|
|
448
|
-
cleanupExpiredEntries(cache)
|
|
449
|
-
setLocalStorageCache(cache)
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
export function calcAmountUsdPrice({
|
|
453
|
-
amount,
|
|
454
|
-
usdPrice,
|
|
455
|
-
}: {
|
|
456
|
-
amount: number | string
|
|
457
|
-
usdPrice: string | number | null | undefined
|
|
458
|
-
}) {
|
|
459
|
-
const sanitizedAmount = normalizeNumber(amount)
|
|
460
|
-
const sanitizedPrice = normalizeNumber(usdPrice)
|
|
461
|
-
|
|
462
|
-
// Validate inputs
|
|
463
|
-
if (!isNonNegativeNumber(sanitizedAmount)) {
|
|
464
|
-
return 0
|
|
465
|
-
}
|
|
466
|
-
if (!isNonNegativeNumber(sanitizedPrice)) {
|
|
467
|
-
return 0
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
const result = sanitizedAmount * sanitizedPrice
|
|
471
|
-
|
|
472
|
-
// Validate result
|
|
473
|
-
if (!isValidNumber(result)) {
|
|
474
|
-
logger.console.error("[trails-sdk] Error calculating amount USD:", {
|
|
475
|
-
sanitizedAmount,
|
|
476
|
-
sanitizedPrice,
|
|
477
|
-
result,
|
|
478
|
-
amount,
|
|
479
|
-
usdPrice,
|
|
480
|
-
})
|
|
481
|
-
return 0
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return result
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export function normalizeNumber(
|
|
488
|
-
number: number | string | null | undefined,
|
|
489
|
-
): number {
|
|
490
|
-
if (number === null || number === undefined) {
|
|
491
|
-
return 0
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// If already a number, return it directly
|
|
495
|
-
if (typeof number === "number") {
|
|
496
|
-
// Validate the number
|
|
497
|
-
if (!isValidNumber(number)) {
|
|
498
|
-
logger.console.error("[trails-sdk] Invalid number value:", number)
|
|
499
|
-
return 0
|
|
500
|
-
}
|
|
501
|
-
return number
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// Only parse strings that might be locale-formatted
|
|
505
|
-
// This should ideally only be used for user input, not internal calculations
|
|
506
|
-
const normalized = parseLocaleNumber(number)
|
|
507
|
-
|
|
508
|
-
// Return 0 for invalid numbers
|
|
509
|
-
if (!isValidNumber(normalized)) {
|
|
510
|
-
logger.console.error("[trails-sdk] Error normalizing number string:", {
|
|
511
|
-
number,
|
|
512
|
-
normalized,
|
|
513
|
-
})
|
|
514
|
-
return 0
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return normalized
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// Format TVL (Total Value Locked) for display
|
|
521
|
-
export function formatTvl(tvl: number): string {
|
|
522
|
-
if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(1)}B`
|
|
523
|
-
if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`
|
|
524
|
-
if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(1)}K`
|
|
525
|
-
return `$${tvl.toFixed(0)}`
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
export { isValidNumeric, isValidInteger } from "./utils/validation.js"
|
package/src/useGasEstimation.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { useQuery } from "@tanstack/react-query"
|
|
2
|
-
import type { QueryClient } from "@tanstack/react-query"
|
|
3
|
-
import type { PublicClient } from "viem"
|
|
4
|
-
import { estimateGasLimit, getFeeData } from "./estimate.js"
|
|
5
|
-
import { MINUTE_MS, SECOND_MS } from "./utils/time.js"
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Parameters for gas limit estimation
|
|
9
|
-
*/
|
|
10
|
-
export interface GasEstimationParams {
|
|
11
|
-
account: string
|
|
12
|
-
to: string | bigint | number
|
|
13
|
-
data: string | bigint | number
|
|
14
|
-
value: bigint | string | number
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Helper to create a consistent query key for gas estimation
|
|
19
|
-
*/
|
|
20
|
-
function createGasEstimationQueryKey(
|
|
21
|
-
chainId: number | undefined,
|
|
22
|
-
params: GasEstimationParams | null | undefined,
|
|
23
|
-
) {
|
|
24
|
-
return [
|
|
25
|
-
"gas-limit",
|
|
26
|
-
chainId,
|
|
27
|
-
params?.account,
|
|
28
|
-
params?.to,
|
|
29
|
-
params?.data,
|
|
30
|
-
params?.value?.toString(),
|
|
31
|
-
] as const
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Hook to estimate gas limit with caching
|
|
36
|
-
*
|
|
37
|
-
* Gas LIMIT is cached for 60 seconds
|
|
38
|
-
*/
|
|
39
|
-
export async function fetchCachedGasLimit(
|
|
40
|
-
queryClient: QueryClient,
|
|
41
|
-
publicClient: PublicClient,
|
|
42
|
-
params: GasEstimationParams,
|
|
43
|
-
logContext: string = "transaction",
|
|
44
|
-
): Promise<bigint | undefined> {
|
|
45
|
-
try {
|
|
46
|
-
const result = await queryClient.fetchQuery({
|
|
47
|
-
queryKey: createGasEstimationQueryKey(publicClient.chain?.id, params),
|
|
48
|
-
queryFn: async () => {
|
|
49
|
-
const gasLimit = await estimateGasLimit(
|
|
50
|
-
publicClient,
|
|
51
|
-
params,
|
|
52
|
-
logContext,
|
|
53
|
-
)
|
|
54
|
-
// React Query doesn't allow undefined return values
|
|
55
|
-
// Return null instead and convert back to undefined outside
|
|
56
|
-
if (gasLimit === undefined) {
|
|
57
|
-
return null
|
|
58
|
-
}
|
|
59
|
-
return gasLimit
|
|
60
|
-
},
|
|
61
|
-
staleTime: MINUTE_MS, // 60 seconds
|
|
62
|
-
gcTime: 2 * MINUTE_MS, // Keep in cache for 2 minutes
|
|
63
|
-
retry: 2, // Retry up to 2 times on failure
|
|
64
|
-
})
|
|
65
|
-
// Convert null back to undefined for the caller
|
|
66
|
-
return result === null ? undefined : result
|
|
67
|
-
} catch (_error) {
|
|
68
|
-
// If query fails, return undefined to allow caller to handle gracefully
|
|
69
|
-
return undefined
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function useGasEstimation(
|
|
74
|
-
publicClient: PublicClient | null | undefined,
|
|
75
|
-
params: GasEstimationParams | null | undefined,
|
|
76
|
-
enabled: boolean = true,
|
|
77
|
-
) {
|
|
78
|
-
return useQuery({
|
|
79
|
-
queryKey: createGasEstimationQueryKey(publicClient?.chain?.id, params),
|
|
80
|
-
queryFn: async () => {
|
|
81
|
-
if (!publicClient || !params) {
|
|
82
|
-
throw new Error("Missing publicClient or params for gas estimation")
|
|
83
|
-
}
|
|
84
|
-
const gasLimit = await estimateGasLimit(publicClient, params)
|
|
85
|
-
if (gasLimit === undefined) {
|
|
86
|
-
return null
|
|
87
|
-
}
|
|
88
|
-
return gasLimit
|
|
89
|
-
},
|
|
90
|
-
enabled: enabled && !!publicClient && !!params,
|
|
91
|
-
staleTime: MINUTE_MS, // 60 seconds
|
|
92
|
-
gcTime: 2 * MINUTE_MS, // Keep in cache for 2 minutes
|
|
93
|
-
retry: 2, // Retry up to 2 times on failure
|
|
94
|
-
retryDelay: SECOND_MS, // Wait 1 second between retries
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Helper function to create gas estimation params
|
|
100
|
-
* Useful for ensuring type safety and consistency
|
|
101
|
-
*/
|
|
102
|
-
export function createGasEstimationParams(
|
|
103
|
-
account: string,
|
|
104
|
-
to: string,
|
|
105
|
-
data: string,
|
|
106
|
-
value: bigint | string | number,
|
|
107
|
-
): GasEstimationParams {
|
|
108
|
-
return {
|
|
109
|
-
account,
|
|
110
|
-
to,
|
|
111
|
-
data,
|
|
112
|
-
value,
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Helper to create a consistent query key for fee data
|
|
118
|
-
*/
|
|
119
|
-
function createFeeDataQueryKey(chainId: number | undefined, context: string) {
|
|
120
|
-
return ["gas-fee-data", chainId, context] as const
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Fetch gas fee data (prices) with SHORT-TERM caching
|
|
125
|
-
*
|
|
126
|
-
* Gas PRICES are cached for only 5 seconds
|
|
127
|
-
*/
|
|
128
|
-
export async function fetchCachedFeeData(
|
|
129
|
-
queryClient: QueryClient,
|
|
130
|
-
publicClient: PublicClient,
|
|
131
|
-
context: string = "default",
|
|
132
|
-
): Promise<{
|
|
133
|
-
maxFeePerGas?: bigint
|
|
134
|
-
maxPriorityFeePerGas?: bigint
|
|
135
|
-
gasPrice?: bigint
|
|
136
|
-
}> {
|
|
137
|
-
return await queryClient.fetchQuery({
|
|
138
|
-
queryKey: createFeeDataQueryKey(publicClient.chain?.id, context),
|
|
139
|
-
queryFn: async () => {
|
|
140
|
-
const feeData = await getFeeData(publicClient)
|
|
141
|
-
return feeData
|
|
142
|
-
},
|
|
143
|
-
staleTime: 5 * SECOND_MS, // 5 seconds
|
|
144
|
-
gcTime: 10 * SECOND_MS, // Keep in cache for 10 seconds
|
|
145
|
-
retry: 2,
|
|
146
|
-
})
|
|
147
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
-
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
4
|
-
<svg version="1.1" id="Your_design" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
|
5
|
-
y="0px" width="126.611px" height="126.611px" viewBox="0 0 126.611 126.611" enable-background="new 0 0 126.611 126.611"
|
|
6
|
-
xml:space="preserve">
|
|
7
|
-
<polygon fill="#F3BA2F" points="38.171,53.203 62.759,28.616 87.36,53.216 101.667,38.909 62.759,0 23.864,38.896 "/>
|
|
8
|
-
<rect x="3.644" y="53.188" transform="matrix(0.7071 0.7071 -0.7071 0.7071 48.7933 8.8106)" fill="#F3BA2F" width="20.233" height="20.234"/>
|
|
9
|
-
<polygon fill="#F3BA2F" points="38.171,73.408 62.759,97.995 87.359,73.396 101.674,87.695 101.667,87.703 62.759,126.611
|
|
10
|
-
23.863,87.716 23.843,87.696 "/>
|
|
11
|
-
<rect x="101.64" y="53.189" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 235.5457 29.0503)" fill="#F3BA2F" width="20.234" height="20.233"/>
|
|
12
|
-
<polygon fill="#F3BA2F" points="77.271,63.298 77.277,63.298 62.759,48.78 52.03,59.509 52.029,59.509 50.797,60.742 48.254,63.285
|
|
13
|
-
48.254,63.285 48.234,63.305 48.254,63.326 62.759,77.831 77.277,63.313 77.284,63.305 "/>
|
|
14
|
-
</svg>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
-
<svg width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
-
<circle cx="512" cy="512" r="512" style="fill:#03ca9b"/>
|
|
4
|
-
<path d="M732.81 275c-1.67-.73-173.51-24.6-343.39 86.88C284 431.22 270 532.68 274.81 600.36c247.08-27.89 452.41-317.29 458-325.36zM291.57 675.53c21.24 38.14 181.77 124.6 323.87 5.35S745.62 344.66 732.81 275c-4.47 10.11-159.62 356.89-441.24 400.51" style="fill:#fff"/>
|
|
5
|
-
</svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg width="500" height="500" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg"><path fill="#1652f0" d="m0 0l400 0 0 400-400 0 0-400m168.23 107.38c-24.43 9.85-44.5 29.84-54.56 54.17-7.56 17.87-9.39 37.96-5.94 56.99 4.91 27.2 21.92 51.86 45.41 66.37 17.89 11.27 39.44 16.5 60.5 14.81 23.61-1.56 46.36-12.19 63.08-28.89-10.16-10.4-20.52-20.61-30.81-30.88-12.44 12.02-30.31 18.47-47.55 15.82-12.8-1.69-24.88-8.02-33.6-17.54-11.77-12.48-17.22-30.64-14.2-47.54 1.96-12.42 8.41-24.01 17.75-32.39 12.77-11.76 31.23-17 48.27-13.58 11.09 1.95 21.16 7.72 29.33 15.36 10.31-10.26 20.62-20.52 30.84-30.88-10.58-10.46-23.42-18.68-37.5-23.57-22.82-8.1-48.62-7.47-71.02 1.75"/><path fill="#fff" d="m168.23 107.38c22.4-9.22 48.2-9.85 71.02-1.75 14.08 4.89 26.92 13.11 37.5 23.57-10.22 10.36-20.53 20.62-30.84 30.88-8.17-7.64-18.24-13.41-29.33-15.36-17.04-3.42-35.5 1.82-48.27 13.58-9.34 8.38-15.79 19.97-17.75 32.39-3.02 16.9 2.43 35.06 14.2 47.54 8.72 9.52 20.8 15.85 33.6 17.54 17.24 2.65 35.11-3.8 47.55-15.82 10.29 10.27 20.65 20.48 30.81 30.88-16.72 16.7-39.47 27.33-63.08 28.89-21.06 1.69-42.61-3.54-60.5-14.81-23.49-14.51-40.5-39.17-45.41-66.37-3.45-19.03-1.62-39.12 5.94-56.99 10.06-24.33 30.13-44.32 54.56-54.17"/></svg>
|