0xtrails 0.6.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aave.d.ts +10 -2
- package/dist/aave.d.ts.map +1 -1
- package/dist/analytics.d.ts +26 -0
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-CbJrlK-L.js → ccip-fConRNoG.js} +21 -21
- package/dist/chains.d.ts +23 -8
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -5
- package/dist/constants.d.ts.map +1 -1
- package/dist/customTokens.d.ts +12 -0
- package/dist/customTokens.d.ts.map +1 -0
- package/dist/decoders.d.ts +2 -2
- package/dist/decoders.d.ts.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/fees.d.ts +37 -2
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +15 -36
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-w7_dK4c5.js → index-BbajxCG_.js} +59269 -77146
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +828 -359
- package/dist/indexerClient.d.ts.map +1 -1
- package/dist/intentReceiptMonitor.d.ts +1 -1
- package/dist/intentReceiptMonitor.d.ts.map +1 -1
- package/dist/intentReceiptPoller.d.ts +1 -1
- package/dist/intentReceiptPoller.d.ts.map +1 -1
- package/dist/intents.d.ts +3 -2
- package/dist/intents.d.ts.map +1 -1
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/mutations.d.ts +2 -2
- package/dist/mutations.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +2 -2
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +1 -1
- package/dist/prices.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +2 -2
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/time.d.ts +6 -0
- package/dist/time.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +40 -25
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +54 -14
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trailsClient.d.ts +1 -1
- package/dist/trailsClient.d.ts.map +1 -1
- package/dist/trailsRouter.d.ts +2 -1
- package/dist/trailsRouter.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -2
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +2 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +5 -3
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +5 -3
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/feeExtractors.d.ts +1 -6
- package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +4 -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 +28 -5
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/testnetHelpers.d.ts +0 -1
- package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/validators.d.ts +0 -2
- package/dist/transactionIntent/validators.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -2
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +7 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/wallets.d.ts +1 -0
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/AddressWalletIcon.d.ts +6 -0
- package/dist/widget/components/AddressWalletIcon.d.ts.map +1 -0
- package/dist/widget/components/ChainFilterDropdown.d.ts +2 -6
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ChainImage.d.ts.map +1 -1
- package/dist/widget/components/ChainList.d.ts +0 -5
- package/dist/widget/components/ChainList.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +6 -6
- 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/DebugMenu.d.ts +1 -1
- package/dist/widget/components/DebugMenu.d.ts.map +1 -1
- package/dist/widget/components/DebugScreensList.d.ts.map +1 -1
- package/dist/widget/components/DepositTracker.d.ts.map +1 -1
- package/dist/widget/components/Earn.d.ts +5 -5
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +1 -1
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +2 -2
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/Footer.d.ts +1 -1
- package/dist/widget/components/Footer.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +5 -5
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts +0 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +6 -6
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/HookModalContent.d.ts +8 -0
- package/dist/widget/components/HookModalContent.d.ts.map +1 -0
- package/dist/widget/components/OriginSelectionAmount.d.ts +11 -0
- package/dist/widget/components/OriginSelectionAmount.d.ts.map +1 -0
- package/dist/widget/components/Pay.d.ts +5 -5
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +5 -5
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -3
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts +2 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecentTokens.d.ts +4 -4
- package/dist/widget/components/RecentTokens.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ShadowPortal.d.ts +6 -0
- package/dist/widget/components/ShadowPortal.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +6 -6
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenList.d.ts +3 -4
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts +3 -4
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +6 -1
- package/dist/widget/components/Tooltip.d.ts.map +1 -1
- package/dist/widget/components/TrailsHookModal.d.ts +10 -0
- package/dist/widget/components/TrailsHookModal.d.ts.map +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts +3 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WidgetProviders.d.ts +14 -0
- package/dist/widget/components/WidgetProviders.d.ts.map +1 -0
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useAddressWalletIcon.d.ts +10 -0
- package/dist/widget/hooks/useAddressWalletIcon.d.ts.map +1 -0
- package/dist/widget/hooks/useBalanceVisible.d.ts +1 -1
- package/dist/widget/hooks/useBalanceVisible.d.ts.map +1 -1
- package/dist/widget/hooks/useChainFilter.d.ts +1 -1
- package/dist/widget/hooks/useChainFilter.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +13 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useConnector.d.ts +4 -0
- package/dist/widget/hooks/useConnector.d.ts.map +1 -0
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useCustomTokenFetch.d.ts +19 -0
- package/dist/widget/hooks/useCustomTokenFetch.d.ts.map +1 -0
- package/dist/widget/hooks/useCustomTokenSearch.d.ts +20 -0
- package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -0
- package/dist/widget/hooks/useDebounce.d.ts +10 -0
- package/dist/widget/hooks/useDebounce.d.ts.map +1 -0
- package/dist/widget/hooks/useDebugScreens.d.ts +7 -2
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -19
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useDestinationSelectedToken.d.ts +1 -14
- package/dist/widget/hooks/useDestinationSelectedToken.d.ts.map +1 -1
- package/dist/widget/hooks/useEarnPool.d.ts +1 -1
- package/dist/widget/hooks/useEarnPool.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsMobile.d.ts +5 -0
- package/dist/widget/hooks/useIsMobile.d.ts.map +1 -0
- package/dist/widget/hooks/useMode.d.ts +2 -2
- package/dist/widget/hooks/useMode.d.ts.map +1 -1
- package/dist/widget/hooks/useOriginSelectedToken.d.ts +2 -15
- package/dist/widget/hooks/useOriginSelectedToken.d.ts.map +1 -1
- package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
- package/dist/widget/hooks/usePriceImpactWarning.d.ts +1 -1
- package/dist/widget/hooks/usePriceImpactWarning.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +173 -4
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts +3 -3
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useRecipients.d.ts +1 -1
- package/dist/widget/hooks/useRecipients.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +2 -2
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedRecipient.d.ts +1 -1
- package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +9 -31
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useSwapAmount.d.ts +1 -1
- package/dist/widget/hooks/useSwapAmount.d.ts.map +1 -1
- package/dist/widget/hooks/useTheme.d.ts +1 -1
- package/dist/widget/hooks/useTheme.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +7 -31
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useTrailsSendTransaction.d.ts +83 -0
- package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -0
- package/dist/widget/hooks/useWalletConnectUri.d.ts +11 -0
- package/dist/widget/hooks/useWalletConnectUri.d.ts.map +1 -0
- package/dist/widget/hooks/useWidgetProps.d.ts +5 -0
- package/dist/widget/hooks/useWidgetProps.d.ts.map +1 -1
- package/dist/widget/index.d.ts +2 -0
- package/dist/widget/index.d.ts.map +1 -1
- package/dist/widget/index.js +8 -5
- package/dist/widget/providers/TrailsModalProvider.d.ts +65 -0
- package/dist/widget/providers/TrailsModalProvider.d.ts.map +1 -0
- package/dist/widget/providers/TrailsProvider.d.ts +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/types.d.ts +11 -18
- package/dist/widget/types.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +20 -11
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +45 -49
- package/src/aave.ts +387 -138
- package/src/analytics.ts +208 -2
- package/src/chains.ts +65 -64
- package/src/constants.ts +18 -14
- package/src/customTokens.ts +151 -0
- package/src/decoders.ts +4 -7
- package/src/error.ts +7 -3
- package/src/fees.ts +239 -125
- package/src/gasless.ts +54 -108
- package/src/index.ts +29 -9
- package/src/indexerClient.ts +2 -0
- package/src/intentReceiptMonitor.ts +1 -4
- package/src/intentReceiptPoller.ts +2 -2
- package/src/intents.ts +16 -5
- package/src/mode.ts +1 -1
- package/src/mutations.ts +7 -3
- package/src/prepareSend.ts +19 -14
- package/src/prices.ts +1 -1
- package/src/sequenceWallet.ts +2 -2
- package/src/time.ts +28 -0
- package/src/tokenBalances.ts +348 -153
- package/src/tokens.ts +393 -142
- package/src/trailsClient.ts +1 -1
- package/src/trailsRouter.ts +4 -5
- package/src/transactionIntent/deposits/depositOrchestrator.ts +6 -2
- package/src/transactionIntent/deposits/gaslessDeposit.ts +13 -7
- package/src/transactionIntent/deposits/standardDeposit.ts +1 -1
- package/src/transactionIntent/execution/transactionState.ts +1 -1
- package/src/transactionIntent/handlers/crossChain.ts +75 -37
- package/src/transactionIntent/handlers/sameChainSameToken.ts +66 -20
- package/src/transactionIntent/quote/feeExtractors.ts +1 -29
- package/src/transactionIntent/quote/normalizeQuote.ts +99 -7
- package/src/transactionIntent/quote/quoteHelpers.ts +1 -1
- package/src/transactionIntent/types.ts +31 -6
- package/src/transactionIntent/utils/testnetHelpers.ts +0 -5
- package/src/transactionIntent/validators.ts +0 -30
- package/src/transactions.ts +3 -3
- package/src/utils.ts +18 -0
- package/src/wallets.ts +32 -10
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +2 -1
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +2 -2
- package/src/widget/components/AddressWalletIcon.tsx +29 -0
- package/src/widget/components/ChainFilterDropdown.tsx +2 -8
- package/src/widget/components/ChainImage.tsx +8 -5
- package/src/widget/components/ChainList.tsx +6 -8
- package/src/widget/components/ClassicSwap.tsx +93 -85
- package/src/widget/components/ConnectWallet.tsx +1 -2
- package/src/widget/components/ConnectedWallets.tsx +17 -4
- package/src/widget/components/DebugMenu.tsx +2 -2
- package/src/widget/components/DebugScreensList.tsx +0 -1
- package/src/widget/components/DepositTracker.tsx +20 -34
- package/src/widget/components/Earn.tsx +7 -6
- package/src/widget/components/FeeOption.tsx +4 -4
- package/src/widget/components/FeeOptions.tsx +19 -39
- package/src/widget/components/Footer.tsx +1 -1
- package/src/widget/components/Fund.tsx +23 -119
- package/src/widget/components/FundMethods.tsx +9 -6
- package/src/widget/components/FundSwap.tsx +6 -5
- package/src/widget/components/FundingMethodSelectorButton.tsx +2 -2
- package/src/widget/components/HookModalContent.tsx +306 -0
- package/src/widget/components/Modal.tsx +1 -1
- package/src/widget/components/OriginSelectionAmount.tsx +135 -0
- package/src/widget/components/Pay.tsx +66 -124
- package/src/widget/components/PoolDeposit.tsx +11 -55
- package/src/widget/components/PoolWithdraw.tsx +3 -3
- package/src/widget/components/QuoteDetails.tsx +473 -728
- package/src/widget/components/Receipt.tsx +74 -7
- package/src/widget/components/RecentTokens.tsx +8 -8
- package/src/widget/components/RecipientSelectorButton.tsx +4 -2
- package/src/widget/components/ScreenHeader.tsx +2 -2
- package/src/widget/components/SearchInputField.tsx +1 -1
- package/src/widget/components/ShadowPortal.tsx +58 -0
- package/src/widget/components/Swap.tsx +6 -5
- package/src/widget/components/ThemeProvider.tsx +1 -1
- package/src/widget/components/TokenList.tsx +3 -4
- package/src/widget/components/TokenSelector.tsx +211 -80
- package/src/widget/components/Tooltip.tsx +18 -7
- package/src/widget/components/TrailsHookModal.tsx +118 -0
- package/src/widget/components/WaasFeeOptions.tsx +333 -138
- package/src/widget/components/WalletConfirmation.tsx +7 -2
- package/src/widget/components/WalletConnect.tsx +197 -235
- package/src/widget/components/WidgetProviders.tsx +75 -0
- package/src/widget/hooks/useAddressWalletIcon.ts +53 -0
- package/src/widget/hooks/useBalanceVisible.tsx +1 -1
- package/src/widget/hooks/useChainFilter.tsx +1 -1
- package/src/widget/hooks/useCheckout.ts +13 -1
- package/src/widget/hooks/useConnector.tsx +18 -0
- package/src/widget/hooks/useCurrentScreen.tsx +3 -3
- package/src/widget/hooks/useCustomTokenFetch.tsx +72 -0
- package/src/widget/hooks/useCustomTokenSearch.tsx +402 -0
- package/src/widget/hooks/useDebounce.ts +25 -0
- package/src/widget/hooks/useDebugScreens.ts +26 -10
- package/src/widget/hooks/useDefaultTokenSelection.tsx +99 -143
- package/src/widget/hooks/useDestinationSelectedToken.tsx +1 -14
- package/src/widget/hooks/useEarnPool.tsx +1 -1
- package/src/widget/hooks/useIntentTransactionHistory.ts +20 -11
- package/src/widget/hooks/useIsMobile.tsx +50 -0
- package/src/widget/hooks/useMode.ts +2 -3
- package/src/widget/hooks/useOriginSelectedToken.tsx +2 -15
- package/src/widget/hooks/usePayMessage.tsx +31 -11
- package/src/widget/hooks/usePriceImpactWarning.ts +1 -1
- package/src/widget/hooks/useQuote.ts +189 -6
- package/src/widget/hooks/useRecentTokens.ts +6 -6
- package/src/widget/hooks/useRecipients.ts +1 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +2 -2
- package/src/widget/hooks/useSelectedFundMethod.tsx +1 -1
- package/src/widget/hooks/useSelectedRecipient.tsx +1 -1
- package/src/widget/hooks/useSendForm.ts +328 -152
- package/src/widget/hooks/useSwapAmount.tsx +1 -1
- package/src/widget/hooks/useTheme.tsx +1 -1
- package/src/widget/hooks/useTokenList.ts +672 -400
- package/src/widget/hooks/useTrailsSendTransaction.ts +949 -0
- package/src/widget/hooks/useWalletConnectUri.tsx +228 -0
- package/src/widget/hooks/useWidgetProps.tsx +3 -1
- package/src/widget/index.tsx +12 -0
- package/src/widget/providers/TrailsModalProvider.tsx +195 -0
- package/src/widget/providers/TrailsProvider.tsx +9 -3
- package/src/widget/types.ts +12 -20
- package/src/widget/widget.tsx +598 -385
- package/dist/cctp.d.ts +0 -3
- package/dist/cctp.d.ts.map +0 -1
- package/dist/lifi.d.ts +0 -4
- package/dist/lifi.d.ts.map +0 -1
- package/dist/meshconnect.d.ts +0 -171
- package/dist/meshconnect.d.ts.map +0 -1
- package/dist/relaySdk.d.ts +0 -87
- package/dist/relaySdk.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -7
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectFlow.d.ts +0 -13
- package/dist/widget/components/MeshConnectFlow.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectIframe.d.ts +0 -15
- package/dist/widget/components/MeshConnectIframe.d.ts.map +0 -1
- package/dist/widget/components/Receive.d.ts +0 -12
- package/dist/widget/components/Receive.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedMeshExchange.d.ts +0 -14
- package/dist/widget/hooks/useSelectedMeshExchange.d.ts.map +0 -1
- package/src/cctp.ts +0 -54
- package/src/lifi.ts +0 -108
- package/src/meshconnect.ts +0 -531
- package/src/relaySdk.ts +0 -703
- package/src/widget/components/MeshConnectExchanges.tsx +0 -290
- package/src/widget/components/MeshConnectFlow.tsx +0 -90
- package/src/widget/components/MeshConnectIframe.tsx +0 -500
- package/src/widget/components/Receive.tsx +0 -175
- package/src/widget/hooks/useSelectedMeshExchange.tsx +0 -46
|
@@ -0,0 +1,949 @@
|
|
|
1
|
+
import { useMutation } from "@tanstack/react-query"
|
|
2
|
+
import { useCallback, useRef } from "react"
|
|
3
|
+
import { useWalletClient, useAccount, useChainId } from "wagmi"
|
|
4
|
+
import { logger } from "../../logger.js"
|
|
5
|
+
import { getFullErrorMessage, getIsUserRejectionError } from "../../error.js"
|
|
6
|
+
import type { UseQuoteProps, SwapReturn } from "./useQuote.js"
|
|
7
|
+
import { prepareSend, TradeType } from "../../prepareSend.js"
|
|
8
|
+
import { useTrailsClient } from "../../trailsClient.js"
|
|
9
|
+
import { useTrails } from "../../widget/providers/TrailsProvider.js"
|
|
10
|
+
import {
|
|
11
|
+
useTrailsModal,
|
|
12
|
+
type HostTransactionDetails,
|
|
13
|
+
type HostTransactionResultLinks,
|
|
14
|
+
type HostTransactionStatus,
|
|
15
|
+
} from "../../widget/providers/TrailsModalProvider.js"
|
|
16
|
+
import { useIndexerGatewayClient } from "../../indexerClient.js"
|
|
17
|
+
import {
|
|
18
|
+
getTokenBalancesWithPrices,
|
|
19
|
+
getHasSufficientBalanceToken,
|
|
20
|
+
} from "../../tokenBalances.js"
|
|
21
|
+
import { useSupportedTokens } from "../../tokens.js"
|
|
22
|
+
import { getChainInfo } from "../../chains.js"
|
|
23
|
+
import { getTokenPrice } from "../../prices.js"
|
|
24
|
+
import { zeroAddress, erc20Abi, type Address, type Hex } from "viem"
|
|
25
|
+
import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
|
|
26
|
+
import { getExplorerUrl } from "../../explorer.js"
|
|
27
|
+
import type { TransactionState } from "../../transactions.js"
|
|
28
|
+
|
|
29
|
+
export type TrailsSendTransactionVariables = {
|
|
30
|
+
to?: Address
|
|
31
|
+
value?: bigint // Native token amount for ORIGIN (wagmi-compatible, sends ETH/native token)
|
|
32
|
+
data?: Hex
|
|
33
|
+
// Destination token requirements (e.g., AAVE deposit needs USDC on Base)
|
|
34
|
+
// Note: Destination can be ERC20 token, so value is NOT needed for destination
|
|
35
|
+
tokenAddress?: Address // Destination token address (ERC20 token required at destination)
|
|
36
|
+
tokenAmount?: string // Destination token amount (in token units, e.g., 3000000 for 3 USDC)
|
|
37
|
+
// Origin token parameters (if not provided, modal will open for selection)
|
|
38
|
+
// Use value for native token origin, OR fromTokenAddress/fromChainId/fromAmount for ERC20 origin
|
|
39
|
+
fromTokenAddress?: Address // Origin token address (ERC20 token to send from)
|
|
40
|
+
fromChainId?: number // Origin chain ID (required if fromTokenAddress is provided)
|
|
41
|
+
fromAmount?: string // Origin token amount (required if fromTokenAddress is provided)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type UseTrailsSendTransactionParameters = Omit<
|
|
45
|
+
UseQuoteProps,
|
|
46
|
+
| "fromTokenAddress"
|
|
47
|
+
| "fromChainId"
|
|
48
|
+
| "toTokenAddress"
|
|
49
|
+
| "toChainId"
|
|
50
|
+
| "swapAmount"
|
|
51
|
+
| "toRecipient"
|
|
52
|
+
| "toCalldata"
|
|
53
|
+
| "tradeType"
|
|
54
|
+
| "selectedFeeOption"
|
|
55
|
+
> & {
|
|
56
|
+
/**
|
|
57
|
+
* Callback fired when the mutation is successful
|
|
58
|
+
*/
|
|
59
|
+
onSuccess?: (
|
|
60
|
+
data: SwapReturn,
|
|
61
|
+
variables: TrailsSendTransactionVariables,
|
|
62
|
+
) => void
|
|
63
|
+
/**
|
|
64
|
+
* Callback fired when the mutation encounters an error
|
|
65
|
+
*/
|
|
66
|
+
onError?: (error: Error, variables: TrailsSendTransactionVariables) => void
|
|
67
|
+
/**
|
|
68
|
+
* Callback fired when the mutation is either successfully fetched or encounters an error
|
|
69
|
+
*/
|
|
70
|
+
onSettled?: (
|
|
71
|
+
data: SwapReturn | undefined,
|
|
72
|
+
error: Error | null,
|
|
73
|
+
variables: TrailsSendTransactionVariables,
|
|
74
|
+
) => void
|
|
75
|
+
/**
|
|
76
|
+
* Custom text for the receipt action button (default: "Transact Again")
|
|
77
|
+
*/
|
|
78
|
+
receiptActionButtonText?: string
|
|
79
|
+
/**
|
|
80
|
+
* Custom callback when receipt action button is clicked
|
|
81
|
+
*/
|
|
82
|
+
onReceiptAction?: () => void
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type UseTrailsSendTransactionReturnType = {
|
|
86
|
+
sendTransaction: (
|
|
87
|
+
variables: TrailsSendTransactionVariables,
|
|
88
|
+
callbacks?: {
|
|
89
|
+
onSuccess?: (data: SwapReturn) => void
|
|
90
|
+
onError?: (error: Error) => void
|
|
91
|
+
onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
|
|
92
|
+
},
|
|
93
|
+
) => void
|
|
94
|
+
sendTransactionAsync: (
|
|
95
|
+
variables: TrailsSendTransactionVariables,
|
|
96
|
+
callbacks?: {
|
|
97
|
+
onSuccess?: (data: SwapReturn) => void
|
|
98
|
+
onError?: (error: Error) => void
|
|
99
|
+
onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
|
|
100
|
+
},
|
|
101
|
+
) => Promise<SwapReturn>
|
|
102
|
+
retry: () => void
|
|
103
|
+
data: SwapReturn | undefined
|
|
104
|
+
error: Error | null
|
|
105
|
+
isPending: boolean
|
|
106
|
+
isSuccess: boolean
|
|
107
|
+
isError: boolean
|
|
108
|
+
isIdle: boolean
|
|
109
|
+
status: "idle" | "pending" | "error" | "success"
|
|
110
|
+
reset: () => void
|
|
111
|
+
variables: TrailsSendTransactionVariables | undefined
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Hook for creating, signing, and sending transactions to networks using Trails SDK.
|
|
116
|
+
* Provides a one-line replacement for wagmi's `useSendTransaction`.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* // Simple usage - one line replacement (wagmi-compatible API)
|
|
121
|
+
* const { sendTransaction } = useTrailsSendTransaction()
|
|
122
|
+
*
|
|
123
|
+
* // Send native token (same as wagmi)
|
|
124
|
+
* sendTransaction({
|
|
125
|
+
* to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
|
|
126
|
+
* value: parseEther('0.01'),
|
|
127
|
+
* })
|
|
128
|
+
*
|
|
129
|
+
* // Deposit 3 USDC to AAVE pool (Trails-specific)
|
|
130
|
+
* // Modal will open for user to select origin token/chain/amount
|
|
131
|
+
* sendTransaction({
|
|
132
|
+
* to: '0xaavePoolAddress',
|
|
133
|
+
* tokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
|
|
134
|
+
* tokenAmount: '3000000', // 3 USDC (6 decimals)
|
|
135
|
+
* data: '0x...', // AAVE deposit calldata
|
|
136
|
+
* })
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export function useTrailsSendTransaction(
|
|
140
|
+
params?: UseTrailsSendTransactionParameters,
|
|
141
|
+
): UseTrailsSendTransactionReturnType {
|
|
142
|
+
const { data: walletClient } = useWalletClient()
|
|
143
|
+
const { chainId: connectedChainId } = useAccount()
|
|
144
|
+
const chainId = useChainId()
|
|
145
|
+
const trailsClient = useTrailsClient()
|
|
146
|
+
const { trailsApiKey, sequenceIndexerUrl } = useTrails()
|
|
147
|
+
const {
|
|
148
|
+
openModal,
|
|
149
|
+
setPendingSelection,
|
|
150
|
+
setHostTransactionState,
|
|
151
|
+
setHostTransactionQuote,
|
|
152
|
+
setHostTransactionStates,
|
|
153
|
+
setHostTransactionTimestamp,
|
|
154
|
+
hostTransactionState,
|
|
155
|
+
setReceiptActionButtonText,
|
|
156
|
+
setOnReceiptAction,
|
|
157
|
+
retryTransactionRef,
|
|
158
|
+
} = useTrailsModal()
|
|
159
|
+
const indexerGatewayClient = useIndexerGatewayClient()
|
|
160
|
+
const { supportedTokens } = useSupportedTokens()
|
|
161
|
+
const commitIntentMutation = useCommitIntent()
|
|
162
|
+
const executeIntentMutation = useExecuteIntent()
|
|
163
|
+
|
|
164
|
+
// Store last transaction variables for retry
|
|
165
|
+
const lastTransactionVariablesRef =
|
|
166
|
+
useRef<TrailsSendTransactionVariables | null>(null)
|
|
167
|
+
|
|
168
|
+
const mergeHostTransactionState = useCallback(
|
|
169
|
+
(update: {
|
|
170
|
+
status?: HostTransactionStatus
|
|
171
|
+
details?: HostTransactionDetails | null
|
|
172
|
+
error?: string | null
|
|
173
|
+
result?: HostTransactionResultLinks | null
|
|
174
|
+
retryEnabled?: boolean
|
|
175
|
+
}) => {
|
|
176
|
+
setHostTransactionState((prev) => ({
|
|
177
|
+
status: update.status ?? prev.status,
|
|
178
|
+
details:
|
|
179
|
+
update.details === null
|
|
180
|
+
? undefined
|
|
181
|
+
: update.details
|
|
182
|
+
? { ...prev.details, ...update.details }
|
|
183
|
+
: prev.details,
|
|
184
|
+
error:
|
|
185
|
+
update.error === null
|
|
186
|
+
? undefined
|
|
187
|
+
: update.error !== undefined
|
|
188
|
+
? update.error
|
|
189
|
+
: prev.error,
|
|
190
|
+
result:
|
|
191
|
+
update.result === null
|
|
192
|
+
? undefined
|
|
193
|
+
: update.result
|
|
194
|
+
? { ...prev.result, ...update.result }
|
|
195
|
+
: prev.result,
|
|
196
|
+
retryEnabled:
|
|
197
|
+
update.retryEnabled !== undefined
|
|
198
|
+
? update.retryEnabled
|
|
199
|
+
: prev.retryEnabled,
|
|
200
|
+
}))
|
|
201
|
+
},
|
|
202
|
+
[setHostTransactionState],
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
// Extract transaction execution logic into a reusable function
|
|
206
|
+
const executeTransaction = async (
|
|
207
|
+
variables: TrailsSendTransactionVariables,
|
|
208
|
+
originSelection?: {
|
|
209
|
+
fromTokenAddress: string
|
|
210
|
+
fromChainId: number
|
|
211
|
+
fromAmount?: string
|
|
212
|
+
},
|
|
213
|
+
options?: { trackInWidget?: boolean },
|
|
214
|
+
): Promise<SwapReturn> => {
|
|
215
|
+
logger.console.log(
|
|
216
|
+
"[trails-sdk] [useTrailsSendTransaction] Executing transaction",
|
|
217
|
+
{ variables, originSelection },
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
// Validate required parameters
|
|
221
|
+
if (!walletClient || !walletClient.account) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
"Wallet client not available. Please connect your wallet.",
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!variables.to) {
|
|
228
|
+
throw new Error("Transaction 'to' address is required.")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Determine origin parameters
|
|
232
|
+
let fromTokenAddress: string
|
|
233
|
+
let fromChainId: number
|
|
234
|
+
let fromAmount: string | undefined
|
|
235
|
+
|
|
236
|
+
if (originSelection) {
|
|
237
|
+
// Use user-selected origin parameters (from modal)
|
|
238
|
+
fromTokenAddress = originSelection.fromTokenAddress
|
|
239
|
+
fromChainId = originSelection.fromChainId
|
|
240
|
+
fromAmount = originSelection.fromAmount
|
|
241
|
+
} else if (
|
|
242
|
+
variables.fromTokenAddress &&
|
|
243
|
+
variables.fromChainId &&
|
|
244
|
+
variables.fromAmount
|
|
245
|
+
) {
|
|
246
|
+
// Use explicitly provided ERC20 token origin parameters
|
|
247
|
+
fromTokenAddress = variables.fromTokenAddress
|
|
248
|
+
fromChainId = variables.fromChainId
|
|
249
|
+
fromAmount = variables.fromAmount
|
|
250
|
+
} else if (variables.to && variables.value !== undefined) {
|
|
251
|
+
// Simple native token send - use current chain
|
|
252
|
+
const currentChainId = connectedChainId || chainId
|
|
253
|
+
if (!currentChainId) {
|
|
254
|
+
throw new Error("Chain ID not available. Please connect your wallet.")
|
|
255
|
+
}
|
|
256
|
+
fromChainId = currentChainId
|
|
257
|
+
fromTokenAddress = zeroAddress
|
|
258
|
+
fromAmount = variables.value.toString()
|
|
259
|
+
} else {
|
|
260
|
+
throw new Error(
|
|
261
|
+
"Origin token parameters are required. Please provide 'value' (native token), or 'fromTokenAddress'/'fromChainId'/'fromAmount' (ERC20 token), or select via modal.",
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Determine destination parameters
|
|
266
|
+
const currentChainId = connectedChainId || chainId
|
|
267
|
+
if (!currentChainId) {
|
|
268
|
+
throw new Error("Chain ID not available. Please connect your wallet.")
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Use tokenAddress and tokenAmount if provided, otherwise infer from to/value
|
|
272
|
+
let toTokenAddress: string
|
|
273
|
+
let toChainId: number
|
|
274
|
+
let toAmount: string
|
|
275
|
+
let recipient: string
|
|
276
|
+
|
|
277
|
+
if (variables.tokenAddress && variables.tokenAmount) {
|
|
278
|
+
// Destination token requirements specified (e.g., AAVE deposit)
|
|
279
|
+
toTokenAddress = variables.tokenAddress
|
|
280
|
+
// Try to find the token's chainId from supportedTokens, fallback to current chain
|
|
281
|
+
const destToken = supportedTokens?.find(
|
|
282
|
+
(token) =>
|
|
283
|
+
token.contractAddress?.toLowerCase() ===
|
|
284
|
+
variables.tokenAddress?.toLowerCase(),
|
|
285
|
+
)
|
|
286
|
+
toChainId = destToken?.chainId ?? currentChainId
|
|
287
|
+
toAmount = variables.tokenAmount
|
|
288
|
+
recipient = variables.to
|
|
289
|
+
} else if (variables.to && variables.value !== undefined) {
|
|
290
|
+
// Simple native token send
|
|
291
|
+
toTokenAddress = zeroAddress
|
|
292
|
+
toChainId = currentChainId
|
|
293
|
+
toAmount = variables.value.toString()
|
|
294
|
+
recipient = variables.to
|
|
295
|
+
} else {
|
|
296
|
+
throw new Error(
|
|
297
|
+
"Either 'value' or 'tokenAddress'/'tokenAmount' must be provided.",
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Determine swap amount based on trade type
|
|
302
|
+
// If tokenAmount is provided, use EXACT_OUTPUT (we need exact amount of destination token)
|
|
303
|
+
// Otherwise, use EXACT_INPUT (we're sending exact amount from origin)
|
|
304
|
+
const tradeType =
|
|
305
|
+
variables.tokenAddress && variables.tokenAmount
|
|
306
|
+
? TradeType.EXACT_OUTPUT
|
|
307
|
+
: TradeType.EXACT_INPUT
|
|
308
|
+
if (tradeType === TradeType.EXACT_INPUT && !fromAmount) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
"Origin amount is required for this transaction. Please provide 'value' or 'fromAmount'.",
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const swapAmount =
|
|
315
|
+
tradeType === TradeType.EXACT_OUTPUT ? toAmount : fromAmount!
|
|
316
|
+
|
|
317
|
+
// Get token balances
|
|
318
|
+
let balances: any[] = []
|
|
319
|
+
try {
|
|
320
|
+
const result = await getTokenBalancesWithPrices({
|
|
321
|
+
account: walletClient.account.address,
|
|
322
|
+
indexerGatewayClient,
|
|
323
|
+
trailsClient,
|
|
324
|
+
})
|
|
325
|
+
balances = result.balances
|
|
326
|
+
} catch (balanceError) {
|
|
327
|
+
logger.console.warn(
|
|
328
|
+
"[trails-sdk] [useTrailsSendTransaction] Error fetching balances, proceeding with zero balance",
|
|
329
|
+
balanceError,
|
|
330
|
+
)
|
|
331
|
+
balances = []
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const originTokenBalance = balances.find(
|
|
335
|
+
(b) =>
|
|
336
|
+
b.chainId === fromChainId &&
|
|
337
|
+
(b.contractAddress?.toLowerCase() === fromTokenAddress?.toLowerCase() ||
|
|
338
|
+
(!b.contractAddress && fromTokenAddress === zeroAddress)),
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
342
|
+
|
|
343
|
+
// Get native token price for origin chain
|
|
344
|
+
let originNativeTokenPriceUsd = 0
|
|
345
|
+
try {
|
|
346
|
+
const originChain = getChainInfo(fromChainId)
|
|
347
|
+
const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
|
|
348
|
+
if (nativeTokenSymbol) {
|
|
349
|
+
const nativePrice = await getTokenPrice(trailsClient, {
|
|
350
|
+
tokenSymbol: nativeTokenSymbol,
|
|
351
|
+
tokenAddress: zeroAddress,
|
|
352
|
+
chainId: fromChainId,
|
|
353
|
+
})
|
|
354
|
+
originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
|
|
355
|
+
}
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger.console.warn(
|
|
358
|
+
"[trails-sdk] [useTrailsSendTransaction] Error getting native token price",
|
|
359
|
+
error,
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Get token info and decimals
|
|
364
|
+
const originToken = supportedTokens?.find(
|
|
365
|
+
(token) =>
|
|
366
|
+
token.contractAddress?.toLowerCase() ===
|
|
367
|
+
fromTokenAddress?.toLowerCase() && token.chainId === fromChainId,
|
|
368
|
+
)
|
|
369
|
+
const destinationToken = supportedTokens?.find(
|
|
370
|
+
(token) =>
|
|
371
|
+
token.contractAddress?.toLowerCase() ===
|
|
372
|
+
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
// Get RPC clients - we need to get them dynamically since we don't know chainIds until mutation
|
|
376
|
+
const { getChainRpcClient } = await import("../../chains.js")
|
|
377
|
+
const originPublicClient = getChainRpcClient(fromChainId)
|
|
378
|
+
const destinationPublicClient = getChainRpcClient(toChainId)
|
|
379
|
+
|
|
380
|
+
// Fetch decimals on-chain if not found
|
|
381
|
+
const fetchDecimalsOnChain = async (
|
|
382
|
+
tokenAddress: string,
|
|
383
|
+
chainId: number,
|
|
384
|
+
): Promise<number | null> => {
|
|
385
|
+
try {
|
|
386
|
+
const publicClient =
|
|
387
|
+
chainId === fromChainId
|
|
388
|
+
? originPublicClient
|
|
389
|
+
: chainId === toChainId
|
|
390
|
+
? destinationPublicClient
|
|
391
|
+
: getChainRpcClient(chainId)
|
|
392
|
+
|
|
393
|
+
if (!publicClient) {
|
|
394
|
+
return null
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (tokenAddress.toLowerCase() === zeroAddress.toLowerCase()) {
|
|
398
|
+
const chainInfo = getChainInfo(chainId)
|
|
399
|
+
return chainInfo?.nativeCurrency.decimals ?? 18
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const decimals = await publicClient.readContract({
|
|
403
|
+
address: tokenAddress as `0x${string}`,
|
|
404
|
+
abi: erc20Abi,
|
|
405
|
+
functionName: "decimals",
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
return decimals
|
|
409
|
+
} catch (error) {
|
|
410
|
+
logger.console.error(
|
|
411
|
+
`[trails-sdk] Error fetching decimals on-chain for token ${tokenAddress} on chain ${chainId}:`,
|
|
412
|
+
error,
|
|
413
|
+
)
|
|
414
|
+
return null
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let sourceTokenDecimals = originToken?.decimals
|
|
419
|
+
if (!sourceTokenDecimals && fromTokenAddress) {
|
|
420
|
+
const onChainDecimals = await fetchDecimalsOnChain(
|
|
421
|
+
fromTokenAddress,
|
|
422
|
+
fromChainId,
|
|
423
|
+
)
|
|
424
|
+
if (onChainDecimals !== null) {
|
|
425
|
+
sourceTokenDecimals = onChainDecimals
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (!sourceTokenDecimals) {
|
|
429
|
+
// Default to 18 for native/unknown
|
|
430
|
+
sourceTokenDecimals = 18
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
let destinationTokenDecimals = destinationToken?.decimals
|
|
434
|
+
if (!destinationTokenDecimals && toTokenAddress) {
|
|
435
|
+
const onChainDecimals = await fetchDecimalsOnChain(
|
|
436
|
+
toTokenAddress,
|
|
437
|
+
toChainId,
|
|
438
|
+
)
|
|
439
|
+
if (onChainDecimals !== null) {
|
|
440
|
+
destinationTokenDecimals = onChainDecimals
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (!destinationTokenDecimals) {
|
|
444
|
+
// Default to 18 for native/unknown
|
|
445
|
+
destinationTokenDecimals = 18
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const destinationTokenSymbol = destinationToken?.symbol ?? ""
|
|
449
|
+
const originTokenSymbol = originToken?.symbol ?? ""
|
|
450
|
+
|
|
451
|
+
const handleTransactionStateChange = (states: TransactionState[]) => {
|
|
452
|
+
if (options?.trackInWidget) {
|
|
453
|
+
setHostTransactionStates(states)
|
|
454
|
+
}
|
|
455
|
+
params?.onStatusUpdate?.(states)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Call prepareSend
|
|
459
|
+
const { send, quote } = await prepareSend({
|
|
460
|
+
account: walletClient.account,
|
|
461
|
+
originTokenAddress: fromTokenAddress,
|
|
462
|
+
originChainId: fromChainId,
|
|
463
|
+
originTokenBalance: originTokenBalanceAmount,
|
|
464
|
+
destinationChainId: toChainId,
|
|
465
|
+
recipient: recipient,
|
|
466
|
+
destinationTokenAddress: toTokenAddress,
|
|
467
|
+
swapAmount: swapAmount,
|
|
468
|
+
tradeType: tradeType,
|
|
469
|
+
originTokenSymbol: originTokenSymbol,
|
|
470
|
+
destinationTokenSymbol: destinationTokenSymbol,
|
|
471
|
+
fee: "0",
|
|
472
|
+
client: walletClient,
|
|
473
|
+
dryMode: false,
|
|
474
|
+
trailsClient,
|
|
475
|
+
destinationCalldata: variables.data
|
|
476
|
+
? variables.data.toString()
|
|
477
|
+
: undefined,
|
|
478
|
+
onTransactionStateChange: handleTransactionStateChange,
|
|
479
|
+
sourceTokenDecimals,
|
|
480
|
+
destinationTokenDecimals,
|
|
481
|
+
paymasterUrl: params?.paymasterUrl,
|
|
482
|
+
slippageTolerance: params?.slippageTolerance?.toString(),
|
|
483
|
+
originNativeTokenPriceUsd,
|
|
484
|
+
quoteProvider: params?.quoteProvider,
|
|
485
|
+
commitIntentFn: commitIntentMutation.mutateAsync,
|
|
486
|
+
executeIntentFn: executeIntentMutation.mutateAsync,
|
|
487
|
+
checkoutOnHandlers: params?.checkoutOnHandlers,
|
|
488
|
+
sequenceIndexerUrl,
|
|
489
|
+
sequenceProjectAccessKey: trailsApiKey,
|
|
490
|
+
originPublicClient: originPublicClient ?? undefined,
|
|
491
|
+
destinationPublicClient: destinationPublicClient ?? undefined,
|
|
492
|
+
isSmartWallet: params?.isSmartWallet ?? undefined,
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
if (options?.trackInWidget) {
|
|
496
|
+
setHostTransactionQuote(quote ?? null)
|
|
497
|
+
if (!hostTransactionState.details) {
|
|
498
|
+
mergeHostTransactionState({
|
|
499
|
+
details: {
|
|
500
|
+
to: recipient,
|
|
501
|
+
tokenAddress: toTokenAddress,
|
|
502
|
+
tokenAmount:
|
|
503
|
+
tradeType === TradeType.EXACT_OUTPUT ? toAmount : undefined,
|
|
504
|
+
toChainId,
|
|
505
|
+
data: variables.data,
|
|
506
|
+
},
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
if (
|
|
510
|
+
!hostTransactionState.status ||
|
|
511
|
+
hostTransactionState.status === "idle"
|
|
512
|
+
) {
|
|
513
|
+
setHostTransactionTimestamp(Date.now())
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Execute the swap
|
|
518
|
+
try {
|
|
519
|
+
// Reset retry flag when starting a new attempt
|
|
520
|
+
if (options?.trackInWidget) {
|
|
521
|
+
mergeHostTransactionState({ retryEnabled: false })
|
|
522
|
+
}
|
|
523
|
+
const {
|
|
524
|
+
depositUserTxnReceipt,
|
|
525
|
+
destinationIntentTransaction,
|
|
526
|
+
totalCompletionSeconds,
|
|
527
|
+
} = await send({
|
|
528
|
+
selectedFeeOption: null,
|
|
529
|
+
// Transition to "pending" when wallet signature is complete
|
|
530
|
+
onOriginSend: () => {
|
|
531
|
+
if (options?.trackInWidget) {
|
|
532
|
+
mergeHostTransactionState({ status: "pending", error: null })
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
if (options?.trackInWidget) {
|
|
538
|
+
mergeHostTransactionState({
|
|
539
|
+
status: "success",
|
|
540
|
+
result: {
|
|
541
|
+
originTxHash: depositUserTxnReceipt?.transactionHash,
|
|
542
|
+
originExplorerUrl: depositUserTxnReceipt?.transactionHash
|
|
543
|
+
? getExplorerUrl({
|
|
544
|
+
txHash: depositUserTxnReceipt.transactionHash,
|
|
545
|
+
chainId: fromChainId,
|
|
546
|
+
})
|
|
547
|
+
: undefined,
|
|
548
|
+
destinationTxHash: destinationIntentTransaction?.txnHash,
|
|
549
|
+
destinationExplorerUrl: destinationIntentTransaction?.txnHash
|
|
550
|
+
? getExplorerUrl({
|
|
551
|
+
txHash: destinationIntentTransaction.txnHash,
|
|
552
|
+
chainId: toChainId,
|
|
553
|
+
})
|
|
554
|
+
: undefined,
|
|
555
|
+
},
|
|
556
|
+
})
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return {
|
|
560
|
+
originTransaction: {
|
|
561
|
+
transactionHash: depositUserTxnReceipt?.transactionHash,
|
|
562
|
+
explorerUrl: getExplorerUrl({
|
|
563
|
+
txHash: depositUserTxnReceipt?.transactionHash as string,
|
|
564
|
+
chainId: fromChainId,
|
|
565
|
+
}),
|
|
566
|
+
receipt: depositUserTxnReceipt,
|
|
567
|
+
},
|
|
568
|
+
destinationTransaction: {
|
|
569
|
+
transactionHash: destinationIntentTransaction?.txnHash,
|
|
570
|
+
explorerUrl: getExplorerUrl({
|
|
571
|
+
txHash: destinationIntentTransaction?.txnHash as string,
|
|
572
|
+
chainId: toChainId,
|
|
573
|
+
}),
|
|
574
|
+
receipt: destinationIntentTransaction,
|
|
575
|
+
},
|
|
576
|
+
totalCompletionSeconds,
|
|
577
|
+
}
|
|
578
|
+
} catch (error) {
|
|
579
|
+
if (options?.trackInWidget) {
|
|
580
|
+
// For user rejection errors, stay on confirmation screen with retry enabled
|
|
581
|
+
const isUserRejection = getIsUserRejectionError(error)
|
|
582
|
+
if (isUserRejection) {
|
|
583
|
+
mergeHostTransactionState({
|
|
584
|
+
status: "confirmation",
|
|
585
|
+
error: null,
|
|
586
|
+
retryEnabled: true,
|
|
587
|
+
})
|
|
588
|
+
} else {
|
|
589
|
+
mergeHostTransactionState({
|
|
590
|
+
status: "error",
|
|
591
|
+
error: getFullErrorMessage(error as Error),
|
|
592
|
+
retryEnabled: false,
|
|
593
|
+
})
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
throw error
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
const mutation = useMutation({
|
|
601
|
+
mutationFn: async (
|
|
602
|
+
variables: TrailsSendTransactionVariables,
|
|
603
|
+
): Promise<SwapReturn> => {
|
|
604
|
+
logger.console.log(
|
|
605
|
+
"[trails-sdk] [useTrailsSendTransaction] Starting transaction",
|
|
606
|
+
variables,
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
// Set receipt customization from params
|
|
610
|
+
setReceiptActionButtonText(
|
|
611
|
+
params?.receiptActionButtonText ?? "Transact Again",
|
|
612
|
+
)
|
|
613
|
+
setOnReceiptAction(params?.onReceiptAction ?? null)
|
|
614
|
+
|
|
615
|
+
// Check if we have origin parameters specified
|
|
616
|
+
const hasNativeTokenOrigin = variables.value !== undefined
|
|
617
|
+
const hasERC20TokenOrigin =
|
|
618
|
+
variables.fromTokenAddress !== undefined &&
|
|
619
|
+
variables.fromChainId !== undefined
|
|
620
|
+
const hasOriginParams = hasNativeTokenOrigin || hasERC20TokenOrigin
|
|
621
|
+
|
|
622
|
+
// Determine destination chain ID
|
|
623
|
+
// Priority: token's chainId (from supportedTokens) > current chain
|
|
624
|
+
let destinationChainId: number | undefined
|
|
625
|
+
if (variables.tokenAddress && supportedTokens) {
|
|
626
|
+
// Find the token's chainId from supportedTokens
|
|
627
|
+
const destToken = supportedTokens.find(
|
|
628
|
+
(token) =>
|
|
629
|
+
token.contractAddress?.toLowerCase() ===
|
|
630
|
+
variables.tokenAddress?.toLowerCase(),
|
|
631
|
+
)
|
|
632
|
+
if (destToken) {
|
|
633
|
+
destinationChainId = destToken.chainId
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (!destinationChainId) {
|
|
637
|
+
destinationChainId = connectedChainId || chainId
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Check balances for origin and destination
|
|
641
|
+
let hasSufficientOriginBalance = true
|
|
642
|
+
let hasSufficientDestinationTokenBalance = true
|
|
643
|
+
|
|
644
|
+
if (walletClient?.account) {
|
|
645
|
+
try {
|
|
646
|
+
// Step 1: Check origin balance FIRST
|
|
647
|
+
// If origin is insufficient, user will need to select a different token via modal
|
|
648
|
+
if (hasOriginParams) {
|
|
649
|
+
let originTokenAddress: string | undefined
|
|
650
|
+
let originChainId: number | undefined
|
|
651
|
+
let originAmount: string | undefined
|
|
652
|
+
|
|
653
|
+
if (variables.value !== undefined) {
|
|
654
|
+
// Native token origin
|
|
655
|
+
originTokenAddress = zeroAddress
|
|
656
|
+
originChainId = connectedChainId || chainId || 1
|
|
657
|
+
originAmount = variables.value.toString()
|
|
658
|
+
} else if (variables.fromTokenAddress && variables.fromChainId) {
|
|
659
|
+
// ERC20 token origin (amount optional for EXACT_OUTPUT)
|
|
660
|
+
originTokenAddress = variables.fromTokenAddress
|
|
661
|
+
originChainId = variables.fromChainId
|
|
662
|
+
originAmount = variables.fromAmount
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (
|
|
666
|
+
originTokenAddress &&
|
|
667
|
+
originChainId &&
|
|
668
|
+
originAmount &&
|
|
669
|
+
originAmount !== "0"
|
|
670
|
+
) {
|
|
671
|
+
hasSufficientOriginBalance = await getHasSufficientBalanceToken({
|
|
672
|
+
account: walletClient.account.address,
|
|
673
|
+
token: originTokenAddress,
|
|
674
|
+
amount: originAmount,
|
|
675
|
+
chainId: originChainId,
|
|
676
|
+
indexerGatewayClient,
|
|
677
|
+
trailsClient,
|
|
678
|
+
})
|
|
679
|
+
logger.console.log(
|
|
680
|
+
"[trails-sdk] [useTrailsSendTransaction] Origin token balance check:",
|
|
681
|
+
{
|
|
682
|
+
tokenAddress: originTokenAddress,
|
|
683
|
+
amount: originAmount,
|
|
684
|
+
chainId: originChainId,
|
|
685
|
+
hasSufficientBalance: hasSufficientOriginBalance,
|
|
686
|
+
},
|
|
687
|
+
)
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Step 2: Only check destination token balance if origin is sufficient
|
|
692
|
+
// (otherwise user will open modal to select a different origin token)
|
|
693
|
+
if (
|
|
694
|
+
hasSufficientOriginBalance &&
|
|
695
|
+
variables.tokenAddress &&
|
|
696
|
+
variables.tokenAmount
|
|
697
|
+
) {
|
|
698
|
+
hasSufficientDestinationTokenBalance =
|
|
699
|
+
await getHasSufficientBalanceToken({
|
|
700
|
+
account: walletClient.account.address,
|
|
701
|
+
token: variables.tokenAddress,
|
|
702
|
+
amount: variables.tokenAmount,
|
|
703
|
+
chainId: destinationChainId,
|
|
704
|
+
indexerGatewayClient,
|
|
705
|
+
trailsClient,
|
|
706
|
+
})
|
|
707
|
+
logger.console.log(
|
|
708
|
+
"[trails-sdk] [useTrailsSendTransaction] Destination token balance check:",
|
|
709
|
+
{
|
|
710
|
+
tokenAddress: variables.tokenAddress,
|
|
711
|
+
tokenAmount: variables.tokenAmount,
|
|
712
|
+
chainId: destinationChainId,
|
|
713
|
+
hasSufficientBalance: hasSufficientDestinationTokenBalance,
|
|
714
|
+
},
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
// Step 3: Gas balance check will be done via QuoteIntent API in prepareSend
|
|
718
|
+
// The API provides comprehensive gas fee information including:
|
|
719
|
+
// - originGas: origin chain gas cost
|
|
720
|
+
// - destinationGas: destination chain gas cost (if applicable)
|
|
721
|
+
// - gasFeeOptions: fee options in different tokens
|
|
722
|
+
// If gas is insufficient, the system will fallback to gasless (handled in prepareSend)
|
|
723
|
+
}
|
|
724
|
+
} catch (balanceError) {
|
|
725
|
+
logger.console.warn(
|
|
726
|
+
"[trails-sdk] [useTrailsSendTransaction] Error checking balances, defaulting to origin selection:",
|
|
727
|
+
balanceError,
|
|
728
|
+
)
|
|
729
|
+
// If balance checks fail, default to opening modal (safe fallback)
|
|
730
|
+
hasSufficientOriginBalance = false
|
|
731
|
+
hasSufficientDestinationTokenBalance = false
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Determine if origin selection is needed
|
|
736
|
+
// Origin selection is needed when:
|
|
737
|
+
// 1. Origin parameters are not provided, OR
|
|
738
|
+
// 2. Origin balance is insufficient (user selected origin but doesn't have enough), OR
|
|
739
|
+
// 3. Destination token balance is insufficient (even if gas balance is sufficient)
|
|
740
|
+
// Note: Gas balance checks are done via QuoteIntent API after origin/destination are confirmed
|
|
741
|
+
const needsOriginSelection =
|
|
742
|
+
!hasOriginParams ||
|
|
743
|
+
!hasSufficientOriginBalance ||
|
|
744
|
+
!hasSufficientDestinationTokenBalance
|
|
745
|
+
|
|
746
|
+
logger.console.log(
|
|
747
|
+
"[trails-sdk] [useTrailsSendTransaction] Origin selection decision:",
|
|
748
|
+
{
|
|
749
|
+
hasOriginParams,
|
|
750
|
+
hasSufficientOriginBalance,
|
|
751
|
+
hasSufficientDestinationTokenBalance,
|
|
752
|
+
needsOriginSelection,
|
|
753
|
+
},
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
if (needsOriginSelection) {
|
|
757
|
+
const requireAmountInput = !(
|
|
758
|
+
variables.tokenAddress && variables.tokenAmount
|
|
759
|
+
)
|
|
760
|
+
const baseDetails: HostTransactionDetails = {
|
|
761
|
+
to: variables.to,
|
|
762
|
+
tokenAddress: variables.tokenAddress,
|
|
763
|
+
tokenAmount: variables.tokenAmount,
|
|
764
|
+
toChainId: destinationChainId,
|
|
765
|
+
data: variables.data,
|
|
766
|
+
}
|
|
767
|
+
mergeHostTransactionState({
|
|
768
|
+
status: "awaiting-origin",
|
|
769
|
+
details: baseDetails,
|
|
770
|
+
error: null,
|
|
771
|
+
result: null,
|
|
772
|
+
})
|
|
773
|
+
setHostTransactionQuote(null)
|
|
774
|
+
setHostTransactionStates([])
|
|
775
|
+
setHostTransactionTimestamp(Date.now())
|
|
776
|
+
// Open modal and wait for user selection
|
|
777
|
+
return new Promise<SwapReturn>((resolve, reject) => {
|
|
778
|
+
setPendingSelection({
|
|
779
|
+
resolve: async (selection) => {
|
|
780
|
+
try {
|
|
781
|
+
mergeHostTransactionState({ status: "confirmation" })
|
|
782
|
+
const result = await executeTransaction(variables, selection, {
|
|
783
|
+
trackInWidget: true,
|
|
784
|
+
})
|
|
785
|
+
resolve(result)
|
|
786
|
+
} catch (error) {
|
|
787
|
+
// Don't override state for user rejections - they're handled in executeTransaction
|
|
788
|
+
// and stay on confirmation screen with retry enabled
|
|
789
|
+
const isUserRejection = getIsUserRejectionError(error)
|
|
790
|
+
if (!isUserRejection) {
|
|
791
|
+
mergeHostTransactionState({
|
|
792
|
+
status: "error",
|
|
793
|
+
error: getFullErrorMessage(error as Error),
|
|
794
|
+
})
|
|
795
|
+
}
|
|
796
|
+
reject(error as Error)
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
reject: (error) => {
|
|
800
|
+
const rejection =
|
|
801
|
+
error instanceof Error ? error : new Error(String(error))
|
|
802
|
+
mergeHostTransactionState({
|
|
803
|
+
status: "error",
|
|
804
|
+
error: getFullErrorMessage(rejection),
|
|
805
|
+
})
|
|
806
|
+
reject(rejection)
|
|
807
|
+
},
|
|
808
|
+
requireAmountInput,
|
|
809
|
+
})
|
|
810
|
+
|
|
811
|
+
// Open the modal after setting pending selection
|
|
812
|
+
// Use setTimeout to ensure state updates are processed
|
|
813
|
+
setTimeout(() => {
|
|
814
|
+
logger.console.log(
|
|
815
|
+
"[trails-sdk] [useTrailsSendTransaction] Calling openModal()",
|
|
816
|
+
)
|
|
817
|
+
openModal()
|
|
818
|
+
}, 0)
|
|
819
|
+
})
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Set up modal for wallet-confirmation, pending, and receipt screens
|
|
823
|
+
const baseDetails: HostTransactionDetails = {
|
|
824
|
+
to: variables.to,
|
|
825
|
+
tokenAddress: variables.tokenAddress,
|
|
826
|
+
tokenAmount: variables.tokenAmount,
|
|
827
|
+
toChainId: destinationChainId,
|
|
828
|
+
data: variables.data,
|
|
829
|
+
}
|
|
830
|
+
mergeHostTransactionState({
|
|
831
|
+
status: "confirmation",
|
|
832
|
+
details: baseDetails,
|
|
833
|
+
error: null,
|
|
834
|
+
result: null,
|
|
835
|
+
})
|
|
836
|
+
setHostTransactionQuote(null)
|
|
837
|
+
setHostTransactionStates([])
|
|
838
|
+
setHostTransactionTimestamp(Date.now())
|
|
839
|
+
openModal()
|
|
840
|
+
|
|
841
|
+
// Execute transaction directly with modal tracking
|
|
842
|
+
return executeTransaction(variables, undefined, { trackInWidget: true })
|
|
843
|
+
},
|
|
844
|
+
onSuccess: (data, variables) => {
|
|
845
|
+
logger.console.log(
|
|
846
|
+
"[trails-sdk] [useTrailsSendTransaction] Transaction successful",
|
|
847
|
+
{ data, variables },
|
|
848
|
+
)
|
|
849
|
+
params?.onSuccess?.(data, variables)
|
|
850
|
+
},
|
|
851
|
+
onError: (error, variables) => {
|
|
852
|
+
logger.console.error(
|
|
853
|
+
"[trails-sdk] [useTrailsSendTransaction] Transaction error",
|
|
854
|
+
{ error, variables },
|
|
855
|
+
)
|
|
856
|
+
const errorMessage = getFullErrorMessage(error)
|
|
857
|
+
// Don't override state for user rejections - they're handled in executeTransaction
|
|
858
|
+
// and stay on confirmation screen with retry enabled
|
|
859
|
+
const isUserRejection = getIsUserRejectionError(error)
|
|
860
|
+
if (hostTransactionState.status !== "idle" && !isUserRejection) {
|
|
861
|
+
mergeHostTransactionState({
|
|
862
|
+
status: "error",
|
|
863
|
+
error: errorMessage,
|
|
864
|
+
})
|
|
865
|
+
}
|
|
866
|
+
params?.onError?.(new Error(errorMessage), variables)
|
|
867
|
+
},
|
|
868
|
+
onSettled: (data, error, variables) => {
|
|
869
|
+
logger.console.log(
|
|
870
|
+
"[trails-sdk] [useTrailsSendTransaction] Transaction settled",
|
|
871
|
+
{ data, error, variables },
|
|
872
|
+
)
|
|
873
|
+
params?.onSettled?.(data, error as Error | null, variables)
|
|
874
|
+
},
|
|
875
|
+
})
|
|
876
|
+
|
|
877
|
+
const sendTransaction = useCallback(
|
|
878
|
+
(
|
|
879
|
+
variables: TrailsSendTransactionVariables,
|
|
880
|
+
callbacks?: {
|
|
881
|
+
onSuccess?: (data: SwapReturn) => void
|
|
882
|
+
onError?: (error: Error) => void
|
|
883
|
+
onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
|
|
884
|
+
},
|
|
885
|
+
) => {
|
|
886
|
+
mutation.mutate(variables, {
|
|
887
|
+
onSuccess: (data) => {
|
|
888
|
+
callbacks?.onSuccess?.(data)
|
|
889
|
+
},
|
|
890
|
+
onError: (error) => {
|
|
891
|
+
callbacks?.onError?.(error as Error)
|
|
892
|
+
},
|
|
893
|
+
onSettled: (data, error) => {
|
|
894
|
+
callbacks?.onSettled?.(data, error as Error | null)
|
|
895
|
+
},
|
|
896
|
+
})
|
|
897
|
+
},
|
|
898
|
+
[mutation],
|
|
899
|
+
)
|
|
900
|
+
|
|
901
|
+
const sendTransactionAsync = useCallback(
|
|
902
|
+
async (
|
|
903
|
+
variables: TrailsSendTransactionVariables,
|
|
904
|
+
callbacks?: {
|
|
905
|
+
onSuccess?: (data: SwapReturn) => void
|
|
906
|
+
onError?: (error: Error) => void
|
|
907
|
+
onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
|
|
908
|
+
},
|
|
909
|
+
): Promise<SwapReturn> => {
|
|
910
|
+
return mutation.mutateAsync(variables, {
|
|
911
|
+
onSuccess: (data) => {
|
|
912
|
+
callbacks?.onSuccess?.(data)
|
|
913
|
+
},
|
|
914
|
+
onError: (error) => {
|
|
915
|
+
callbacks?.onError?.(error as Error)
|
|
916
|
+
},
|
|
917
|
+
onSettled: (data, error) => {
|
|
918
|
+
callbacks?.onSettled?.(data, error as Error | null)
|
|
919
|
+
},
|
|
920
|
+
})
|
|
921
|
+
},
|
|
922
|
+
[mutation],
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
// Retry function that re-executes with last variables
|
|
926
|
+
const retry = useCallback(() => {
|
|
927
|
+
if (lastTransactionVariablesRef.current) {
|
|
928
|
+
sendTransaction(lastTransactionVariablesRef.current)
|
|
929
|
+
}
|
|
930
|
+
}, [sendTransaction])
|
|
931
|
+
|
|
932
|
+
// Store retry function in ref so widget can call it (using ref to avoid re-renders)
|
|
933
|
+
retryTransactionRef.current = retry
|
|
934
|
+
|
|
935
|
+
return {
|
|
936
|
+
sendTransaction,
|
|
937
|
+
sendTransactionAsync,
|
|
938
|
+
retry,
|
|
939
|
+
data: mutation.data,
|
|
940
|
+
error: mutation.error as Error | null,
|
|
941
|
+
isPending: mutation.isPending,
|
|
942
|
+
isSuccess: mutation.isSuccess,
|
|
943
|
+
isError: mutation.isError,
|
|
944
|
+
isIdle: mutation.isIdle,
|
|
945
|
+
status: mutation.status,
|
|
946
|
+
reset: mutation.reset,
|
|
947
|
+
variables: mutation.variables,
|
|
948
|
+
}
|
|
949
|
+
}
|