0xtrails 0.13.1 → 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-DStzFCYT.js → ccip-CT_An6eM.js} +28 -28
- package/dist/chains.d.ts +1 -1
- 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/{index-HY9_ppit.js → index-RfqL5Foz.js} +56523 -43196
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +383 -332
- 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/prepareSend.d.ts.map +1 -1
- package/dist/query/balance.fetchers.d.ts +27 -0
- package/dist/query/balance.fetchers.d.ts.map +1 -1
- package/dist/query/balance.hooks.d.ts +19 -0
- 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/tokenList.queries.d.ts +54 -0
- package/dist/query/tokenList.queries.d.ts.map +1 -0
- package/dist/recover.d.ts +3 -1
- 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 +3 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/umd/trails.min.js +291 -202
- 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/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/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.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/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.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/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/TransferPendingVertical.d.ts +1 -0
- package/dist/widget/components/TransferPendingVertical.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/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/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +1 -1
- 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.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/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/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 +9 -4
- package/src/constants.ts +2 -0
- package/src/customTokens.ts +21 -0
- package/src/index.ts +1 -0
- package/src/intents.ts +49 -41
- 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/prepareSend.ts +45 -44
- package/src/query/balance.fetchers.ts +134 -4
- package/src/query/balance.hooks.ts +61 -2
- 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/tokenList.queries.ts +118 -0
- package/src/recover.ts +86 -23
- package/src/tokens.ts +108 -26
- package/src/transactionIntent/deposits/depositOrchestrator.ts +11 -11
- package/src/transactionIntent/deposits/gaslessDeposit.ts +38 -38
- package/src/transactionIntent/deposits/standardDeposit.ts +0 -4
- package/src/transactionIntent/handlers/intentHandler.ts +28 -11
- 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 +3 -0
- package/src/walletUtils.ts +2 -1
- package/src/wallets.ts +184 -380
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/ClassicSwap.tsx +22 -5
- 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/Fund.tsx +144 -12
- package/src/widget/components/FundMethods.tsx +5 -9
- package/src/widget/components/MeldHistory.tsx +1 -1
- package/src/widget/components/MeshExchangeSelection.tsx +218 -0
- package/src/widget/components/OnrampHistoryRow.tsx +1 -1
- package/src/widget/components/Pay.tsx +20 -36
- package/src/widget/components/PoolDeposit.tsx +13 -22
- package/src/widget/components/QRCodeWalletSelect.tsx +5 -2
- package/src/widget/components/QuoteDetails.tsx +77 -68
- package/src/widget/components/Recipients.tsx +2 -1
- package/src/widget/components/RefundWarning.tsx +5 -10
- package/src/widget/components/TokenSelector.tsx +85 -16
- package/src/widget/components/TransactionDetails.tsx +46 -0
- package/src/widget/components/TransferPendingVertical.tsx +27 -19
- 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 -4
- package/src/widget/hooks/useAddressWalletIcon.ts +2 -1
- 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/useIntentTransactionHistory.ts +5 -0
- package/src/widget/hooks/useMeldTransactionStatus.ts +1 -1
- package/src/widget/hooks/useQuote.ts +51 -45
- package/src/widget/hooks/useSelectedFundMethod.tsx +14 -1
- package/src/widget/hooks/useSendForm.ts +26 -10
- package/src/widget/hooks/useTokenList.ts +208 -139
- 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/meldProviderUtils.ts +8 -2
- package/src/widget/utils/meshSupportedTokens.ts +28 -0
- package/src/widget/utils/onrampConfig.ts +15 -0
- package/src/widget/utils/trailsOnrampConfig.ts +39 -0
- package/src/widget/widget.tsx +164 -98
- 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/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/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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query"
|
|
1
2
|
import { ArrowLeftRight } from "lucide-react"
|
|
2
3
|
import type React from "react"
|
|
3
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
|
@@ -17,6 +18,9 @@ import { useSupportedTokens, type Token } from "../../tokens.js"
|
|
|
17
18
|
import type { FundMethod } from "../../transactionIntent/types.js"
|
|
18
19
|
import { isPassthroughEligible } from "../../utils/passthrough.js"
|
|
19
20
|
import { useWidgetProps } from "../hooks/useWidgetProps.js"
|
|
21
|
+
import { getMatchingMeshSupportedTokens } from "../utils/meshSupportedTokens.js"
|
|
22
|
+
import { getActiveMeshEnvironment } from "../utils/onrampConfig.js"
|
|
23
|
+
import { getWidgetOnrampConfig } from "../utils/trailsOnrampConfig.js"
|
|
20
24
|
import type { Screen } from "../hooks/useViewManager.js"
|
|
21
25
|
import { useViewManager } from "../hooks/useViewManager.js"
|
|
22
26
|
import { useDefaultDestinationToken } from "../hooks/useDefaultDestinationToken.js"
|
|
@@ -33,9 +37,9 @@ import { useOriginSelectedToken } from "../hooks/useOriginSelectedToken.js"
|
|
|
33
37
|
import type { ProcessedFeeOption } from "../hooks/useSelectedFeeOption.js"
|
|
34
38
|
import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
|
|
35
39
|
import { useSelectedRecipient } from "../hooks/useSelectedRecipient.js"
|
|
36
|
-
import { useSendForm } from "../hooks/useSendForm.js"
|
|
40
|
+
import { useSendForm, type OnCompleteProps } from "../hooks/useSendForm.js"
|
|
37
41
|
import { useSwapState } from "../hooks/useSwapState.js"
|
|
38
|
-
import {
|
|
42
|
+
import { useAccountTokenBalanceOnchain } from "../../query/balance.hooks.js"
|
|
39
43
|
import type { BaseProps, OnrampConfirmCallback } from "../types/commonProps.js"
|
|
40
44
|
import { isWithinCooldown, SECOND_MS } from "../../utils/time.js"
|
|
41
45
|
import { forexRateStore } from "../utils/forexRateStore.js"
|
|
@@ -58,6 +62,7 @@ import { TokenSelectorButton } from "./TokenSelectorButton.js"
|
|
|
58
62
|
import LoadingSpinner from "./LoadingSpinner.js"
|
|
59
63
|
|
|
60
64
|
import { addressEqual } from "../../utils/address.js"
|
|
65
|
+
import { useOnrampClient } from "../../onrampClient.js"
|
|
61
66
|
interface FundProps extends BaseProps {
|
|
62
67
|
onWaitingForOnrampConfirm?: OnrampConfirmCallback
|
|
63
68
|
title?: string
|
|
@@ -102,7 +107,14 @@ const Fund: React.FC<FundProps> = ({
|
|
|
102
107
|
defaultInputMode,
|
|
103
108
|
}) => {
|
|
104
109
|
const { mode, navigate } = useViewManager()
|
|
105
|
-
const
|
|
110
|
+
const widgetProps = useWidgetProps()
|
|
111
|
+
const {
|
|
112
|
+
fundOptions,
|
|
113
|
+
onramp: onrampFactory,
|
|
114
|
+
apiKey,
|
|
115
|
+
trailsApiUrl,
|
|
116
|
+
} = widgetProps
|
|
117
|
+
const onrampClient = useOnrampClient()
|
|
106
118
|
const {
|
|
107
119
|
selectedToken: originToken,
|
|
108
120
|
setSelectedToken: setOriginToken,
|
|
@@ -116,7 +128,21 @@ const Fund: React.FC<FundProps> = ({
|
|
|
116
128
|
setHasManualSelection: setHasManualDestinationSelection,
|
|
117
129
|
isControlledByProps: isDestinationControlledByProps,
|
|
118
130
|
} = useDestinationSelectedToken()
|
|
119
|
-
const { paymentMethod } = useSelectedFundMethod()
|
|
131
|
+
const { paymentMethod, selectedMeshExchange } = useSelectedFundMethod()
|
|
132
|
+
const meshOnrampConfig = getWidgetOnrampConfig(onrampFactory)
|
|
133
|
+
const meshEnvironment = getActiveMeshEnvironment(meshOnrampConfig)
|
|
134
|
+
const meshEnabled = !!meshOnrampConfig?.mesh
|
|
135
|
+
const meshAllowedExchanges = meshOnrampConfig?.mesh?.exchanges ?? null
|
|
136
|
+
const activeMeshIntegrationIds = selectedMeshExchange
|
|
137
|
+
? [selectedMeshExchange.integrationId]
|
|
138
|
+
: null
|
|
139
|
+
const activeMeshExchangeKeys = selectedMeshExchange
|
|
140
|
+
? null
|
|
141
|
+
: meshAllowedExchanges
|
|
142
|
+
const isCoinbaseMeshOnramp =
|
|
143
|
+
fundMethod === "onramp-mesh" &&
|
|
144
|
+
(selectedMeshExchange?.exchangeKey === "coinbase" ||
|
|
145
|
+
selectedMeshExchange?.exchangeKey === "coinbaseRamp")
|
|
120
146
|
|
|
121
147
|
// Check if fee options will be shown (not needed for onramp/direct-transfer modes)
|
|
122
148
|
const skipFeeBalanceFetch =
|
|
@@ -129,11 +155,9 @@ const Fund: React.FC<FundProps> = ({
|
|
|
129
155
|
const {
|
|
130
156
|
token: freshOriginToken,
|
|
131
157
|
isLoadingBalance: isLoadingFreshOriginBalance,
|
|
132
|
-
} =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
skipFeeBalanceFetch,
|
|
136
|
-
)
|
|
158
|
+
} = useAccountTokenBalanceOnchain(originToken, account?.address, {
|
|
159
|
+
disabled: skipFeeBalanceFetch,
|
|
160
|
+
})
|
|
137
161
|
|
|
138
162
|
const { selectedRecipient, setSelectedRecipient } = useSelectedRecipient()
|
|
139
163
|
const {
|
|
@@ -179,6 +203,14 @@ const Fund: React.FC<FundProps> = ({
|
|
|
179
203
|
const [isUserTyping, setIsUserTyping] = useState(false)
|
|
180
204
|
const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
181
205
|
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
return () => {
|
|
208
|
+
if (typingTimeoutRef.current) {
|
|
209
|
+
clearTimeout(typingTimeoutRef.current)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}, [])
|
|
213
|
+
|
|
182
214
|
// Get country defaults when onramp is active
|
|
183
215
|
const {
|
|
184
216
|
countryCode: detectedCountryCode,
|
|
@@ -314,6 +346,7 @@ const Fund: React.FC<FundProps> = ({
|
|
|
314
346
|
setSellAmount,
|
|
315
347
|
buyAmount,
|
|
316
348
|
setBuyAmount,
|
|
349
|
+
resetSwapState,
|
|
317
350
|
enterFormMode,
|
|
318
351
|
} = useSwapState()
|
|
319
352
|
|
|
@@ -351,6 +384,16 @@ const Fund: React.FC<FundProps> = ({
|
|
|
351
384
|
const [isCreatingWidgetSession, setIsCreatingWidgetSession] = useState(false)
|
|
352
385
|
const [widgetError, setWidgetError] = useState<string | null>(null)
|
|
353
386
|
|
|
387
|
+
const handleCompleteAndClearAmounts = useCallback(
|
|
388
|
+
(result: OnCompleteProps) => {
|
|
389
|
+
setInputDisplayValue("")
|
|
390
|
+
setSellFiatAmount("")
|
|
391
|
+
resetSwapState()
|
|
392
|
+
onComplete(result)
|
|
393
|
+
},
|
|
394
|
+
[onComplete, resetSwapState, setSellFiatAmount],
|
|
395
|
+
)
|
|
396
|
+
|
|
354
397
|
// Initialize and update selected recipient from toRecipient prop (but don't auto-set to account address)
|
|
355
398
|
// biome-ignore lint/correctness/useExhaustiveDependencies: selectedRecipient is intentionally excluded to avoid infinite loops
|
|
356
399
|
useEffect(() => {
|
|
@@ -462,7 +505,7 @@ const Fund: React.FC<FundProps> = ({
|
|
|
462
505
|
paymasterUrls,
|
|
463
506
|
onSend,
|
|
464
507
|
onConfirm,
|
|
465
|
-
onComplete,
|
|
508
|
+
onComplete: handleCompleteAndClearAmounts,
|
|
466
509
|
selectedToken: effectiveOriginToken as any,
|
|
467
510
|
setWalletConfirmRetryHandler,
|
|
468
511
|
tradeType: tradeType,
|
|
@@ -489,6 +532,60 @@ const Fund: React.FC<FundProps> = ({
|
|
|
489
532
|
: undefined,
|
|
490
533
|
})
|
|
491
534
|
|
|
535
|
+
const {
|
|
536
|
+
data: isMeshRouteSupported = true,
|
|
537
|
+
isLoading: isLoadingMeshRouteSupport,
|
|
538
|
+
} = useQuery({
|
|
539
|
+
queryKey: [
|
|
540
|
+
"mesh-route-support",
|
|
541
|
+
meshEnvironment,
|
|
542
|
+
activeMeshExchangeKeys,
|
|
543
|
+
prepareSendQuote?.originChain?.id,
|
|
544
|
+
prepareSendQuote?.originToken?.symbol,
|
|
545
|
+
trailsApiUrl,
|
|
546
|
+
apiKey,
|
|
547
|
+
],
|
|
548
|
+
queryFn: async () => {
|
|
549
|
+
const response = await onrampClient.getMeshSupportedTokens({
|
|
550
|
+
environment: meshEnvironment,
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
const allowedTokens = !activeMeshExchangeKeys?.length
|
|
554
|
+
? !activeMeshIntegrationIds?.length
|
|
555
|
+
? response.tokens || []
|
|
556
|
+
: (response.tokens || []).filter((token) =>
|
|
557
|
+
(token.integrationIds || []).some((integrationId) =>
|
|
558
|
+
activeMeshIntegrationIds.includes(integrationId),
|
|
559
|
+
),
|
|
560
|
+
)
|
|
561
|
+
: (response.tokens || []).filter((token) =>
|
|
562
|
+
(token.exchangeKeys || []).some((exchangeKey) =>
|
|
563
|
+
activeMeshExchangeKeys.includes(exchangeKey),
|
|
564
|
+
),
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
return (
|
|
568
|
+
getMatchingMeshSupportedTokens(
|
|
569
|
+
allowedTokens,
|
|
570
|
+
prepareSendQuote?.originChain?.id,
|
|
571
|
+
prepareSendQuote?.originToken?.symbol,
|
|
572
|
+
).length > 0
|
|
573
|
+
)
|
|
574
|
+
},
|
|
575
|
+
enabled:
|
|
576
|
+
fundMethod === "onramp-mesh" &&
|
|
577
|
+
meshEnabled &&
|
|
578
|
+
!!prepareSendQuote?.originChain?.id &&
|
|
579
|
+
!!prepareSendQuote?.originToken?.symbol &&
|
|
580
|
+
!!apiKey &&
|
|
581
|
+
!!trailsApiUrl,
|
|
582
|
+
staleTime: 24 * 60 * 60 * 1000,
|
|
583
|
+
gcTime: 24 * 60 * 60 * 1000,
|
|
584
|
+
refetchOnMount: false,
|
|
585
|
+
refetchOnWindowFocus: false,
|
|
586
|
+
refetchOnReconnect: false,
|
|
587
|
+
})
|
|
588
|
+
|
|
492
589
|
const selectedOnrampProviderQuote =
|
|
493
590
|
selectedOnrampProvider || autoSelectedOnrampQuote
|
|
494
591
|
|
|
@@ -705,8 +802,7 @@ const Fund: React.FC<FundProps> = ({
|
|
|
705
802
|
useState(false)
|
|
706
803
|
|
|
707
804
|
const { supportedTokens } = useSupportedTokens({
|
|
708
|
-
disabled:
|
|
709
|
-
!!toToken || showSourceTokenSelector || showDestinationTokenSelector,
|
|
805
|
+
disabled: !toToken,
|
|
710
806
|
})
|
|
711
807
|
|
|
712
808
|
// Use a ref to track if we've already auto-selected from toToken prop
|
|
@@ -890,9 +986,33 @@ const Fund: React.FC<FundProps> = ({
|
|
|
890
986
|
setHasManualOriginSelection,
|
|
891
987
|
])
|
|
892
988
|
|
|
989
|
+
useEffect(() => {
|
|
990
|
+
if (hasManualOriginSelection || !isCoinbaseMeshOnramp) {
|
|
991
|
+
return
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
const isUsdcBaseSelected =
|
|
995
|
+
!!originToken &&
|
|
996
|
+
originToken.chainId === USDC_BASE.chainId &&
|
|
997
|
+
addressEqual(originToken.contractAddress, USDC_BASE.contractAddress)
|
|
998
|
+
|
|
999
|
+
if (!isUsdcBaseSelected) {
|
|
1000
|
+
logger.console.log(
|
|
1001
|
+
"[Fund] Preselecting USDC on Base for Coinbase Mesh onramp",
|
|
1002
|
+
)
|
|
1003
|
+
setOriginToken(USDC_BASE as Token)
|
|
1004
|
+
}
|
|
1005
|
+
}, [
|
|
1006
|
+
hasManualOriginSelection,
|
|
1007
|
+
isCoinbaseMeshOnramp,
|
|
1008
|
+
originToken,
|
|
1009
|
+
setOriginToken,
|
|
1010
|
+
])
|
|
1011
|
+
|
|
893
1012
|
// Auto-select origin token using separated hook
|
|
894
1013
|
useEffect(() => {
|
|
895
1014
|
if (
|
|
1015
|
+
fundMethod !== "onramp-mesh" &&
|
|
896
1016
|
!originToken &&
|
|
897
1017
|
!isLoadingOriginDefaults &&
|
|
898
1018
|
defaultOriginToken &&
|
|
@@ -910,6 +1030,7 @@ const Fund: React.FC<FundProps> = ({
|
|
|
910
1030
|
defaultOriginToken,
|
|
911
1031
|
setOriginToken,
|
|
912
1032
|
hasManualOriginSelection,
|
|
1033
|
+
fundMethod,
|
|
913
1034
|
])
|
|
914
1035
|
|
|
915
1036
|
// Auto-select destination token using separated hook
|
|
@@ -2258,6 +2379,8 @@ const Fund: React.FC<FundProps> = ({
|
|
|
2258
2379
|
!isValidCustomToken ||
|
|
2259
2380
|
isLoadingQuote ||
|
|
2260
2381
|
!prepareSendQuote ||
|
|
2382
|
+
(fundMethod === "onramp-mesh" &&
|
|
2383
|
+
(isLoadingMeshRouteSupport || !isMeshRouteSupported)) ||
|
|
2261
2384
|
(!isMeldOnRampActive &&
|
|
2262
2385
|
fundMethod !== "direct-transfer" &&
|
|
2263
2386
|
prepareSendQuote?.noSufficientBalance) ||
|
|
@@ -2295,6 +2418,15 @@ const Fund: React.FC<FundProps> = ({
|
|
|
2295
2418
|
) : fundMethod !== "direct-transfer" &&
|
|
2296
2419
|
prepareSendQuote?.noSufficientBalance ? (
|
|
2297
2420
|
"Insufficient Balance"
|
|
2421
|
+
) : fundMethod === "onramp-mesh" && isLoadingMeshRouteSupport ? (
|
|
2422
|
+
<div className="flex items-center justify-center">
|
|
2423
|
+
<LoadingSpinner className="mr-2" />
|
|
2424
|
+
<span>Checking exchange funding...</span>
|
|
2425
|
+
</div>
|
|
2426
|
+
) : fundMethod === "onramp-mesh" &&
|
|
2427
|
+
prepareSendQuote &&
|
|
2428
|
+
!isMeshRouteSupported ? (
|
|
2429
|
+
"Exchange funding unavailable"
|
|
2298
2430
|
) : isMeldOnRampActive && !sellFiatAmount ? (
|
|
2299
2431
|
"Enter amount"
|
|
2300
2432
|
) : !isMeldOnRampActive && !sellAmount ? (
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type React from "react"
|
|
2
2
|
import { ChevronRight, CreditCard, Wallet, ZapIcon } from "lucide-react"
|
|
3
|
+
import { wagmiConnectorToWalletId } from "@0xtrails/wallet-registry"
|
|
3
4
|
import { useAccount, useConnections, useSwitchAccount } from "wagmi"
|
|
4
5
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
5
6
|
import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
|
|
6
7
|
import { useViewManager } from "../hooks/useViewManager.js"
|
|
7
8
|
import { useWalletConnectionContext } from "../hooks/useWalletConnectionContext.js"
|
|
8
|
-
import { useWallets
|
|
9
|
+
import { useWallets } from "../../wallets.js"
|
|
9
10
|
import ExchangeIcon from "../assets/Exchange-icon-black.svg"
|
|
10
11
|
import WalletChange from "../assets/WalletChange-black.svg"
|
|
11
12
|
import { truncateAddress } from "../../utils/address.js"
|
|
12
13
|
import { useResolveEns } from "../../ens.js"
|
|
13
14
|
import { AddressWalletIcon } from "./AddressWalletIcon.js"
|
|
14
15
|
import { useWidgetProps } from "../hooks/useWidgetProps.js"
|
|
15
|
-
import { useAccountTotalBalanceUsd } from "../../query/balance.hooks.js"
|
|
16
16
|
import type { FundMethod } from "../../transactionIntent/types.js"
|
|
17
17
|
import type { FundMethodListOption } from "../widget.js"
|
|
18
18
|
|
|
@@ -107,17 +107,13 @@ const FundMethods: React.FC<FundMethodsProps> = ({
|
|
|
107
107
|
eligibleConnectedWallets.find((wallet) => wallet.isActive) ||
|
|
108
108
|
eligibleConnectedWallets[0]
|
|
109
109
|
|
|
110
|
-
const
|
|
111
|
-
activeConnection?.address || null,
|
|
112
|
-
)
|
|
113
|
-
const hasActiveWalletBalance = activeWalletBalanceUsd > 0
|
|
114
|
-
|
|
115
|
-
const showWalletInline = !!activeConnection && hasActiveWalletBalance
|
|
110
|
+
const showWalletInline = !!activeConnection
|
|
116
111
|
|
|
117
112
|
const fundMethodAliases: Record<FundMethodListOption, FundMethod> = {
|
|
118
113
|
"connected-wallet": "wallet",
|
|
119
114
|
"crypto-transfer": "direct-transfer",
|
|
120
115
|
"cc-onramp": "onramp-meld",
|
|
116
|
+
exchange: "onramp-mesh",
|
|
121
117
|
"exchange-onramp": "onramp-mesh",
|
|
122
118
|
}
|
|
123
119
|
|
|
@@ -170,7 +166,7 @@ const FundMethods: React.FC<FundMethodsProps> = ({
|
|
|
170
166
|
listedInternalSet.size > 0 &&
|
|
171
167
|
!listedInternalSet.has(method)
|
|
172
168
|
|
|
173
|
-
const displayMeshExchange = !!onramp
|
|
169
|
+
const displayMeshExchange = !!onramp
|
|
174
170
|
|
|
175
171
|
const renderFundMethod = (method: FundMethod) => {
|
|
176
172
|
const forceDisabled = isUnlisted(method)
|
|
@@ -6,7 +6,7 @@ import { isValidNumber } from "../../utils/validation.js"
|
|
|
6
6
|
import { getChainName } from "../../chains.js"
|
|
7
7
|
import { logger } from "../../logger.js"
|
|
8
8
|
import { useMeldServiceProviders } from "../../query/meld.hooks.js"
|
|
9
|
-
import type { MeldServiceProvider } from "
|
|
9
|
+
import type { MeldServiceProvider } from "@0xtrails/api/onramp"
|
|
10
10
|
import { SECOND_MS, formatRelativeDate } from "../../utils/time.js"
|
|
11
11
|
import {
|
|
12
12
|
useMeldTransactionHistory,
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query"
|
|
2
|
+
import { ChevronRight } from "lucide-react"
|
|
3
|
+
import type React from "react"
|
|
4
|
+
import { useState } from "react"
|
|
5
|
+
import { useOnrampClient } from "../../onrampClient.js"
|
|
6
|
+
import { logger } from "../../logger.js"
|
|
7
|
+
import { ScreenHeader } from "./ScreenHeader.js"
|
|
8
|
+
import { useWidgetProps } from "../hooks/useWidgetProps.js"
|
|
9
|
+
import { getActiveMeshEnvironment } from "../utils/onrampConfig.js"
|
|
10
|
+
import { getWidgetOnrampConfig } from "../utils/trailsOnrampConfig.js"
|
|
11
|
+
|
|
12
|
+
const INITIAL_VISIBLE_EXCHANGES = 3
|
|
13
|
+
|
|
14
|
+
export interface MeshExchangeSelectionProps {
|
|
15
|
+
onBack: () => void
|
|
16
|
+
onSelectExchange: (exchange: {
|
|
17
|
+
integrationId: string
|
|
18
|
+
exchangeKey: string
|
|
19
|
+
exchangeName: string
|
|
20
|
+
}) => void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getExchangeBackgroundClassName(exchangeKey: string): string {
|
|
24
|
+
switch (exchangeKey) {
|
|
25
|
+
case "coinbase":
|
|
26
|
+
case "coinbaseRamp":
|
|
27
|
+
case "sandboxCoinbase":
|
|
28
|
+
return "bg-white"
|
|
29
|
+
case "binanceInternational":
|
|
30
|
+
case "binanceInternationalDirect":
|
|
31
|
+
case "binanceUs":
|
|
32
|
+
case "binanceUsDirect":
|
|
33
|
+
case "sandbox":
|
|
34
|
+
case "binanceConnect":
|
|
35
|
+
return "bg-black"
|
|
36
|
+
case "bitfinex":
|
|
37
|
+
case "bitfinexDirect":
|
|
38
|
+
return "bg-[#0e3452]"
|
|
39
|
+
case "kraken":
|
|
40
|
+
case "krakenDirect":
|
|
41
|
+
return "bg-[#5841d7]"
|
|
42
|
+
case "uphold":
|
|
43
|
+
case "upholdDirect":
|
|
44
|
+
return "bg-[#49cc68]"
|
|
45
|
+
case "paribu":
|
|
46
|
+
case "paribuOAuth":
|
|
47
|
+
return "bg-[#9cba3b]"
|
|
48
|
+
case "robinhood":
|
|
49
|
+
case "robinhoodDirect":
|
|
50
|
+
case "robinhoodConnect":
|
|
51
|
+
return "bg-[#ccff00]"
|
|
52
|
+
default:
|
|
53
|
+
return "bg-gray-700"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const MeshExchangeSelection: React.FC<MeshExchangeSelectionProps> = ({
|
|
58
|
+
onBack,
|
|
59
|
+
onSelectExchange,
|
|
60
|
+
}) => {
|
|
61
|
+
const { onramp: onrampFactory, apiKey, trailsApiUrl } = useWidgetProps()
|
|
62
|
+
const onrampClient = useOnrampClient()
|
|
63
|
+
const meshOnrampConfig = getWidgetOnrampConfig(onrampFactory)
|
|
64
|
+
const [showAllExchanges, setShowAllExchanges] = useState(false)
|
|
65
|
+
const [failedLogos, setFailedLogos] = useState<Record<string, true>>({})
|
|
66
|
+
|
|
67
|
+
const meshEnvironment = getActiveMeshEnvironment(meshOnrampConfig)
|
|
68
|
+
|
|
69
|
+
const {
|
|
70
|
+
data: exchangeOptions = [],
|
|
71
|
+
isLoading,
|
|
72
|
+
error,
|
|
73
|
+
} = useQuery({
|
|
74
|
+
queryKey: ["mesh-exchange-options", meshEnvironment, trailsApiUrl, apiKey],
|
|
75
|
+
queryFn: async () => {
|
|
76
|
+
const response = await onrampClient.getMeshIntegrations({
|
|
77
|
+
environment: meshEnvironment,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return (response.integrations || []).map((integration) => {
|
|
81
|
+
return {
|
|
82
|
+
key: integration.key,
|
|
83
|
+
integrationId: integration.id,
|
|
84
|
+
exchangeName: integration.displayName || integration.key,
|
|
85
|
+
imageUrl: integration.imageUrl || "",
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
},
|
|
89
|
+
enabled: !!apiKey && !!trailsApiUrl,
|
|
90
|
+
staleTime: 24 * 60 * 60 * 1000,
|
|
91
|
+
gcTime: 24 * 60 * 60 * 1000,
|
|
92
|
+
refetchOnMount: false,
|
|
93
|
+
refetchOnWindowFocus: false,
|
|
94
|
+
refetchOnReconnect: false,
|
|
95
|
+
})
|
|
96
|
+
const visibleExchangeOptions = showAllExchanges
|
|
97
|
+
? exchangeOptions
|
|
98
|
+
: exchangeOptions.slice(0, INITIAL_VISIBLE_EXCHANGES)
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className="flex flex-col h-full">
|
|
102
|
+
<ScreenHeader
|
|
103
|
+
onBack={onBack}
|
|
104
|
+
headerContent="Select Exchange"
|
|
105
|
+
headerContentAlign="left"
|
|
106
|
+
/>
|
|
107
|
+
|
|
108
|
+
<div className="flex-1">
|
|
109
|
+
{isLoading ? (
|
|
110
|
+
<div className="flex h-full items-center justify-center">
|
|
111
|
+
<div className="text-center">
|
|
112
|
+
<div className="mt-4 mx-auto mb-4 h-8 w-8 animate-spin rounded-full border-2 border-solid border-blue-500 border-t-transparent" />
|
|
113
|
+
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
114
|
+
Loading exchanges...
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
) : error ? (
|
|
119
|
+
<div className="flex h-full items-center justify-center">
|
|
120
|
+
<div className="rounded-lg border border-solid border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-800 dark:bg-red-900/20 dark:text-red-300">
|
|
121
|
+
{error instanceof Error
|
|
122
|
+
? error.message
|
|
123
|
+
: "Failed to load exchanges"}
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
) : exchangeOptions.length === 0 ? (
|
|
127
|
+
<div className="flex h-full items-center justify-center">
|
|
128
|
+
<div className="rounded-lg border border-solid border-gray-200 bg-gray-50 p-4 text-sm text-gray-600 dark:border-gray-700 dark:bg-gray-800/70 dark:text-gray-300">
|
|
129
|
+
No supported exchanges are currently available.
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
) : (
|
|
133
|
+
<div className="max-h-[420px] overflow-y-auto pr-1 pt-4">
|
|
134
|
+
<div className="space-y-4">
|
|
135
|
+
{visibleExchangeOptions.map((exchange) => (
|
|
136
|
+
<button
|
|
137
|
+
key={exchange.integrationId}
|
|
138
|
+
type="button"
|
|
139
|
+
onClick={() => {
|
|
140
|
+
logger.console.log(
|
|
141
|
+
"[trails-sdk] Selected Mesh exchange in widget:",
|
|
142
|
+
exchange,
|
|
143
|
+
)
|
|
144
|
+
onSelectExchange({
|
|
145
|
+
integrationId: exchange.integrationId,
|
|
146
|
+
exchangeKey: exchange.key,
|
|
147
|
+
exchangeName: exchange.exchangeName,
|
|
148
|
+
})
|
|
149
|
+
}}
|
|
150
|
+
className="w-full flex items-center justify-between cursor-pointer font-semibold py-4 px-6 rounded-lg transition-all duration-200 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-900 dark:text-white"
|
|
151
|
+
>
|
|
152
|
+
<div className="flex items-center space-x-3 flex-1">
|
|
153
|
+
<div
|
|
154
|
+
className={`flex h-12 w-12 items-center justify-center overflow-hidden rounded-lg border border-solid border-gray-200 dark:border-gray-700 ${getExchangeBackgroundClassName(exchange.key)}`}
|
|
155
|
+
>
|
|
156
|
+
{exchange.imageUrl &&
|
|
157
|
+
!failedLogos[exchange.integrationId] ? (
|
|
158
|
+
<img
|
|
159
|
+
src={exchange.imageUrl}
|
|
160
|
+
alt={`${exchange.exchangeName} logo`}
|
|
161
|
+
className="h-8 w-8 rounded object-contain"
|
|
162
|
+
loading="lazy"
|
|
163
|
+
referrerPolicy="no-referrer"
|
|
164
|
+
onError={() => {
|
|
165
|
+
setFailedLogos((current) => ({
|
|
166
|
+
...current,
|
|
167
|
+
[exchange.integrationId]: true,
|
|
168
|
+
}))
|
|
169
|
+
}}
|
|
170
|
+
/>
|
|
171
|
+
) : (
|
|
172
|
+
<span className="text-sm font-semibold text-white">
|
|
173
|
+
{exchange.exchangeName.slice(0, 2).toUpperCase()}
|
|
174
|
+
</span>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
<div className="flex-1 text-left">
|
|
178
|
+
<h4 className="font-semibold text-gray-900 dark:text-gray-100">
|
|
179
|
+
{exchange.exchangeName}
|
|
180
|
+
</h4>
|
|
181
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
182
|
+
Connect your account to transfer funds
|
|
183
|
+
</p>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
<ChevronRight className="w-5 h-5 text-gray-400" />
|
|
187
|
+
</button>
|
|
188
|
+
))}
|
|
189
|
+
{!showAllExchanges &&
|
|
190
|
+
exchangeOptions.length > INITIAL_VISIBLE_EXCHANGES && (
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
onClick={() => setShowAllExchanges(true)}
|
|
194
|
+
className="w-full cursor-pointer rounded-lg border border-solid border-gray-200 px-6 py-3 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800"
|
|
195
|
+
>
|
|
196
|
+
Show more
|
|
197
|
+
</button>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
)}
|
|
202
|
+
</div>
|
|
203
|
+
|
|
204
|
+
{meshEnvironment === "sandbox" && (
|
|
205
|
+
<div className="mt-4 border border-solid border-yellow-200 bg-yellow-50 p-3 dark:border-yellow-800 dark:bg-yellow-900/20">
|
|
206
|
+
<div className="text-center">
|
|
207
|
+
<p className="text-sm font-medium text-yellow-800 dark:text-yellow-200">
|
|
208
|
+
Sandbox environment
|
|
209
|
+
</p>
|
|
210
|
+
<p className="text-xs text-yellow-600 dark:text-yellow-300">
|
|
211
|
+
No real funds are used
|
|
212
|
+
</p>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
</div>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
@@ -4,7 +4,7 @@ import { useState } from "react"
|
|
|
4
4
|
import { getChainName } from "../../chains.js"
|
|
5
5
|
import { isValidNumber } from "../../utils/validation.js"
|
|
6
6
|
import { logger } from "../../logger.js"
|
|
7
|
-
import type { MeldServiceProvider } from "
|
|
7
|
+
import type { MeldServiceProvider } from "@0xtrails/api/onramp"
|
|
8
8
|
import { SECOND_MS, formatRelativeDate } from "../../utils/time.js"
|
|
9
9
|
import { truncateAddress } from "../../utils/address.js"
|
|
10
10
|
import type { MeldTransactionData } from "../hooks/useMeldTransactionHistory.js"
|
|
@@ -21,7 +21,7 @@ import { useSendForm } from "../hooks/useSendForm.js"
|
|
|
21
21
|
import { useSwapAmount } from "../hooks/useSwapAmount.js"
|
|
22
22
|
import { useSwapState } from "../hooks/useSwapState.js"
|
|
23
23
|
import { useTargetAmount } from "../hooks/useTargetAmount.js"
|
|
24
|
-
import {
|
|
24
|
+
import { useAccountTokenBalanceOnchain } from "../../query/balance.hooks.js"
|
|
25
25
|
import type { BaseProps } from "../types/commonProps.js"
|
|
26
26
|
import { AddressOrEnsName } from "./AddressOrEnsName.js"
|
|
27
27
|
import { AddressWalletIcon } from "./AddressWalletIcon.js"
|
|
@@ -130,27 +130,11 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
130
130
|
const { trackClick } = useClickTracking()
|
|
131
131
|
const paymentRequestInputRef = useRef<HTMLInputElement>(null)
|
|
132
132
|
|
|
133
|
-
// Get
|
|
134
|
-
const {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
allSupportedTokens: true, // Show all tokens for destination selection
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
// Get origin token balance for display
|
|
142
|
-
const originTokenBalance = useMemo(() => {
|
|
143
|
-
if (!originToken || !filteredTokensFormatted) return null
|
|
144
|
-
|
|
145
|
-
const foundToken = filteredTokensFormatted.find(
|
|
146
|
-
(token) =>
|
|
147
|
-
token.contractAddress?.toLowerCase() ===
|
|
148
|
-
originToken.contractAddress?.toLowerCase() &&
|
|
149
|
-
token.chainId === originToken.chainId,
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
return foundToken
|
|
153
|
-
}, [originToken, filteredTokensFormatted])
|
|
133
|
+
// Get origin token with fresh balance for display and fee option checks
|
|
134
|
+
const {
|
|
135
|
+
token: freshOriginToken,
|
|
136
|
+
isLoadingBalance: isLoadingFreshOriginBalance,
|
|
137
|
+
} = useAccountTokenBalanceOnchain(originToken, account?.address)
|
|
154
138
|
|
|
155
139
|
// Calculate effective recipient for useSendForm
|
|
156
140
|
const effectiveRecipient =
|
|
@@ -782,9 +766,9 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
782
766
|
type="button"
|
|
783
767
|
className="text-xs text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 transition-colors bg-transparent border-none p-0"
|
|
784
768
|
onClick={() => {
|
|
785
|
-
if (
|
|
769
|
+
if (freshOriginToken?.balanceFormatted) {
|
|
786
770
|
const balance = parseFloat(
|
|
787
|
-
|
|
771
|
+
freshOriginToken.balanceFormatted,
|
|
788
772
|
)
|
|
789
773
|
if (isValidNumber(balance)) {
|
|
790
774
|
setTokenAmountForBackend(balance.toFixed(6))
|
|
@@ -794,9 +778,9 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
794
778
|
onKeyDown={(e) => {
|
|
795
779
|
if (e.key === "Enter" || e.key === " ") {
|
|
796
780
|
e.preventDefault()
|
|
797
|
-
if (
|
|
781
|
+
if (freshOriginToken?.balanceFormatted) {
|
|
798
782
|
const balance = parseFloat(
|
|
799
|
-
|
|
783
|
+
freshOriginToken.balanceFormatted,
|
|
800
784
|
)
|
|
801
785
|
if (isValidNumber(balance)) {
|
|
802
786
|
setTokenAmountForBackend(balance.toFixed(6))
|
|
@@ -805,26 +789,26 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
805
789
|
}
|
|
806
790
|
}}
|
|
807
791
|
title="Click to use full balance"
|
|
808
|
-
disabled={!
|
|
792
|
+
disabled={!freshOriginToken?.balanceFormatted}
|
|
809
793
|
>
|
|
810
794
|
<span translate="no">
|
|
811
795
|
Balance:{" "}
|
|
812
|
-
{
|
|
796
|
+
{isLoadingFreshOriginBalance ? (
|
|
813
797
|
<span className="inline-block w-12 h-3 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></span>
|
|
814
798
|
) : (
|
|
815
|
-
|
|
816
|
-
|
|
799
|
+
freshOriginToken?.balanceLocaleDisplay ||
|
|
800
|
+
freshOriginToken?.balanceFormatted ||
|
|
817
801
|
""
|
|
818
802
|
)}
|
|
819
803
|
</span>
|
|
820
804
|
</button>
|
|
821
805
|
|
|
822
806
|
{/* Percentage Buttons - Only show if toAmount is not set */}
|
|
823
|
-
{!toAmount &&
|
|
807
|
+
{!toAmount && freshOriginToken?.balanceFormatted && (
|
|
824
808
|
<PercentageMaxButtons
|
|
825
|
-
userBalance={
|
|
826
|
-
userBalanceRaw={
|
|
827
|
-
decimals={
|
|
809
|
+
userBalance={freshOriginToken.balanceFormatted}
|
|
810
|
+
userBalanceRaw={freshOriginToken.balance ?? "0"}
|
|
811
|
+
decimals={freshOriginToken.decimals ?? 18}
|
|
828
812
|
isNativeToken={originToken.isNativeToken ?? false}
|
|
829
813
|
gasCostFormatted={prepareSendQuote?.gasCostFormatted}
|
|
830
814
|
chainId={originToken.chainId}
|
|
@@ -1064,7 +1048,7 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
1064
1048
|
originToken
|
|
1065
1049
|
? {
|
|
1066
1050
|
originToken,
|
|
1067
|
-
originTokenBalance:
|
|
1051
|
+
originTokenBalance: freshOriginToken?.balance ?? "0",
|
|
1068
1052
|
originTokenAmount:
|
|
1069
1053
|
prepareSendQuote?.originAmountFormatted ?? "0",
|
|
1070
1054
|
}
|
|
@@ -1129,7 +1113,7 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
1129
1113
|
(selectedFeeOption && originToken
|
|
1130
1114
|
? isFeeOptionDisabled(selectedFeeOption as ProcessedFeeOption, {
|
|
1131
1115
|
originToken: originToken,
|
|
1132
|
-
originTokenBalance:
|
|
1116
|
+
originTokenBalance: freshOriginToken?.balance ?? "0",
|
|
1133
1117
|
originTokenAmount:
|
|
1134
1118
|
prepareSendQuote?.originAmountFormatted ?? "0",
|
|
1135
1119
|
})
|