0xtrails 0.2.4 → 0.2.5
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 +8 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/{ccip-BlV1Mry3.js → ccip-CXlshvBY.js} +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/estimate.d.ts +52 -0
- package/dist/estimate.d.ts.map +1 -1
- package/dist/{index-BNWCIGfQ.js → index-_QuyGrjU.js} +72332 -72246
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +40 -0
- package/dist/intents.d.ts.map +1 -1
- package/dist/metaTxnMonitor.d.ts +3 -3
- package/dist/metaTxnMonitor.d.ts.map +1 -1
- package/dist/metaTxns.d.ts +3 -3
- package/dist/metaTxns.d.ts.map +1 -1
- package/dist/morpho.d.ts +8 -0
- package/dist/morpho.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +16 -6
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/queryParams.d.ts.map +1 -1
- package/dist/relayer.d.ts +6 -6
- package/dist/relayer.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +2 -2
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -0
- 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 +4 -0
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/Earn.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/{FundSendForm.d.ts → FundSwap.d.ts} +11 -5
- package/dist/widget/components/FundSwap.d.ts.map +1 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
- package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
- package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +11 -34
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
- package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +16 -8
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receive.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Recipients.d.ts.map +1 -1
- package/dist/widget/components/RequiredPropsError.d.ts +8 -0
- package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +1 -0
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/SwapSettings.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts +1 -0
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/UserPreferences.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +8 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +2 -0
- package/dist/widget/css/index.css +554 -0
- package/dist/widget/hooks/useBack.d.ts +1 -0
- package/dist/widget/hooks/useBack.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +1 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -3
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts +4 -4
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +18 -12
- package/src/aave.ts +32 -0
- package/src/config.ts +12 -4
- package/src/constants.ts +2 -0
- package/src/error.ts +19 -1
- package/src/estimate.ts +416 -5
- package/src/intents.ts +161 -11
- package/src/metaTxnMonitor.ts +3 -3
- package/src/metaTxns.ts +3 -5
- package/src/morpho.ts +32 -0
- package/src/prepareSend.ts +503 -166
- package/src/queryParams.ts +2 -1
- package/src/relayer.ts +11 -11
- package/src/sequenceWallet.ts +2 -2
- package/src/tokens.ts +7 -1
- package/src/wallets.ts +8 -0
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountActionsDropdown.tsx +3 -13
- package/src/widget/components/AccountSettings.tsx +6 -24
- package/src/widget/components/ClassicSwap.tsx +111 -155
- package/src/widget/components/ConnectWallet.tsx +4 -37
- package/src/widget/components/ConnectedWallets.tsx +113 -58
- package/src/widget/components/Earn.tsx +73 -589
- package/src/widget/components/Fund.tsx +31 -82
- package/src/widget/components/FundMethods.tsx +82 -159
- package/src/widget/components/FundSwap.tsx +52 -0
- package/src/widget/components/FundingMethodSelectorButton.tsx +60 -0
- package/src/widget/components/Modal.tsx +6 -2
- package/src/widget/components/Pay.tsx +183 -208
- package/src/widget/components/PercentageMaxButtons.tsx +77 -0
- package/src/widget/components/PoolDeposit.tsx +593 -0
- package/src/widget/components/PoolWithdraw.tsx +903 -0
- package/src/widget/components/QuoteDetails.tsx +22 -8
- package/src/widget/components/Receive.tsx +0 -2
- package/src/widget/components/RecipientSelectorButton.tsx +42 -0
- package/src/widget/components/Recipients.tsx +62 -156
- package/src/widget/components/RequiredPropsError.tsx +33 -0
- package/src/widget/components/ScreenHeader.tsx +5 -1
- package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
- package/src/widget/components/Swap.tsx +2 -43
- package/src/widget/components/SwapSettings.tsx +2 -14
- package/src/widget/components/TokenImage.tsx +21 -4
- package/src/widget/components/TokenList.tsx +0 -1
- package/src/widget/components/TokenSelector.tsx +1 -0
- package/src/widget/components/TokenSelectorButton.tsx +75 -0
- package/src/widget/components/UserPreferences.tsx +6 -24
- package/src/widget/components/WaasFeeOptions.tsx +331 -0
- package/src/widget/components/WalletConfirmation.tsx +55 -3
- package/src/widget/components/WalletList.tsx +4 -2
- package/src/widget/hooks/useBack.tsx +2 -0
- package/src/widget/hooks/useCheckout.ts +36 -20
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
- package/src/widget/hooks/usePayMessage.tsx +86 -11
- package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
- package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
- package/src/widget/hooks/useSendForm.ts +24 -2
- package/src/widget/index.css +27 -0
- package/src/widget/widget.tsx +169 -111
- package/dist/widget/components/FundSendForm.d.ts.map +0 -1
- package/dist/widget/components/PaySendForm.d.ts.map +0 -1
- package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
- package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
- package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
- package/src/widget/components/FundSendForm.tsx +0 -903
- package/src/widget/components/PaySendForm.tsx +0 -869
- package/src/widget/components/SimpleSwap.tsx +0 -983
- package/src/widget/hooks/useSwapSettings.tsx +0 -100
|
@@ -1,37 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TrendingUp,
|
|
3
|
-
ArrowDown,
|
|
4
|
-
ChevronRight,
|
|
5
|
-
Search,
|
|
6
|
-
ChevronDown,
|
|
7
|
-
Loader2,
|
|
8
|
-
} from "lucide-react"
|
|
9
|
-
import { useEffect, useState, useRef } from "react"
|
|
1
|
+
import { useState } from "react"
|
|
10
2
|
import type React from "react"
|
|
11
3
|
import type { Account, WalletClient } from "viem"
|
|
12
4
|
import type { TransactionState } from "../../transactions.js"
|
|
13
5
|
import type { OnCompleteProps } from "../hooks/useSendForm.js"
|
|
14
6
|
import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
|
|
15
|
-
import {
|
|
16
|
-
import { TradeType } from "../../prepareSend.js"
|
|
17
|
-
import { useOriginSelectedToken } from "../hooks/useOriginSelectedToken.js"
|
|
18
|
-
import { useEarnPool } from "../hooks/useEarnPool.js"
|
|
19
|
-
import { useTokenList } from "../hooks/useTokenList.js"
|
|
20
|
-
import { useMode } from "../hooks/useMode.js"
|
|
21
|
-
import { useBalanceVisible } from "../hooks/useBalanceVisible.js"
|
|
22
|
-
import { TokenImage } from "./TokenImage.js"
|
|
23
|
-
import { TokenSelector } from "./TokenSelector.js"
|
|
24
|
-
import { EarnPools } from "./EarnPools.js"
|
|
7
|
+
import { ArrowUpCircle, ArrowDownCircle } from "lucide-react"
|
|
25
8
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import { formatTvl } from "../../prices.js"
|
|
29
|
-
import { getExplorerUrlForAddress } from "../../explorer.js"
|
|
30
|
-
import aaveLogo from "../assets/aave.svg"
|
|
31
|
-
import morphoLogo from "../assets/morpho.svg"
|
|
9
|
+
import { PoolDeposit } from "./PoolDeposit.js"
|
|
10
|
+
import { PoolWithdraw } from "./PoolWithdraw.js"
|
|
32
11
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
33
12
|
import type { SupportedToken } from "../../tokens.js"
|
|
34
|
-
import { logger } from "../../logger.js"
|
|
35
13
|
|
|
36
14
|
interface EarnProps {
|
|
37
15
|
onBack?: () => void
|
|
@@ -85,205 +63,10 @@ export const Earn: React.FC<EarnProps> = ({
|
|
|
85
63
|
onRecentTokenSelect,
|
|
86
64
|
onTrackToken,
|
|
87
65
|
}) => {
|
|
88
|
-
const
|
|
89
|
-
const { isBalanceVisible } = useBalanceVisible()
|
|
90
|
-
const { selectedToken: originToken, setSelectedToken: setOriginToken } =
|
|
91
|
-
useOriginSelectedToken()
|
|
92
|
-
const { selectedPool, setSelectedPool } = useEarnPool()
|
|
93
|
-
|
|
94
|
-
const [showEarnPools, setShowEarnPools] = useState(false)
|
|
95
|
-
const [showOriginTokenSelector, setShowOriginTokenSelector] = useState(false)
|
|
96
|
-
const [showOriginChainList, setShowOriginChainList] = useState(false)
|
|
97
|
-
const [amount, setAmount] = useState("")
|
|
98
|
-
const inputRef = useRef<HTMLInputElement>(null)
|
|
99
|
-
|
|
100
|
-
// Get sorted tokens to auto-select the highest USD value token
|
|
101
|
-
const { filteredTokensFormatted, isLoadingTokens } = useTokenList({
|
|
102
|
-
onContinue: () => {}, // Not used for auto-selection
|
|
103
|
-
onError: () => {}, // Not used for auto-selection
|
|
104
|
-
fundMethod: undefined,
|
|
105
|
-
allSupportedTokens: false,
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
// Use useSendForm for quote functionality when both token and pool are selected
|
|
109
|
-
const {
|
|
110
|
-
amountUsdDisplay,
|
|
111
|
-
balanceFormatted,
|
|
112
|
-
isLoadingQuote,
|
|
113
|
-
prepareSendQuote,
|
|
114
|
-
setAmount: setSendFormAmount,
|
|
115
|
-
handleSubmit,
|
|
116
|
-
isSubmitting,
|
|
117
|
-
buttonText,
|
|
118
|
-
isValidRecipient,
|
|
119
|
-
} = useSendForm({
|
|
120
|
-
account,
|
|
121
|
-
toAmount: undefined,
|
|
122
|
-
toRecipient: selectedPool?.depositAddress,
|
|
123
|
-
toChainId: selectedPool?.chainId,
|
|
124
|
-
toToken: selectedPool?.token.address,
|
|
125
|
-
toCalldata: undefined,
|
|
126
|
-
walletClient,
|
|
127
|
-
onTransactionStateChange,
|
|
128
|
-
onError,
|
|
129
|
-
onWaitingForWalletConfirm,
|
|
130
|
-
paymasterUrls,
|
|
131
|
-
gasless,
|
|
132
|
-
onConfirm,
|
|
133
|
-
onComplete,
|
|
134
|
-
onSend,
|
|
135
|
-
selectedToken: originToken as any,
|
|
136
|
-
setWalletConfirmRetryHandler,
|
|
137
|
-
tradeType: TradeType.EXACT_INPUT,
|
|
138
|
-
quoteProvider,
|
|
139
|
-
fundMethod,
|
|
140
|
-
mode,
|
|
141
|
-
onNavigateToMeshConnect,
|
|
142
|
-
checkoutOnHandlers,
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
// Auto-select the highest USD value token as origin token
|
|
146
|
-
useEffect(() => {
|
|
147
|
-
if (
|
|
148
|
-
!originToken &&
|
|
149
|
-
!isLoadingTokens &&
|
|
150
|
-
filteredTokensFormatted?.length > 0
|
|
151
|
-
) {
|
|
152
|
-
const highestValueToken = filteredTokensFormatted[0] // First token is highest USD value
|
|
153
|
-
if (highestValueToken && Number(highestValueToken.balanceUsd) > 0) {
|
|
154
|
-
const decimals =
|
|
155
|
-
highestValueToken.contractInfo?.decimals ??
|
|
156
|
-
(highestValueToken as any)?.decimals
|
|
157
|
-
setOriginToken({
|
|
158
|
-
...highestValueToken,
|
|
159
|
-
contractInfo: {
|
|
160
|
-
decimals,
|
|
161
|
-
contractAddress: highestValueToken.contractAddress,
|
|
162
|
-
symbol: highestValueToken.symbol,
|
|
163
|
-
name: highestValueToken.name,
|
|
164
|
-
},
|
|
165
|
-
} as any)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}, [originToken, isLoadingTokens, filteredTokensFormatted, setOriginToken])
|
|
169
|
-
|
|
170
|
-
// Auto-focus input field on component mount
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
if (inputRef.current) {
|
|
173
|
-
inputRef.current.focus()
|
|
174
|
-
}
|
|
175
|
-
}, [])
|
|
176
|
-
|
|
177
|
-
const handleAmountChange = (value: string) => {
|
|
178
|
-
// Validate decimal places (max 8 decimals)
|
|
179
|
-
const decimalMatch = value.match(/^\d*\.?\d{0,8}$/)
|
|
180
|
-
if (!decimalMatch && value !== "") {
|
|
181
|
-
return // Don't update if more than 8 decimals
|
|
182
|
-
}
|
|
183
|
-
setAmount(value)
|
|
184
|
-
setSendFormAmount(value) // Sync with useSendForm for quote functionality
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const handlePoolSelect = (pool: any) => {
|
|
188
|
-
logger.console.log("Selected pool:", pool)
|
|
189
|
-
setSelectedPool(pool)
|
|
190
|
-
setShowEarnPools(false)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const handleOriginTokenSelect = (token: any) => {
|
|
194
|
-
const formattedToken = {
|
|
195
|
-
...token,
|
|
196
|
-
decimals: token.contractInfo?.decimals || token.decimals,
|
|
197
|
-
contractInfo: {
|
|
198
|
-
decimals: token.contractInfo?.decimals || token.decimals,
|
|
199
|
-
contractAddress: token.contractAddress,
|
|
200
|
-
symbol: token.symbol,
|
|
201
|
-
name: token.name,
|
|
202
|
-
},
|
|
203
|
-
} as any
|
|
204
|
-
setOriginToken(formattedToken)
|
|
205
|
-
logger.console.log("[trails-sdk] selected origin token", token)
|
|
206
|
-
setShowOriginTokenSelector(false)
|
|
207
|
-
// Track the token selection
|
|
208
|
-
onTrackToken?.(token)
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Handle percentage button clicks
|
|
212
|
-
const handlePercentageClick = (percentage: number) => {
|
|
213
|
-
if (!originToken || !balanceFormatted) return
|
|
214
|
-
|
|
215
|
-
// Parse the balance and calculate percentage
|
|
216
|
-
const balance = parseFloat(balanceFormatted)
|
|
217
|
-
if (Number.isNaN(balance)) return
|
|
218
|
-
|
|
219
|
-
const calculatedAmount = (balance * percentage) / 100
|
|
220
|
-
const amountStr = calculatedAmount.toFixed(6)
|
|
221
|
-
setAmount(amountStr)
|
|
222
|
-
setSendFormAmount(amountStr)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Handle max button click
|
|
226
|
-
const handleMaxClick = () => {
|
|
227
|
-
if (!balanceFormatted) return
|
|
228
|
-
|
|
229
|
-
const balance = parseFloat(balanceFormatted)
|
|
230
|
-
if (Number.isNaN(balance)) return
|
|
231
|
-
|
|
232
|
-
const amountStr = balance.toFixed(6)
|
|
233
|
-
setAmount(amountStr)
|
|
234
|
-
setSendFormAmount(amountStr)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (showOriginChainList) {
|
|
238
|
-
return (
|
|
239
|
-
<ChainList
|
|
240
|
-
onBack={() => {
|
|
241
|
-
setShowOriginChainList(false)
|
|
242
|
-
setShowOriginTokenSelector(true)
|
|
243
|
-
}}
|
|
244
|
-
/>
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (showEarnPools) {
|
|
249
|
-
return (
|
|
250
|
-
<EarnPools
|
|
251
|
-
onBack={() => setShowEarnPools(false)}
|
|
252
|
-
onPoolSelect={handlePoolSelect}
|
|
253
|
-
/>
|
|
254
|
-
)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (showOriginTokenSelector) {
|
|
258
|
-
return (
|
|
259
|
-
<div className="space-y-2">
|
|
260
|
-
<ScreenHeader
|
|
261
|
-
onBack={() => setShowOriginTokenSelector(false)}
|
|
262
|
-
headerContent="Select Token"
|
|
263
|
-
headerContentAlign="left"
|
|
264
|
-
showAccountActions={true}
|
|
265
|
-
/>
|
|
266
|
-
<TokenSelector
|
|
267
|
-
onTokenSelect={handleOriginTokenSelect}
|
|
268
|
-
onError={onError}
|
|
269
|
-
fundMethod={fundMethod}
|
|
270
|
-
showContinueButton={false}
|
|
271
|
-
compactMode={false}
|
|
272
|
-
recentTokens={recentTokens}
|
|
273
|
-
onRecentTokenSelect={onRecentTokenSelect}
|
|
274
|
-
allSupportedTokens={false}
|
|
275
|
-
chainListScreen={true}
|
|
276
|
-
onNavigateToChainList={() => {
|
|
277
|
-
setShowOriginTokenSelector(false)
|
|
278
|
-
setShowOriginChainList(true)
|
|
279
|
-
}}
|
|
280
|
-
/>
|
|
281
|
-
</div>
|
|
282
|
-
)
|
|
283
|
-
}
|
|
66
|
+
const [activeTab, setActiveTab] = useState<"deposit" | "withdraw">("deposit")
|
|
284
67
|
|
|
285
68
|
return (
|
|
286
|
-
<div className="space-y-
|
|
69
|
+
<div className="space-y-2">
|
|
287
70
|
<ScreenHeader
|
|
288
71
|
onBack={onBack}
|
|
289
72
|
headerContent="Earn"
|
|
@@ -291,376 +74,77 @@ export const Earn: React.FC<EarnProps> = ({
|
|
|
291
74
|
showAccountActions={true}
|
|
292
75
|
/>
|
|
293
76
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
<div className="trails-bg-secondary trails-bg-secondary-hover trails-border-radius-container p-3 group transition-all duration-200 border border-transparent focus-within:!bg-white dark:focus-within:!bg-gray-800 trails-focus-border-secondary">
|
|
297
|
-
{/* Deposit Label and Percentage Buttons */}
|
|
298
|
-
<div className="flex justify-between items-center mb-2">
|
|
299
|
-
<div className="text-sm font-semibold trails-text-secondary text-left">
|
|
300
|
-
Deposit
|
|
301
|
-
</div>
|
|
302
|
-
|
|
303
|
-
{/* Percentage Buttons */}
|
|
304
|
-
{originToken && (
|
|
305
|
-
<div className="flex space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
|
|
306
|
-
<button
|
|
307
|
-
type="button"
|
|
308
|
-
onClick={() => handlePercentageClick(25)}
|
|
309
|
-
className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
|
|
310
|
-
>
|
|
311
|
-
25%
|
|
312
|
-
</button>
|
|
313
|
-
<button
|
|
314
|
-
type="button"
|
|
315
|
-
onClick={() => handlePercentageClick(50)}
|
|
316
|
-
className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
|
|
317
|
-
>
|
|
318
|
-
50%
|
|
319
|
-
</button>
|
|
320
|
-
<button
|
|
321
|
-
type="button"
|
|
322
|
-
onClick={() => handlePercentageClick(75)}
|
|
323
|
-
className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
|
|
324
|
-
>
|
|
325
|
-
75%
|
|
326
|
-
</button>
|
|
327
|
-
<button
|
|
328
|
-
type="button"
|
|
329
|
-
onClick={handleMaxClick}
|
|
330
|
-
className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
|
|
331
|
-
>
|
|
332
|
-
Max
|
|
333
|
-
</button>
|
|
334
|
-
</div>
|
|
335
|
-
)}
|
|
336
|
-
</div>
|
|
337
|
-
|
|
338
|
-
<div className="flex items-center space-x-2">
|
|
339
|
-
{/* Amount Input */}
|
|
340
|
-
<div className="flex-1">
|
|
341
|
-
<div
|
|
342
|
-
className="flex items-center justify-start cursor-text"
|
|
343
|
-
onClick={() => inputRef.current?.focus()}
|
|
344
|
-
>
|
|
345
|
-
<div className="flex items-center">
|
|
346
|
-
<input
|
|
347
|
-
ref={inputRef}
|
|
348
|
-
type="text"
|
|
349
|
-
value={amount}
|
|
350
|
-
onChange={(e) => handleAmountChange(e.target.value)}
|
|
351
|
-
placeholder="0"
|
|
352
|
-
className={`bg-transparent border-none outline-none font-bold text-left trails-text-primary placeholder-trails-text-primary ${
|
|
353
|
-
isLoadingQuote ? "animate-pulse" : ""
|
|
354
|
-
}`}
|
|
355
|
-
style={{
|
|
356
|
-
fontSize:
|
|
357
|
-
amount.length > 12
|
|
358
|
-
? "0.875rem"
|
|
359
|
-
: amount.length > 9
|
|
360
|
-
? "1rem"
|
|
361
|
-
: amount.length > 6
|
|
362
|
-
? "1.125rem"
|
|
363
|
-
: amount.length > 3
|
|
364
|
-
? "1.25rem"
|
|
365
|
-
: "1.5rem",
|
|
366
|
-
width: `${Math.max((amount || "0").length, 1)}ch`,
|
|
367
|
-
minWidth: "1ch",
|
|
368
|
-
maxWidth: "270px",
|
|
369
|
-
padding: "0",
|
|
370
|
-
margin: "0",
|
|
371
|
-
transition: "all 0.1s ease-in-out",
|
|
372
|
-
}}
|
|
373
|
-
inputMode="decimal"
|
|
374
|
-
/>
|
|
375
|
-
<span
|
|
376
|
-
className="font-bold text-gray-400 dark:text-gray-500"
|
|
377
|
-
style={{
|
|
378
|
-
fontSize:
|
|
379
|
-
amount.length > 12
|
|
380
|
-
? "0.875rem"
|
|
381
|
-
: amount.length > 9
|
|
382
|
-
? "1rem"
|
|
383
|
-
: amount.length > 6
|
|
384
|
-
? "1.125rem"
|
|
385
|
-
: amount.length > 3
|
|
386
|
-
? "1.25rem"
|
|
387
|
-
: "1.5rem",
|
|
388
|
-
marginLeft: "0.1em",
|
|
389
|
-
padding: "0",
|
|
390
|
-
transition: "all 0.2s ease-in-out",
|
|
391
|
-
}}
|
|
392
|
-
>
|
|
393
|
-
{originToken?.symbol.slice(0, 4) || ""}
|
|
394
|
-
</span>
|
|
395
|
-
{isLoadingQuote && (
|
|
396
|
-
<div className="ml-2 animate-spin rounded-full h-4 w-4 border-solid border-b-2 trails-primary" />
|
|
397
|
-
)}
|
|
398
|
-
</div>
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
|
|
402
|
-
{/* Token Selection Button */}
|
|
403
|
-
<button
|
|
404
|
-
type="button"
|
|
405
|
-
onClick={() => setShowOriginTokenSelector(true)}
|
|
406
|
-
className="flex items-center space-x-2 trails-bg-card hover:trails-hover-bg trails-border-radius-input px-2.5 py-1.5 border trails-border-primary transition-colors cursor-pointer"
|
|
407
|
-
>
|
|
408
|
-
{originToken ? (
|
|
409
|
-
<>
|
|
410
|
-
<TokenImage
|
|
411
|
-
symbol={originToken.symbol}
|
|
412
|
-
imageUrl={originToken.imageUrl}
|
|
413
|
-
chainId={originToken.chainId}
|
|
414
|
-
size={20}
|
|
415
|
-
/>
|
|
416
|
-
<span className="font-medium trails-text-primary text-sm">
|
|
417
|
-
{originToken.symbol}
|
|
418
|
-
</span>
|
|
419
|
-
<ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
|
|
420
|
-
</>
|
|
421
|
-
) : (
|
|
422
|
-
<>
|
|
423
|
-
<span className="font-medium trails-text-muted text-sm">
|
|
424
|
-
Select Token
|
|
425
|
-
</span>
|
|
426
|
-
<ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
|
|
427
|
-
</>
|
|
428
|
-
)}
|
|
429
|
-
</button>
|
|
430
|
-
</div>
|
|
431
|
-
|
|
432
|
-
{/* Bottom Info Row */}
|
|
433
|
-
<div className="mt-2 flex justify-between items-center">
|
|
434
|
-
{/* USD Amount */}
|
|
435
|
-
<div className="text-xs trails-text-muted">
|
|
436
|
-
{originToken?.symbol && amount ? (
|
|
437
|
-
<>≈ {amountUsdDisplay || "$0.00"}</>
|
|
438
|
-
) : (
|
|
439
|
-
<span> </span>
|
|
440
|
-
)}
|
|
441
|
-
</div>
|
|
442
|
-
|
|
443
|
-
{/* Origin Token Balance */}
|
|
444
|
-
<div className="text-xs trails-text-muted text-right">
|
|
445
|
-
{originToken ? (
|
|
446
|
-
<button
|
|
447
|
-
type="button"
|
|
448
|
-
className="text-xs trails-text-muted cursor-pointer hover:trails-hover-text transition-colors bg-transparent border-none p-0"
|
|
449
|
-
onClick={handleMaxClick}
|
|
450
|
-
onKeyDown={(e) => {
|
|
451
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
452
|
-
e.preventDefault()
|
|
453
|
-
handleMaxClick()
|
|
454
|
-
}
|
|
455
|
-
}}
|
|
456
|
-
title="Click to use full balance"
|
|
457
|
-
>
|
|
458
|
-
Balance:{" "}
|
|
459
|
-
{isBalanceVisible
|
|
460
|
-
? `${balanceFormatted || "0.00"} ${originToken.symbol}`
|
|
461
|
-
: "••••••"}
|
|
462
|
-
</button>
|
|
463
|
-
) : (
|
|
464
|
-
<span> </span>
|
|
465
|
-
)}
|
|
466
|
-
</div>
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
469
|
-
|
|
470
|
-
{/* Arrow Down Between Sections */}
|
|
471
|
-
<div className="relative">
|
|
472
|
-
<div className="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 p-1.5 trails-border-radius-button trails-bg-tertiary transition-colors border-2 border-white dark:border-gray-800 z-1">
|
|
473
|
-
<ArrowDown
|
|
474
|
-
className="w-5 h-5 text-gray-900 dark:text-white"
|
|
475
|
-
strokeWidth={2.5}
|
|
476
|
-
/>
|
|
477
|
-
</div>
|
|
478
|
-
</div>
|
|
479
|
-
|
|
480
|
-
{/* Destination Vault Selection */}
|
|
481
|
-
<div className="trails-bg-secondary trails-border-radius-container transition-all duration-200 border border-transparent hover:!bg-white dark:hover:!bg-white hover:border-gray-400 dark:hover:border-gray-500">
|
|
482
|
-
{selectedPool ? (
|
|
483
|
-
<div className="p-3 trails-border-radius-container trails-bg-secondary transition-all overflow-hidden">
|
|
484
|
-
{/* Vault Label */}
|
|
485
|
-
<div className="flex justify-between items-center mb-2">
|
|
486
|
-
<div className="text-sm font-semibold trails-text-secondary text-left">
|
|
487
|
-
Vault
|
|
488
|
-
</div>
|
|
489
|
-
</div>
|
|
490
|
-
|
|
491
|
-
<div className="px-1">
|
|
492
|
-
<div className="flex items-center justify-between">
|
|
493
|
-
<div className="flex items-center space-x-3">
|
|
494
|
-
<div style={{ width: "32px", height: "32px" }}>
|
|
495
|
-
<a
|
|
496
|
-
href={getExplorerUrlForAddress({
|
|
497
|
-
address: selectedPool.token.address,
|
|
498
|
-
chainId: selectedPool.chainId,
|
|
499
|
-
})}
|
|
500
|
-
target="_blank"
|
|
501
|
-
rel="noopener noreferrer"
|
|
502
|
-
className="cursor-pointer"
|
|
503
|
-
>
|
|
504
|
-
<TokenImage
|
|
505
|
-
symbol={selectedPool.token.symbol}
|
|
506
|
-
imageUrl={selectedPool.token.logoUrl}
|
|
507
|
-
chainId={selectedPool.chainId}
|
|
508
|
-
size={32}
|
|
509
|
-
/>
|
|
510
|
-
</a>
|
|
511
|
-
</div>
|
|
512
|
-
<div>
|
|
513
|
-
<h3 className="font-medium text-gray-900 dark:text-white text-sm">
|
|
514
|
-
{selectedPool.poolUrl ? (
|
|
515
|
-
<a
|
|
516
|
-
href={selectedPool.poolUrl}
|
|
517
|
-
target="_blank"
|
|
518
|
-
rel="noopener noreferrer"
|
|
519
|
-
className="hover:underline cursor-pointer"
|
|
520
|
-
>
|
|
521
|
-
{selectedPool.name}
|
|
522
|
-
</a>
|
|
523
|
-
) : (
|
|
524
|
-
selectedPool.name
|
|
525
|
-
)}
|
|
526
|
-
</h3>
|
|
527
|
-
<div className="flex items-center space-x-2">
|
|
528
|
-
<span className="text-xs text-gray-500 dark:text-gray-400 flex items-center">
|
|
529
|
-
{selectedPool.protocol === "Aave" && (
|
|
530
|
-
<img
|
|
531
|
-
src={aaveLogo}
|
|
532
|
-
alt="Aave"
|
|
533
|
-
className="w-3 h-3 mr-1"
|
|
534
|
-
/>
|
|
535
|
-
)}
|
|
536
|
-
{selectedPool.protocol === "Morpho" && (
|
|
537
|
-
<img
|
|
538
|
-
src={morphoLogo}
|
|
539
|
-
alt="Morpho"
|
|
540
|
-
className="w-3 h-3 mr-1"
|
|
541
|
-
/>
|
|
542
|
-
)}
|
|
543
|
-
{selectedPool.protocolUrl ? (
|
|
544
|
-
<a
|
|
545
|
-
href={selectedPool.protocolUrl}
|
|
546
|
-
target="_blank"
|
|
547
|
-
rel="noopener noreferrer"
|
|
548
|
-
className="hover:underline cursor-pointer"
|
|
549
|
-
>
|
|
550
|
-
{selectedPool.protocol}
|
|
551
|
-
</a>
|
|
552
|
-
) : (
|
|
553
|
-
selectedPool.protocol
|
|
554
|
-
)}
|
|
555
|
-
</span>
|
|
556
|
-
</div>
|
|
557
|
-
</div>
|
|
558
|
-
</div>
|
|
559
|
-
<button
|
|
560
|
-
type="button"
|
|
561
|
-
title="Select Vault"
|
|
562
|
-
onClick={() => setShowEarnPools(true)}
|
|
563
|
-
className="text-right flex items-center space-x-3 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 rounded p-2 transition-colors"
|
|
564
|
-
>
|
|
565
|
-
<div>
|
|
566
|
-
<div className="flex items-center justify-end space-x-1 text-green-600 dark:text-green-400 mb-1 whitespace-nowrap">
|
|
567
|
-
<TrendingUp className="w-3 h-3" />
|
|
568
|
-
<span className="font-semibold text-sm">
|
|
569
|
-
{selectedPool.apy.toFixed(1)}% APY
|
|
570
|
-
</span>
|
|
571
|
-
</div>
|
|
572
|
-
<p className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
|
|
573
|
-
TVL: {formatTvl(selectedPool.tvl)}
|
|
574
|
-
</p>
|
|
575
|
-
</div>
|
|
576
|
-
<ChevronRight className="w-4 h-4 text-gray-400" />
|
|
577
|
-
</button>
|
|
578
|
-
</div>
|
|
579
|
-
</div>
|
|
580
|
-
</div>
|
|
581
|
-
) : (
|
|
582
|
-
<button
|
|
583
|
-
type="button"
|
|
584
|
-
onClick={() => setShowEarnPools(true)}
|
|
585
|
-
className="w-full py-6 px-4 trails-list-item trails-border-radius-container transition-all duration-200 cursor-pointer"
|
|
586
|
-
>
|
|
587
|
-
<div className="flex items-center justify-between">
|
|
588
|
-
<div className="flex items-center space-x-3 flex-1">
|
|
589
|
-
<div className="w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
|
|
590
|
-
<Search className="w-4 h-4 text-gray-400" />
|
|
591
|
-
</div>
|
|
592
|
-
<div className="text-left flex-1">
|
|
593
|
-
<div className="font-semibold text-gray-900 dark:text-white text-sm">
|
|
594
|
-
Select vault to earn yield with
|
|
595
|
-
</div>
|
|
596
|
-
</div>
|
|
597
|
-
</div>
|
|
598
|
-
<ChevronRight className="w-4 h-4 trails-text-muted flex-shrink-0" />
|
|
599
|
-
</div>
|
|
600
|
-
</button>
|
|
601
|
-
)}
|
|
602
|
-
</div>
|
|
603
|
-
</div>
|
|
604
|
-
|
|
605
|
-
{prepareSendQuote?.noSufficientBalance ? (
|
|
606
|
-
<div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
|
|
607
|
-
<div className="flex items-center space-x-2">
|
|
608
|
-
<svg
|
|
609
|
-
className="w-4 h-4 text-amber-500 flex-shrink-0"
|
|
610
|
-
fill="none"
|
|
611
|
-
stroke="currentColor"
|
|
612
|
-
viewBox="0 0 24 24"
|
|
613
|
-
aria-hidden="true"
|
|
614
|
-
>
|
|
615
|
-
<path
|
|
616
|
-
strokeLinecap="round"
|
|
617
|
-
strokeLinejoin="round"
|
|
618
|
-
strokeWidth={2}
|
|
619
|
-
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
620
|
-
/>
|
|
621
|
-
</svg>
|
|
622
|
-
<p className="text-sm text-amber-600 dark:text-amber-400">
|
|
623
|
-
Insufficient balance to complete this transaction
|
|
624
|
-
</p>
|
|
625
|
-
</div>
|
|
626
|
-
</div>
|
|
627
|
-
) : null}
|
|
628
|
-
|
|
629
|
-
<form onSubmit={handleSubmit}>
|
|
77
|
+
{/* Tabs */}
|
|
78
|
+
<div className="flex justify-start space-x-2">
|
|
630
79
|
<button
|
|
631
|
-
type="
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
isLoadingQuote ||
|
|
639
|
-
!prepareSendQuote ||
|
|
640
|
-
prepareSendQuote?.noSufficientBalance
|
|
641
|
-
}
|
|
642
|
-
className={`w-full font-semibold py-4 px-4 trails-border-radius-button transition-colors bg-blue-500 hover:bg-blue-600 disabled:bg-gray-300 text-white disabled:text-gray-500 disabled:cursor-not-allowed cursor-pointer relative`}
|
|
80
|
+
type="button"
|
|
81
|
+
onClick={() => setActiveTab("deposit")}
|
|
82
|
+
className={`flex items-center space-x-2 py-2 px-4 text-xs font-bold cursor-pointer trails-border-radius-input ${
|
|
83
|
+
activeTab === "deposit"
|
|
84
|
+
? "trails-bg-secondary text-blue-500"
|
|
85
|
+
: "trails-text-secondary"
|
|
86
|
+
}`}
|
|
643
87
|
>
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
<Loader2
|
|
647
|
-
className={`w-5 h-5 animate-spin mr-2 ${"text-gray-400"}`}
|
|
648
|
-
/>
|
|
649
|
-
<span>{buttonText}</span>
|
|
650
|
-
</div>
|
|
651
|
-
) : prepareSendQuote?.noSufficientBalance ? (
|
|
652
|
-
"Insufficient Balance"
|
|
653
|
-
) : (
|
|
654
|
-
buttonText || "Deposit"
|
|
655
|
-
)}
|
|
88
|
+
<ArrowDownCircle className="w-4 h-4" />
|
|
89
|
+
<span>Deposit</span>
|
|
656
90
|
</button>
|
|
657
|
-
|
|
91
|
+
<button
|
|
92
|
+
type="button"
|
|
93
|
+
onClick={() => setActiveTab("withdraw")}
|
|
94
|
+
className={`flex items-center space-x-2 py-2 px-4 text-xs font-bold cursor-pointer trails-border-radius-input ${
|
|
95
|
+
activeTab === "withdraw"
|
|
96
|
+
? "trails-bg-secondary text-blue-500"
|
|
97
|
+
: "trails-text-secondary"
|
|
98
|
+
}`}
|
|
99
|
+
>
|
|
100
|
+
<ArrowUpCircle className="w-4 h-4" />
|
|
101
|
+
<span>Withdraw</span>
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
658
104
|
|
|
659
|
-
{/*
|
|
660
|
-
{
|
|
661
|
-
<
|
|
662
|
-
|
|
663
|
-
|
|
105
|
+
{/* Content */}
|
|
106
|
+
{activeTab === "deposit" ? (
|
|
107
|
+
<PoolDeposit
|
|
108
|
+
account={account}
|
|
109
|
+
walletClient={walletClient}
|
|
110
|
+
onTransactionStateChange={onTransactionStateChange}
|
|
111
|
+
onError={onError}
|
|
112
|
+
onWaitingForWalletConfirm={onWaitingForWalletConfirm}
|
|
113
|
+
onConfirm={onConfirm}
|
|
114
|
+
onComplete={onComplete}
|
|
115
|
+
onSend={onSend}
|
|
116
|
+
paymasterUrls={paymasterUrls}
|
|
117
|
+
gasless={gasless}
|
|
118
|
+
setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
|
|
119
|
+
quoteProvider={quoteProvider}
|
|
120
|
+
fundMethod={fundMethod}
|
|
121
|
+
onNavigateToMeshConnect={onNavigateToMeshConnect}
|
|
122
|
+
checkoutOnHandlers={checkoutOnHandlers}
|
|
123
|
+
recentTokens={recentTokens}
|
|
124
|
+
onRecentTokenSelect={onRecentTokenSelect}
|
|
125
|
+
onTrackToken={onTrackToken}
|
|
126
|
+
/>
|
|
127
|
+
) : (
|
|
128
|
+
<PoolWithdraw
|
|
129
|
+
account={account}
|
|
130
|
+
walletClient={walletClient}
|
|
131
|
+
onTransactionStateChange={onTransactionStateChange}
|
|
132
|
+
onError={onError}
|
|
133
|
+
onWaitingForWalletConfirm={onWaitingForWalletConfirm}
|
|
134
|
+
onConfirm={onConfirm}
|
|
135
|
+
onComplete={onComplete}
|
|
136
|
+
onSend={onSend}
|
|
137
|
+
paymasterUrls={paymasterUrls}
|
|
138
|
+
gasless={gasless}
|
|
139
|
+
setWalletConfirmRetryHandler={setWalletConfirmRetryHandler}
|
|
140
|
+
quoteProvider={quoteProvider}
|
|
141
|
+
fundMethod={fundMethod}
|
|
142
|
+
onNavigateToMeshConnect={onNavigateToMeshConnect}
|
|
143
|
+
checkoutOnHandlers={checkoutOnHandlers}
|
|
144
|
+
recentTokens={recentTokens}
|
|
145
|
+
onRecentTokenSelect={onRecentTokenSelect}
|
|
146
|
+
onTrackToken={onTrackToken}
|
|
147
|
+
/>
|
|
664
148
|
)}
|
|
665
149
|
</div>
|
|
666
150
|
)
|