0xtrails 0.6.0 → 0.6.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-Dw5AN7oU.js → ccip-CZfykYU7.js} +4 -4
- package/dist/chains.d.ts +9 -2
- 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/contractUtils.d.ts +2 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/{index-BtVUTbEZ.js → index-S9pphnT9.js} +29732 -36767
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +300 -242
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +3 -1
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/widget/components/ChainImage.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/DepositTracker.d.ts +12 -0
- package/dist/widget/components/DepositTracker.d.ts.map +1 -0
- package/dist/widget/components/Disconnect.d.ts.map +1 -1
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeOptions.d.ts +9 -0
- package/dist/widget/components/QRCodeOptions.d.ts.map +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WalletConnectionPending.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/css/index.css +103 -38
- 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/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.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.map +1 -1
- package/package.json +6 -9
- package/src/chains.ts +37 -4
- package/src/constants.ts +1 -0
- package/src/contractUtils.ts +8 -7
- package/src/estimate.ts +2 -2
- package/src/index.ts +2 -0
- package/src/intents.ts +2 -2
- package/src/paymasterSend.ts +2 -2
- package/src/prepareSend.ts +34 -3
- package/src/sendUserOp.ts +2 -2
- package/src/tokens.ts +2 -2
- package/src/transactionIntent/deposits/gaslessDeposit.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +51 -2
- package/src/transactionIntent/handlers/sameChainSameToken.ts +52 -2
- package/src/transactionIntent/quote/normalizeQuote.ts +2 -2
- package/src/transactionIntent/types.ts +9 -1
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/ChainImage.tsx +10 -7
- package/src/widget/components/ChainList.tsx +1 -1
- package/src/widget/components/ClassicSwap.tsx +8 -4
- package/src/widget/components/ConnectedWallets.tsx +1 -1
- package/src/widget/components/DepositTracker.tsx +298 -0
- package/src/widget/components/Disconnect.tsx +24 -3
- package/src/widget/components/FeeBreakdown.tsx +3 -3
- package/src/widget/components/QRCodeDeposit.tsx +29 -19
- package/src/widget/components/QRCodeOptions.tsx +65 -0
- package/src/widget/components/QuoteDetails.tsx +694 -803
- package/src/widget/components/Receipt.tsx +76 -40
- package/src/widget/components/ThemeProvider.tsx +7 -12
- package/src/widget/components/Toast.tsx +3 -2
- package/src/widget/components/TokenSelector.tsx +1 -1
- package/src/widget/components/Tooltip.tsx +1 -1
- package/src/widget/components/TransferPendingVertical.tsx +11 -2
- package/src/widget/components/WalletConnectionPending.tsx +28 -5
- package/src/widget/hooks/useCheckout.ts +10 -2
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +1 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +114 -143
- package/src/widget/hooks/useQuote.ts +92 -6
- package/src/widget/hooks/useSelectedFeeOption.tsx +86 -29
- package/src/widget/hooks/useSendForm.ts +43 -7
- package/src/widget/index.css +103 -38
- package/src/widget/widget.tsx +48 -5
- package/dist/0xtrails.css +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TokenImage } from "./TokenImage.js"
|
|
2
2
|
import { ChainImage } from "./ChainImage.js"
|
|
3
|
-
import { InfoIcon } from "@0xsequence/design-system"
|
|
4
3
|
import { Tooltip } from "./Tooltip.js"
|
|
5
4
|
import type React from "react"
|
|
6
5
|
import { getExplorerUrlForAddress } from "../../explorer.js"
|
|
@@ -10,7 +9,7 @@ import { truncateAddress } from "../../utils.js"
|
|
|
10
9
|
import { PriceImpactWarning } from "./PriceImpactWarning.js"
|
|
11
10
|
import { usePriceImpactWarning } from "../hooks/usePriceImpactWarning.js"
|
|
12
11
|
import { formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
13
|
-
import { Copy, Check } from "lucide-react"
|
|
12
|
+
import { Copy, Check, Info } from "lucide-react"
|
|
14
13
|
|
|
15
14
|
interface QuoteDetailsProps {
|
|
16
15
|
quote?: PrepareSendQuote | null
|
|
@@ -37,7 +36,9 @@ const formatCompletionTime = (seconds: number): string => {
|
|
|
37
36
|
const remainingMinutes = Math.floor((seconds % 3600) / 60)
|
|
38
37
|
const remainingSeconds = seconds % 60
|
|
39
38
|
if (remainingMinutes > 0 || remainingSeconds > 0) {
|
|
40
|
-
return `${hours}h${remainingMinutes}m${
|
|
39
|
+
return `${hours}h${remainingMinutes}m${
|
|
40
|
+
remainingSeconds > 0 ? `${remainingSeconds}s` : ""
|
|
41
|
+
}`
|
|
41
42
|
} else {
|
|
42
43
|
return `${hours}h`
|
|
43
44
|
}
|
|
@@ -56,11 +57,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
56
57
|
const [showCalldata, setShowCalldata] = useState(false)
|
|
57
58
|
const [showOriginRate, setShowOriginRate] = useState(true)
|
|
58
59
|
const [isExpanded, setIsExpanded] = useState(false)
|
|
59
|
-
const [showMoreInfo, setShowMoreInfo] = useState(false)
|
|
60
60
|
const [intentIdCopied, setIntentIdCopied] = useState(false)
|
|
61
61
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
62
62
|
const calldataRef = useRef<HTMLDivElement>(null)
|
|
63
|
-
const moreInfoRef = useRef<HTMLDivElement>(null)
|
|
64
63
|
|
|
65
64
|
const priceImpactConfig = usePriceImpactWarning()
|
|
66
65
|
|
|
@@ -100,7 +99,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
100
99
|
|
|
101
100
|
return (
|
|
102
101
|
<div
|
|
103
|
-
className={`relative transition-opacity duration-300 ${
|
|
102
|
+
className={`relative transition-opacity duration-300 ${
|
|
103
|
+
isRefetching ? "opacity-50" : ""
|
|
104
|
+
}`}
|
|
104
105
|
>
|
|
105
106
|
{/* Price Impact Warning - always visible when conditions are met */}
|
|
106
107
|
<PriceImpactWarning
|
|
@@ -116,7 +117,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
116
117
|
<span className="text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
117
118
|
Balance Status:
|
|
118
119
|
<Tooltip message="Your wallet does not have sufficient balance to complete this transaction">
|
|
119
|
-
<
|
|
120
|
+
<Info className="w-3 h-3 text-amber-500 dark:text-amber-400 cursor-pointer" />
|
|
120
121
|
</Tooltip>
|
|
121
122
|
</span>
|
|
122
123
|
<span className="font-medium text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
@@ -139,92 +140,66 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
139
140
|
</div>
|
|
140
141
|
)}
|
|
141
142
|
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{quote.gasCostUsdDisplay}
|
|
199
|
-
</span>
|
|
200
|
-
</>
|
|
201
|
-
)}
|
|
202
|
-
<svg
|
|
203
|
-
className="w-3 h-3 transition-transform duration-300 ease-out"
|
|
204
|
-
fill="none"
|
|
205
|
-
stroke="currentColor"
|
|
206
|
-
viewBox="0 0 24 24"
|
|
207
|
-
aria-hidden="true"
|
|
208
|
-
>
|
|
209
|
-
<path
|
|
210
|
-
strokeLinecap="round"
|
|
211
|
-
strokeLinejoin="round"
|
|
212
|
-
strokeWidth={2}
|
|
213
|
-
d="M19 9l-7 7-7-7"
|
|
214
|
-
/>
|
|
215
|
-
</svg>
|
|
216
|
-
</div>
|
|
217
|
-
</button>
|
|
218
|
-
) : (
|
|
219
|
-
<button
|
|
220
|
-
type="button"
|
|
221
|
-
onClick={() => setIsExpanded(true)}
|
|
222
|
-
className={`w-full max-w-md flex items-center ${compact ? "justify-center" : "justify-between"} gap-2 py-1 px-1 trails-border-radius-button transition-colors cursor-pointer text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300`}
|
|
223
|
-
aria-label="Show transaction details"
|
|
224
|
-
>
|
|
225
|
-
<span>Transaction details</span>
|
|
143
|
+
<div className={`flex justify-center`}>
|
|
144
|
+
{swapMode ? (
|
|
145
|
+
<button
|
|
146
|
+
type="button"
|
|
147
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
148
|
+
className="w-full flex items-center justify-between px-2 py-2 trails-border-radius-button transition-colors cursor-pointer text-xs"
|
|
149
|
+
aria-label="Show more details"
|
|
150
|
+
>
|
|
151
|
+
<div className="flex items-center gap-2 text-gray-600 dark:text-gray-400 whitespace-nowrap max-w-48 truncate">
|
|
152
|
+
{quote?.originTokenRate && (
|
|
153
|
+
<span className="font-medium">{quote.originTokenRate}</span>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
<div className="flex items-center gap-2 text-gray-600 dark:text-gray-400">
|
|
157
|
+
{quote?.completionEstimateSeconds != null && (
|
|
158
|
+
<>
|
|
159
|
+
<svg
|
|
160
|
+
className="w-3 h-3"
|
|
161
|
+
fill="none"
|
|
162
|
+
stroke="currentColor"
|
|
163
|
+
viewBox="0 0 24 24"
|
|
164
|
+
aria-hidden="true"
|
|
165
|
+
>
|
|
166
|
+
<path
|
|
167
|
+
strokeLinecap="round"
|
|
168
|
+
strokeLinejoin="round"
|
|
169
|
+
strokeWidth={2}
|
|
170
|
+
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
171
|
+
/>
|
|
172
|
+
</svg>
|
|
173
|
+
<span className="font-medium">
|
|
174
|
+
~{formatCompletionTime(quote.completionEstimateSeconds)}
|
|
175
|
+
</span>
|
|
176
|
+
</>
|
|
177
|
+
)}
|
|
178
|
+
{quote?.gasCostUsd != null && quote?.gasCostUsd > 0 && (
|
|
179
|
+
<>
|
|
180
|
+
<svg
|
|
181
|
+
aria-hidden="true"
|
|
182
|
+
focusable="false"
|
|
183
|
+
data-prefix="fas"
|
|
184
|
+
data-icon="gas-pump"
|
|
185
|
+
className="svg-inline--fa fa-gas-pump"
|
|
186
|
+
role="img"
|
|
187
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
188
|
+
viewBox="0 0 512 512"
|
|
189
|
+
width="12"
|
|
190
|
+
>
|
|
191
|
+
<path
|
|
192
|
+
fill="currentColor"
|
|
193
|
+
d="M32 64C32 28.7 60.7 0 96 0H256c35.3 0 64 28.7 64 64V256h8c48.6 0 88 39.4 88 88v32c0 13.3 10.7 24 24 24s24-10.7 24-24V222c-27.6-7.1-48-32.2-48-62V96L384 64c-8.8-8.8-8.8-23.2 0-32s23.2-8.8 32 0l77.3 77.3c12 12 18.7 28.3 18.7 45.3V168v24 32V376c0 39.8-32.2 72-72 72s-72-32.2-72-72V344c0-22.1-17.9-40-40-40h-8V448c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32V64zM96 80v96c0 8.8 7.2 16 16 16H240c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H112c-8.8 0-16 7.2-16 16z"
|
|
194
|
+
/>
|
|
195
|
+
</svg>
|
|
196
|
+
<span className="font-medium">{quote.gasCostUsdDisplay}</span>
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
226
199
|
<svg
|
|
227
|
-
className=
|
|
200
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
201
|
+
isExpanded ? "rotate-180" : ""
|
|
202
|
+
}`}
|
|
228
203
|
fill="none"
|
|
229
204
|
stroke="currentColor"
|
|
230
205
|
viewBox="0 0 24 24"
|
|
@@ -237,10 +212,37 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
237
212
|
d="M19 9l-7 7-7-7"
|
|
238
213
|
/>
|
|
239
214
|
</svg>
|
|
240
|
-
</
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
215
|
+
</div>
|
|
216
|
+
</button>
|
|
217
|
+
) : (
|
|
218
|
+
<button
|
|
219
|
+
type="button"
|
|
220
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
221
|
+
className={`w-full max-w-md flex items-center ${
|
|
222
|
+
compact ? "justify-center" : "justify-between"
|
|
223
|
+
} gap-2 py-1 px-1 trails-border-radius-button transition-colors cursor-pointer text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300`}
|
|
224
|
+
aria-label="Show transaction details"
|
|
225
|
+
>
|
|
226
|
+
<span>Transaction details</span>
|
|
227
|
+
<svg
|
|
228
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
229
|
+
isExpanded ? "rotate-180" : ""
|
|
230
|
+
}`}
|
|
231
|
+
fill="none"
|
|
232
|
+
stroke="currentColor"
|
|
233
|
+
viewBox="0 0 24 24"
|
|
234
|
+
aria-hidden="true"
|
|
235
|
+
>
|
|
236
|
+
<path
|
|
237
|
+
strokeLinecap="round"
|
|
238
|
+
strokeLinejoin="round"
|
|
239
|
+
strokeWidth={2}
|
|
240
|
+
d="M19 9l-7 7-7-7"
|
|
241
|
+
/>
|
|
242
|
+
</svg>
|
|
243
|
+
</button>
|
|
244
|
+
)}
|
|
245
|
+
</div>
|
|
244
246
|
|
|
245
247
|
{/* Details container */}
|
|
246
248
|
<div
|
|
@@ -249,66 +251,15 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
249
251
|
isExpanded ? "max-h-[250px] opacity-100" : "max-h-0 opacity-0"
|
|
250
252
|
}`}
|
|
251
253
|
>
|
|
252
|
-
<div
|
|
253
|
-
className=
|
|
254
|
-
>
|
|
255
|
-
{/* Close Button - only visible when expanded, at top center */}
|
|
256
|
-
<div className={`flex justify-center mb-4 -mt-2`}>
|
|
257
|
-
{swapMode ? (
|
|
258
|
-
<button
|
|
259
|
-
type="button"
|
|
260
|
-
onClick={() => setIsExpanded(false)}
|
|
261
|
-
className="w-full flex items-center justify-end py-2 text-xs transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 cursor-pointer"
|
|
262
|
-
aria-label="Close details"
|
|
263
|
-
>
|
|
264
|
-
<svg
|
|
265
|
-
className="w-3 h-3 transition-transform duration-300 ease-out rotate-180"
|
|
266
|
-
fill="none"
|
|
267
|
-
stroke="currentColor"
|
|
268
|
-
viewBox="0 0 24 24"
|
|
269
|
-
aria-hidden="true"
|
|
270
|
-
>
|
|
271
|
-
<path
|
|
272
|
-
strokeLinecap="round"
|
|
273
|
-
strokeLinejoin="round"
|
|
274
|
-
strokeWidth={2}
|
|
275
|
-
d="M19 9l-7 7-7-7"
|
|
276
|
-
/>
|
|
277
|
-
</svg>
|
|
278
|
-
</button>
|
|
279
|
-
) : (
|
|
280
|
-
<button
|
|
281
|
-
type="button"
|
|
282
|
-
onClick={() => setIsExpanded(false)}
|
|
283
|
-
className="flex items-center gap-1 px-3 py-1 text-xs bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 trails-border-radius-button transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 cursor-pointer"
|
|
284
|
-
aria-label="Close details"
|
|
285
|
-
>
|
|
286
|
-
<span>Close</span>
|
|
287
|
-
<svg
|
|
288
|
-
className="w-3 h-3 transition-transform duration-300 ease-out"
|
|
289
|
-
fill="none"
|
|
290
|
-
stroke="currentColor"
|
|
291
|
-
viewBox="0 0 24 24"
|
|
292
|
-
aria-hidden="true"
|
|
293
|
-
>
|
|
294
|
-
<path
|
|
295
|
-
strokeLinecap="round"
|
|
296
|
-
strokeLinejoin="round"
|
|
297
|
-
strokeWidth={2}
|
|
298
|
-
d="M19 9l-7 7-7-7"
|
|
299
|
-
/>
|
|
300
|
-
</svg>
|
|
301
|
-
</button>
|
|
302
|
-
)}
|
|
303
|
-
</div>
|
|
304
|
-
<div className="space-y-3">
|
|
254
|
+
<div className={`text-sm p-2 space-y-2`}>
|
|
255
|
+
<div className="space-y-2">
|
|
305
256
|
{/* Estimated Time */}
|
|
306
|
-
{quote?.completionEstimateSeconds != null && (
|
|
257
|
+
{/* {quote?.completionEstimateSeconds != null && (
|
|
307
258
|
<div className="flex justify-between items-center">
|
|
308
259
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
309
260
|
Estimated Time:
|
|
310
261
|
<Tooltip message="Estimated time for the transaction to complete across all chains">
|
|
311
|
-
<
|
|
262
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
312
263
|
</Tooltip>
|
|
313
264
|
</span>
|
|
314
265
|
<span className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1">
|
|
@@ -329,79 +280,102 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
329
280
|
~{formatCompletionTime(quote.completionEstimateSeconds)}
|
|
330
281
|
</span>
|
|
331
282
|
</div>
|
|
332
|
-
)}
|
|
283
|
+
)} */}
|
|
333
284
|
|
|
334
285
|
{/* Spacer */}
|
|
335
|
-
<div className="h-2" />
|
|
286
|
+
{/* <div className="h-2" /> */}
|
|
336
287
|
|
|
337
288
|
{/* Gas Costs Section */}
|
|
338
289
|
{quote?.trailsFeeBreakdown &&
|
|
339
290
|
(quote?.trailsFeeBreakdown.originRelayFee ||
|
|
340
291
|
quote?.trailsFeeBreakdown.destinationRelayFee) && (
|
|
341
292
|
<>
|
|
342
|
-
{/*
|
|
343
|
-
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
293
|
+
{/* Total Fees */}
|
|
294
|
+
{(() => {
|
|
295
|
+
// Calculate total gas costs
|
|
296
|
+
const originGasUsd = parseFloat(
|
|
297
|
+
quote.trailsFeeBreakdown?.originRelayFee?.usdValue?.replace(
|
|
298
|
+
/[^0-9.-]/g,
|
|
299
|
+
"",
|
|
300
|
+
) || "0",
|
|
301
|
+
)
|
|
302
|
+
const destGasUsd = parseFloat(
|
|
303
|
+
quote.trailsFeeBreakdown?.destinationRelayFee?.usdValue?.replace(
|
|
304
|
+
/[^0-9.-]/g,
|
|
305
|
+
"",
|
|
306
|
+
) || "0",
|
|
307
|
+
)
|
|
308
|
+
const totalGasUsd = originGasUsd + destGasUsd
|
|
357
309
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
310
|
+
// Calculate total provider costs (including swap fees)
|
|
311
|
+
const providerUsd = parseFloat(
|
|
312
|
+
quote.trailsFeeBreakdown?.providerFee?.usdValue?.replace(
|
|
313
|
+
/[^0-9.-]/g,
|
|
314
|
+
"",
|
|
315
|
+
) || "0",
|
|
316
|
+
)
|
|
317
|
+
const trailsUsd = parseFloat(
|
|
318
|
+
quote.trailsFeeBreakdown?.trailsFee?.usdValue?.replace(
|
|
319
|
+
/[^0-9.-]/g,
|
|
320
|
+
"",
|
|
321
|
+
) || "0",
|
|
322
|
+
)
|
|
323
|
+
const originUsd = parseFloat(
|
|
324
|
+
quote.originAmountUsdDisplay?.replace(/[^0-9.-]/g, "") ||
|
|
325
|
+
"0",
|
|
326
|
+
)
|
|
327
|
+
const destUsd = parseFloat(
|
|
328
|
+
quote.destinationAmountUsdDisplay?.replace(
|
|
329
|
+
/[^0-9.-]/g,
|
|
330
|
+
"",
|
|
331
|
+
) || "0",
|
|
332
|
+
)
|
|
333
|
+
const totalFeesUsd = parseFloat(
|
|
334
|
+
quote.fees?.totalFeeAmountUsdDisplay?.replace(
|
|
335
|
+
/[^0-9.-]/g,
|
|
336
|
+
"",
|
|
337
|
+
) || "0",
|
|
338
|
+
)
|
|
339
|
+
const swapFeesUsd = Math.max(
|
|
340
|
+
0,
|
|
341
|
+
originUsd - destUsd - totalFeesUsd,
|
|
342
|
+
)
|
|
343
|
+
const totalProviderUsd =
|
|
344
|
+
providerUsd + trailsUsd + swapFeesUsd
|
|
345
|
+
|
|
346
|
+
// Sum of all gas costs and all provider costs
|
|
347
|
+
const grandTotalUsd = totalGasUsd + totalProviderUsd
|
|
348
|
+
|
|
349
|
+
if (grandTotalUsd <= 0) return null
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<div className="flex justify-between items-center">
|
|
353
|
+
<span className="text-sm font-semibold text-gray-900 dark:text-white flex items-center gap-1">
|
|
354
|
+
Fees total
|
|
355
|
+
<Tooltip message="The total fees for this transaction, including gas costs and all provider fees">
|
|
356
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
357
|
+
</Tooltip>
|
|
358
|
+
</span>
|
|
359
|
+
<span className="font-semibold text-sm text-gray-900 dark:text-white">
|
|
360
|
+
≈ {formatUsdAmountDisplay(grandTotalUsd)}
|
|
361
|
+
</span>
|
|
362
|
+
</div>
|
|
363
|
+
)
|
|
364
|
+
})()}
|
|
365
|
+
|
|
366
|
+
<div className="h-0" />
|
|
377
367
|
|
|
378
368
|
{/* All Gas Costs */}
|
|
379
369
|
{(quote.trailsFeeBreakdown.originRelayFee ||
|
|
380
370
|
quote.trailsFeeBreakdown.destinationRelayFee) && (
|
|
381
371
|
<div className="flex justify-between items-center">
|
|
382
372
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
383
|
-
All gas costs
|
|
373
|
+
All gas costs
|
|
384
374
|
<Tooltip message="Total gas costs for executing transactions on both origin and destination chains">
|
|
385
|
-
<
|
|
375
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
386
376
|
</Tooltip>
|
|
387
377
|
</span>
|
|
388
|
-
<span className="font-medium text-xs text-gray-
|
|
389
|
-
<svg
|
|
390
|
-
aria-hidden="true"
|
|
391
|
-
focusable="false"
|
|
392
|
-
data-prefix="fas"
|
|
393
|
-
data-icon="gas-pump"
|
|
394
|
-
className="svg-inline--fa fa-gas-pump"
|
|
395
|
-
role="img"
|
|
396
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
397
|
-
viewBox="0 0 512 512"
|
|
398
|
-
width="12"
|
|
399
|
-
>
|
|
400
|
-
<path
|
|
401
|
-
fill="currentColor"
|
|
402
|
-
d="M32 64C32 28.7 60.7 0 96 0H256c35.3 0 64 28.7 64 64V256h8c48.6 0 88 39.4 88 88v32c0 13.3 10.7 24 24 24s24-10.7 24-24V222c-27.6-7.1-48-32.2-48-62V96L384 64c-8.8-8.8-8.8-23.2 0-32s23.2-8.8 32 0l77.3 77.3c12 12 18.7 28.3 18.7 45.3V168v24 32V376c0 39.8-32.2 72-72 72s-72-32.2-72-72V344c0-22.1-17.9-40-40-40h-8V448c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32V64zM96 80v96c0 8.8 7.2 16 16 16H240c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H112c-8.8 0-16 7.2-16 16z"
|
|
403
|
-
/>
|
|
404
|
-
</svg>
|
|
378
|
+
<span className="font-medium text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
405
379
|
{(() => {
|
|
406
380
|
const originGasUsd = parseFloat(
|
|
407
381
|
quote.trailsFeeBreakdown.originRelayFee?.usdValue?.replace(
|
|
@@ -422,8 +396,43 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
422
396
|
</div>
|
|
423
397
|
)}
|
|
424
398
|
|
|
399
|
+
{/* Origin Gas */}
|
|
400
|
+
{quote.trailsFeeBreakdown.originRelayFee && (
|
|
401
|
+
<div className="flex justify-between items-center">
|
|
402
|
+
<span className="text-xs text-gray-400 dark:text-gray-600 flex items-center gap-1">
|
|
403
|
+
Origin Gas
|
|
404
|
+
<ChainImage chainId={quote.originChain.id} size={16} />
|
|
405
|
+
<Tooltip message="Gas fee for executing the transaction on the origin chain">
|
|
406
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
407
|
+
</Tooltip>
|
|
408
|
+
</span>
|
|
409
|
+
<span className="font-medium text-xs text-gray-400 dark:text-gray-600">
|
|
410
|
+
{quote.trailsFeeBreakdown.originRelayFee.usdValue}
|
|
411
|
+
</span>
|
|
412
|
+
</div>
|
|
413
|
+
)}
|
|
414
|
+
|
|
415
|
+
{/* Destination Gas */}
|
|
416
|
+
{quote.trailsFeeBreakdown.destinationRelayFee && (
|
|
417
|
+
<div className="flex justify-between items-center">
|
|
418
|
+
<span className="text-xs text-gray-400 dark:text-gray-600 flex items-center gap-1">
|
|
419
|
+
Destination Gas
|
|
420
|
+
<ChainImage
|
|
421
|
+
chainId={quote.destinationChain.id}
|
|
422
|
+
size={16}
|
|
423
|
+
/>
|
|
424
|
+
<Tooltip message="Gas fee for executing the transaction on the destination chain">
|
|
425
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
426
|
+
</Tooltip>
|
|
427
|
+
</span>
|
|
428
|
+
<span className="font-medium text-xs text-gray-400 dark:text-gray-600">
|
|
429
|
+
{quote.trailsFeeBreakdown.destinationRelayFee.usdValue}
|
|
430
|
+
</span>
|
|
431
|
+
</div>
|
|
432
|
+
)}
|
|
433
|
+
|
|
425
434
|
{/* Spacer */}
|
|
426
|
-
<div className="h-
|
|
435
|
+
<div className="h-1" />
|
|
427
436
|
</>
|
|
428
437
|
)}
|
|
429
438
|
|
|
@@ -456,149 +465,6 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
456
465
|
return (
|
|
457
466
|
<>
|
|
458
467
|
{/* Bridge/Swap Provider Fee */}
|
|
459
|
-
{hasProviderFee &&
|
|
460
|
-
quote.trailsFeeBreakdown.providerFee &&
|
|
461
|
-
(() => {
|
|
462
|
-
const providerFee = quote.trailsFeeBreakdown.providerFee
|
|
463
|
-
const isCrossChain =
|
|
464
|
-
quote.originChain.id !== quote.destinationChain.id
|
|
465
|
-
const providerName = quote.quoteProvider?.name || ""
|
|
466
|
-
|
|
467
|
-
return (
|
|
468
|
-
<div className="flex justify-between items-center">
|
|
469
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
470
|
-
{isCrossChain ? (
|
|
471
|
-
providerName ? (
|
|
472
|
-
<>
|
|
473
|
-
Bridge (
|
|
474
|
-
<a
|
|
475
|
-
href={quote.quoteProvider?.url}
|
|
476
|
-
target="_blank"
|
|
477
|
-
rel="noopener noreferrer"
|
|
478
|
-
className="hover:underline flex items-center gap-0.5"
|
|
479
|
-
>
|
|
480
|
-
{providerName}
|
|
481
|
-
<svg
|
|
482
|
-
className="w-3 h-3"
|
|
483
|
-
fill="none"
|
|
484
|
-
stroke="currentColor"
|
|
485
|
-
viewBox="0 0 24 24"
|
|
486
|
-
aria-hidden="true"
|
|
487
|
-
>
|
|
488
|
-
<path
|
|
489
|
-
strokeLinecap="round"
|
|
490
|
-
strokeLinejoin="round"
|
|
491
|
-
strokeWidth={2}
|
|
492
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
493
|
-
/>
|
|
494
|
-
</svg>
|
|
495
|
-
</a>
|
|
496
|
-
):
|
|
497
|
-
</>
|
|
498
|
-
) : (
|
|
499
|
-
<>Bridge:</>
|
|
500
|
-
)
|
|
501
|
-
) : providerName ? (
|
|
502
|
-
<>
|
|
503
|
-
Liquidity Provider (
|
|
504
|
-
<a
|
|
505
|
-
href={quote.quoteProvider?.url}
|
|
506
|
-
target="_blank"
|
|
507
|
-
rel="noopener noreferrer"
|
|
508
|
-
className="hover:underline flex items-center gap-0.5"
|
|
509
|
-
>
|
|
510
|
-
{providerName}
|
|
511
|
-
<svg
|
|
512
|
-
className="w-3 h-3"
|
|
513
|
-
fill="none"
|
|
514
|
-
stroke="currentColor"
|
|
515
|
-
viewBox="0 0 24 24"
|
|
516
|
-
aria-hidden="true"
|
|
517
|
-
>
|
|
518
|
-
<path
|
|
519
|
-
strokeLinecap="round"
|
|
520
|
-
strokeLinejoin="round"
|
|
521
|
-
strokeWidth={2}
|
|
522
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
523
|
-
/>
|
|
524
|
-
</svg>
|
|
525
|
-
</a>
|
|
526
|
-
):
|
|
527
|
-
</>
|
|
528
|
-
) : (
|
|
529
|
-
<>Liquidity Provider:</>
|
|
530
|
-
)}
|
|
531
|
-
<Tooltip message="Fee charged by the bridge/swap provider for executing the transaction">
|
|
532
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
533
|
-
</Tooltip>
|
|
534
|
-
</span>
|
|
535
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
536
|
-
{providerFee.usdValue}
|
|
537
|
-
</span>
|
|
538
|
-
</div>
|
|
539
|
-
)
|
|
540
|
-
})()}
|
|
541
|
-
|
|
542
|
-
{/* Swap Fees (implicit costs) */}
|
|
543
|
-
{(() => {
|
|
544
|
-
// Calculate swap fees: (originAmount - destinationAmount) - totalFees
|
|
545
|
-
const originUsd = parseFloat(
|
|
546
|
-
quote.originAmountUsdDisplay?.replace(/[^0-9.-]/g, "") ||
|
|
547
|
-
"0",
|
|
548
|
-
)
|
|
549
|
-
const destUsd = parseFloat(
|
|
550
|
-
quote.destinationAmountUsdDisplay?.replace(
|
|
551
|
-
/[^0-9.-]/g,
|
|
552
|
-
"",
|
|
553
|
-
) || "0",
|
|
554
|
-
)
|
|
555
|
-
const totalFeesUsd = parseFloat(
|
|
556
|
-
quote.fees?.totalFeeAmountUsdDisplay?.replace(
|
|
557
|
-
/[^0-9.-]/g,
|
|
558
|
-
"",
|
|
559
|
-
) || "0",
|
|
560
|
-
)
|
|
561
|
-
|
|
562
|
-
const swapFeesUsd = originUsd - destUsd - totalFeesUsd
|
|
563
|
-
|
|
564
|
-
// Only show if swap fees > 0
|
|
565
|
-
if (swapFeesUsd <= 0) return null
|
|
566
|
-
|
|
567
|
-
return (
|
|
568
|
-
<div className="flex justify-between items-center">
|
|
569
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
570
|
-
Swap:
|
|
571
|
-
<Tooltip message="Implicit costs including DEX fees, liquidity provider fees, and routing costs">
|
|
572
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
573
|
-
</Tooltip>
|
|
574
|
-
</span>
|
|
575
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
576
|
-
{formatUsdAmountDisplay(swapFeesUsd)}
|
|
577
|
-
</span>
|
|
578
|
-
</div>
|
|
579
|
-
)
|
|
580
|
-
})()}
|
|
581
|
-
|
|
582
|
-
{/* Trails Platform Fee */}
|
|
583
|
-
{hasTrailsFee &&
|
|
584
|
-
quote.trailsFeeBreakdown.trailsFee &&
|
|
585
|
-
(() => {
|
|
586
|
-
const trailsFee = quote.trailsFeeBreakdown.trailsFee
|
|
587
|
-
|
|
588
|
-
return (
|
|
589
|
-
<div className="flex justify-between items-center">
|
|
590
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
591
|
-
Trails:
|
|
592
|
-
<Tooltip message="Platform fee for using the Trails service">
|
|
593
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
594
|
-
</Tooltip>
|
|
595
|
-
</span>
|
|
596
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
597
|
-
{trailsFee.usdValue}
|
|
598
|
-
</span>
|
|
599
|
-
</div>
|
|
600
|
-
)
|
|
601
|
-
})()}
|
|
602
468
|
|
|
603
469
|
{/* All Provider Costs */}
|
|
604
470
|
{(hasProviderFee || hasTrailsFee) &&
|
|
@@ -640,57 +506,116 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
640
506
|
originUsd - destUsd - totalFeesUsd,
|
|
641
507
|
)
|
|
642
508
|
|
|
643
|
-
const totalProviderUsd =
|
|
644
|
-
providerUsd + trailsUsd + swapFeesUsd
|
|
509
|
+
const totalProviderUsd =
|
|
510
|
+
providerUsd + trailsUsd + swapFeesUsd
|
|
511
|
+
|
|
512
|
+
return (
|
|
513
|
+
<div className="flex justify-between items-center">
|
|
514
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
515
|
+
All provider costs
|
|
516
|
+
<Tooltip message="Total fees charged by providers, including bridge/swap, platform fees, and implicit swap costs">
|
|
517
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
518
|
+
</Tooltip>
|
|
519
|
+
</span>
|
|
520
|
+
<span className="font-medium text-xs text-gray-600 dark:text-gray-400">
|
|
521
|
+
{formatUsdAmountDisplay(totalProviderUsd)}
|
|
522
|
+
</span>
|
|
523
|
+
</div>
|
|
524
|
+
)
|
|
525
|
+
})()}
|
|
526
|
+
|
|
527
|
+
{hasProviderFee &&
|
|
528
|
+
quote.trailsFeeBreakdown.providerFee &&
|
|
529
|
+
(() => {
|
|
530
|
+
const providerFee = quote.trailsFeeBreakdown.providerFee
|
|
531
|
+
const isCrossChain =
|
|
532
|
+
quote.originChain.id !== quote.destinationChain.id
|
|
533
|
+
const providerName = quote.quoteProvider?.name || ""
|
|
645
534
|
|
|
646
535
|
return (
|
|
647
536
|
<div className="flex justify-between items-center">
|
|
648
|
-
<span className="text-xs text-gray-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
537
|
+
<span className="text-xs text-gray-400 dark:text-gray-600 flex items-center gap-1">
|
|
538
|
+
{isCrossChain ? (
|
|
539
|
+
providerName ? (
|
|
540
|
+
<>
|
|
541
|
+
Bridge
|
|
542
|
+
<span>
|
|
543
|
+
(
|
|
544
|
+
<a
|
|
545
|
+
href={quote.quoteProvider?.url}
|
|
546
|
+
target="_blank"
|
|
547
|
+
rel="noopener noreferrer"
|
|
548
|
+
className="hover:underline inline-flex items-center gap-0.5 text-blue-500"
|
|
549
|
+
>
|
|
550
|
+
{providerName}
|
|
551
|
+
<svg
|
|
552
|
+
className="w-3 h-3"
|
|
553
|
+
fill="none"
|
|
554
|
+
stroke="currentColor"
|
|
555
|
+
viewBox="0 0 24 24"
|
|
556
|
+
aria-hidden="true"
|
|
557
|
+
>
|
|
558
|
+
<path
|
|
559
|
+
strokeLinecap="round"
|
|
560
|
+
strokeLinejoin="round"
|
|
561
|
+
strokeWidth={2}
|
|
562
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
563
|
+
/>
|
|
564
|
+
</svg>
|
|
565
|
+
</a>
|
|
566
|
+
)
|
|
567
|
+
</span>
|
|
568
|
+
</>
|
|
569
|
+
) : (
|
|
570
|
+
<>Bridge:</>
|
|
571
|
+
)
|
|
572
|
+
) : providerName ? (
|
|
573
|
+
<>
|
|
574
|
+
Liquidity Provider{" "}
|
|
575
|
+
<span>
|
|
576
|
+
(
|
|
577
|
+
<a
|
|
578
|
+
href={quote.quoteProvider?.url}
|
|
579
|
+
target="_blank"
|
|
580
|
+
rel="noopener noreferrer"
|
|
581
|
+
className="hover:underline inline-flex items-center gap-0.5 text-blue-500"
|
|
582
|
+
>
|
|
583
|
+
{providerName}
|
|
584
|
+
<svg
|
|
585
|
+
className="w-3 h-3"
|
|
586
|
+
fill="none"
|
|
587
|
+
stroke="currentColor"
|
|
588
|
+
viewBox="0 0 24 24"
|
|
589
|
+
aria-hidden="true"
|
|
590
|
+
>
|
|
591
|
+
<path
|
|
592
|
+
strokeLinecap="round"
|
|
593
|
+
strokeLinejoin="round"
|
|
594
|
+
strokeWidth={2}
|
|
595
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
596
|
+
/>
|
|
597
|
+
</svg>
|
|
598
|
+
</a>
|
|
599
|
+
)
|
|
600
|
+
</span>
|
|
601
|
+
</>
|
|
602
|
+
) : (
|
|
603
|
+
<>Liquidity Provider</>
|
|
604
|
+
)}
|
|
605
|
+
<Tooltip message="Fee charged by the bridge/swap provider for executing the transaction">
|
|
606
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
652
607
|
</Tooltip>
|
|
653
608
|
</span>
|
|
654
|
-
<span className="font-medium text-xs text-gray-
|
|
655
|
-
{
|
|
609
|
+
<span className="font-medium text-xs text-gray-400 dark:text-gray-600">
|
|
610
|
+
{providerFee.usdValue}
|
|
656
611
|
</span>
|
|
657
612
|
</div>
|
|
658
613
|
)
|
|
659
614
|
})()}
|
|
660
615
|
|
|
661
|
-
{/*
|
|
662
|
-
<div className="h-2" />
|
|
663
|
-
|
|
664
|
-
{/* Total Fees */}
|
|
616
|
+
{/* Swap Fees (implicit costs) */}
|
|
665
617
|
{(() => {
|
|
666
|
-
// Calculate
|
|
667
|
-
const originGasUsd = parseFloat(
|
|
668
|
-
quote.trailsFeeBreakdown?.originRelayFee?.usdValue?.replace(
|
|
669
|
-
/[^0-9.-]/g,
|
|
670
|
-
"",
|
|
671
|
-
) || "0",
|
|
672
|
-
)
|
|
673
|
-
const destGasUsd = parseFloat(
|
|
674
|
-
quote.trailsFeeBreakdown?.destinationRelayFee?.usdValue?.replace(
|
|
675
|
-
/[^0-9.-]/g,
|
|
676
|
-
"",
|
|
677
|
-
) || "0",
|
|
678
|
-
)
|
|
679
|
-
const totalGasUsd = originGasUsd + destGasUsd
|
|
680
|
-
|
|
681
|
-
// Calculate total provider costs (including swap fees)
|
|
682
|
-
const providerUsd = parseFloat(
|
|
683
|
-
quote.trailsFeeBreakdown?.providerFee?.usdValue?.replace(
|
|
684
|
-
/[^0-9.-]/g,
|
|
685
|
-
"",
|
|
686
|
-
) || "0",
|
|
687
|
-
)
|
|
688
|
-
const trailsUsd = parseFloat(
|
|
689
|
-
quote.trailsFeeBreakdown?.trailsFee?.usdValue?.replace(
|
|
690
|
-
/[^0-9.-]/g,
|
|
691
|
-
"",
|
|
692
|
-
) || "0",
|
|
693
|
-
)
|
|
618
|
+
// Calculate swap fees: (originAmount - destinationAmount) - totalFees
|
|
694
619
|
const originUsd = parseFloat(
|
|
695
620
|
quote.originAmountUsdDisplay?.replace(/[^0-9.-]/g, "") ||
|
|
696
621
|
"0",
|
|
@@ -707,39 +632,53 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
707
632
|
"",
|
|
708
633
|
) || "0",
|
|
709
634
|
)
|
|
710
|
-
const swapFeesUsd = Math.max(
|
|
711
|
-
0,
|
|
712
|
-
originUsd - destUsd - totalFeesUsd,
|
|
713
|
-
)
|
|
714
|
-
const totalProviderUsd =
|
|
715
|
-
providerUsd + trailsUsd + swapFeesUsd
|
|
716
635
|
|
|
717
|
-
|
|
718
|
-
const grandTotalUsd = totalGasUsd + totalProviderUsd
|
|
636
|
+
const swapFeesUsd = originUsd - destUsd - totalFeesUsd
|
|
719
637
|
|
|
720
|
-
if
|
|
638
|
+
// Only show if swap fees > 0
|
|
639
|
+
if (swapFeesUsd <= 0) return null
|
|
721
640
|
|
|
722
641
|
return (
|
|
723
642
|
<div className="flex justify-between items-center">
|
|
724
|
-
<span className="text-xs
|
|
725
|
-
|
|
726
|
-
<Tooltip message="
|
|
727
|
-
<
|
|
643
|
+
<span className="text-xs text-gray-400 dark:text-gray-600 flex items-center gap-1">
|
|
644
|
+
Swap
|
|
645
|
+
<Tooltip message="Implicit costs including DEX fees, liquidity provider fees, and routing costs">
|
|
646
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
728
647
|
</Tooltip>
|
|
729
648
|
</span>
|
|
730
|
-
<span className="font-
|
|
731
|
-
|
|
649
|
+
<span className="font-medium text-xs text-gray-400 dark:text-gray-600">
|
|
650
|
+
{formatUsdAmountDisplay(swapFeesUsd)}
|
|
732
651
|
</span>
|
|
733
652
|
</div>
|
|
734
653
|
)
|
|
735
654
|
})()}
|
|
736
655
|
|
|
737
|
-
{/*
|
|
738
|
-
|
|
656
|
+
{/* Trails Platform Fee */}
|
|
657
|
+
{hasTrailsFee &&
|
|
658
|
+
quote.trailsFeeBreakdown.trailsFee &&
|
|
659
|
+
(() => {
|
|
660
|
+
const trailsFee = quote.trailsFeeBreakdown.trailsFee
|
|
661
|
+
|
|
662
|
+
return (
|
|
663
|
+
<div className="flex justify-between items-center">
|
|
664
|
+
<span className="text-xs text-gray-400 dark:text-gray-600 flex items-center gap-1">
|
|
665
|
+
Trails
|
|
666
|
+
<Tooltip message="Platform fee for using the Trails service">
|
|
667
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
668
|
+
</Tooltip>
|
|
669
|
+
</span>
|
|
670
|
+
<span className="font-medium text-xs text-gray-400 dark:text-gray-600">
|
|
671
|
+
{trailsFee.usdValue}
|
|
672
|
+
</span>
|
|
673
|
+
</div>
|
|
674
|
+
)
|
|
675
|
+
})()}
|
|
739
676
|
</>
|
|
740
677
|
)
|
|
741
678
|
})()}
|
|
742
679
|
|
|
680
|
+
<div className="h-px bg-gray-200 dark:bg-gray-800 my-4" />
|
|
681
|
+
|
|
743
682
|
{/* Transaction Details Section */}
|
|
744
683
|
{(() => {
|
|
745
684
|
const hasSlippage =
|
|
@@ -755,30 +694,32 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
755
694
|
|
|
756
695
|
return (
|
|
757
696
|
<>
|
|
758
|
-
<div
|
|
759
|
-
|
|
697
|
+
<div>
|
|
698
|
+
<span className="text-sm font-semibold text-gray-900 dark:text-white flex items-center gap-1">
|
|
699
|
+
Transaction details
|
|
700
|
+
</span>
|
|
760
701
|
</div>
|
|
761
702
|
|
|
762
703
|
{/* Intent ID */}
|
|
763
704
|
{hasIntentId && (
|
|
764
705
|
<div className="flex justify-between items-center gap-2">
|
|
765
706
|
<span className="text-xs text-gray-600 dark:text-gray-400">
|
|
766
|
-
Intent ID
|
|
707
|
+
Intent ID
|
|
767
708
|
</span>
|
|
768
|
-
<div className="flex items-center gap-
|
|
709
|
+
<div className="flex items-center gap-1 text-xs font-medium text-gray-600 dark:text-gray-400">
|
|
769
710
|
<span title={quote.intentId ?? undefined}>
|
|
770
|
-
{truncateAddress(quote?.intentId ?? "",
|
|
711
|
+
{truncateAddress(quote?.intentId ?? "", 9, 3)}
|
|
771
712
|
</span>
|
|
772
713
|
<button
|
|
773
714
|
type="button"
|
|
774
715
|
onClick={handleCopyIntentId}
|
|
775
|
-
className="p-
|
|
716
|
+
className="p-0.5 rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
|
|
776
717
|
aria-label="Copy intent ID"
|
|
777
718
|
>
|
|
778
719
|
{intentIdCopied ? (
|
|
779
|
-
<Check className="w-3
|
|
720
|
+
<Check className="w-3 h-3 text-emerald-500" />
|
|
780
721
|
) : (
|
|
781
|
-
<Copy className="w-3
|
|
722
|
+
<Copy className="w-3 h-3 text-gray-500 dark:text-gray-400" />
|
|
782
723
|
)}
|
|
783
724
|
</button>
|
|
784
725
|
</div>
|
|
@@ -789,12 +730,12 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
789
730
|
{hasSlippage && (
|
|
790
731
|
<div className="flex justify-between items-center">
|
|
791
732
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
792
|
-
Max slippage
|
|
733
|
+
Max slippage
|
|
793
734
|
<Tooltip message="The maximum percentage by which the exchange rate can change before the transaction fails. Higher slippage means more tolerance for price changes but potentially worse rates.">
|
|
794
|
-
<
|
|
735
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
795
736
|
</Tooltip>
|
|
796
737
|
</span>
|
|
797
|
-
<span className="font-medium text-xs text-gray-
|
|
738
|
+
<span className="font-medium text-xs text-gray-600 dark:text-gray-400">
|
|
798
739
|
{quote.slippageTolerance}%
|
|
799
740
|
</span>
|
|
800
741
|
</div>
|
|
@@ -805,9 +746,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
805
746
|
<div className="space-y-1">
|
|
806
747
|
<div className="flex justify-between items-center">
|
|
807
748
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
808
|
-
Price impact
|
|
749
|
+
Price impact
|
|
809
750
|
<Tooltip message="The percentage change in the token price caused by your trade. Higher impact means your trade affects the market price more, potentially resulting in worse rates.">
|
|
810
|
-
<
|
|
751
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
811
752
|
</Tooltip>
|
|
812
753
|
</span>
|
|
813
754
|
<span
|
|
@@ -816,7 +757,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
816
757
|
? "text-red-600 dark:text-red-400"
|
|
817
758
|
: Math.abs(Number(quote.priceImpact)) > 0.5
|
|
818
759
|
? "text-orange-600 dark:text-orange-400"
|
|
819
|
-
: "text-gray-
|
|
760
|
+
: "text-gray-600 dark:text-gray-400"
|
|
820
761
|
}`}
|
|
821
762
|
>
|
|
822
763
|
{Math.abs(Number(quote.priceImpact)) > 0.5 && (
|
|
@@ -853,401 +794,351 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
853
794
|
)
|
|
854
795
|
})()}
|
|
855
796
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
<svg
|
|
878
|
-
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
879
|
-
showMoreInfo ? "rotate-180" : ""
|
|
880
|
-
}`}
|
|
881
|
-
fill="none"
|
|
882
|
-
stroke="currentColor"
|
|
883
|
-
viewBox="0 0 24 24"
|
|
884
|
-
aria-hidden="true"
|
|
885
|
-
>
|
|
886
|
-
<path
|
|
887
|
-
strokeLinecap="round"
|
|
888
|
-
strokeLinejoin="round"
|
|
889
|
-
strokeWidth={2}
|
|
890
|
-
d="M19 9l-7 7-7-7"
|
|
891
|
-
/>
|
|
892
|
-
</svg>
|
|
893
|
-
</button>
|
|
797
|
+
<div className="space-y-3 pt-2">
|
|
798
|
+
{/* Exchange Rate */}
|
|
799
|
+
{quote?.originTokenRate && quote?.destinationTokenRate && (
|
|
800
|
+
<div className="flex justify-between items-center">
|
|
801
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
802
|
+
Exchange Rate
|
|
803
|
+
<Tooltip message="The current exchange rate between the origin and destination tokens">
|
|
804
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
805
|
+
</Tooltip>
|
|
806
|
+
</span>
|
|
807
|
+
<button
|
|
808
|
+
type="button"
|
|
809
|
+
onClick={() => setShowOriginRate(!showOriginRate)}
|
|
810
|
+
className="font-medium text-xs hover:underline cursor-pointer text-gray-600 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
|
811
|
+
>
|
|
812
|
+
{showOriginRate
|
|
813
|
+
? quote.originTokenRate
|
|
814
|
+
: quote.destinationTokenRate}
|
|
815
|
+
</button>
|
|
816
|
+
</div>
|
|
817
|
+
)}
|
|
894
818
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
<div className="
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
<
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
819
|
+
{/* Origin Transfer Amount */}
|
|
820
|
+
{quote?.originAmount &&
|
|
821
|
+
quote?.originToken.symbol &&
|
|
822
|
+
quote?.originChain.id && (
|
|
823
|
+
<div className="flex justify-between items-start">
|
|
824
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
825
|
+
Origin Transfer Amount
|
|
826
|
+
<Tooltip message="The amount of tokens you will send from the origin chain">
|
|
827
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
828
|
+
</Tooltip>
|
|
829
|
+
</span>
|
|
830
|
+
<div className="text-right">
|
|
831
|
+
{quote.originToken.contractAddress ===
|
|
832
|
+
"0x0000000000000000000000000000000000000000" ? (
|
|
833
|
+
<>
|
|
834
|
+
<div className="font-medium text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1 justify-end">
|
|
835
|
+
<TokenImage
|
|
836
|
+
imageUrl={quote.originToken.imageUrl}
|
|
837
|
+
symbol={quote.originToken.symbol}
|
|
838
|
+
chainId={quote.originChain.id}
|
|
839
|
+
contractAddress={
|
|
840
|
+
quote.originToken.contractAddress
|
|
841
|
+
}
|
|
842
|
+
size={16}
|
|
843
|
+
/>
|
|
844
|
+
{quote.originAmountDisplay}{" "}
|
|
845
|
+
{quote.originToken.symbol}
|
|
846
|
+
</div>
|
|
847
|
+
{quote.originAmountUsdDisplay && (
|
|
848
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
849
|
+
≈ {quote.originAmountUsdDisplay}
|
|
850
|
+
</div>
|
|
851
|
+
)}
|
|
852
|
+
</>
|
|
853
|
+
) : (
|
|
854
|
+
<>
|
|
855
|
+
<a
|
|
856
|
+
href={getExplorerUrlForAddress({
|
|
857
|
+
address: quote.originToken.contractAddress,
|
|
858
|
+
chainId: quote.originChain.id,
|
|
859
|
+
})}
|
|
860
|
+
target="_blank"
|
|
861
|
+
rel="noopener noreferrer"
|
|
862
|
+
className="hover:underline cursor-pointer"
|
|
863
|
+
>
|
|
864
|
+
<div className="font-medium text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1 justify-end">
|
|
865
|
+
<TokenImage
|
|
866
|
+
imageUrl={quote.originToken.imageUrl}
|
|
867
|
+
symbol={quote.originToken.symbol}
|
|
868
|
+
chainId={quote.originChain.id}
|
|
869
|
+
contractAddress={
|
|
870
|
+
quote.originToken.contractAddress
|
|
871
|
+
}
|
|
872
|
+
size={16}
|
|
873
|
+
/>
|
|
874
|
+
{quote.originAmountDisplay}{" "}
|
|
875
|
+
{quote.originToken.symbol}
|
|
876
|
+
</div>
|
|
877
|
+
</a>
|
|
878
|
+
{quote.originAmountUsdDisplay && (
|
|
879
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
880
|
+
≈ {quote.originAmountUsdDisplay}
|
|
881
|
+
</div>
|
|
882
|
+
)}
|
|
883
|
+
</>
|
|
884
|
+
)}
|
|
922
885
|
</div>
|
|
923
|
-
|
|
886
|
+
</div>
|
|
887
|
+
)}
|
|
924
888
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
</>
|
|
959
|
-
) : (
|
|
960
|
-
<>
|
|
961
|
-
<a
|
|
962
|
-
href={getExplorerUrlForAddress({
|
|
963
|
-
address: quote.originToken.contractAddress,
|
|
964
|
-
chainId: quote.originChain.id,
|
|
965
|
-
})}
|
|
966
|
-
target="_blank"
|
|
967
|
-
rel="noopener noreferrer"
|
|
968
|
-
className="hover:underline cursor-pointer"
|
|
969
|
-
>
|
|
970
|
-
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
971
|
-
<TokenImage
|
|
972
|
-
imageUrl={quote.originToken.imageUrl}
|
|
973
|
-
symbol={quote.originToken.symbol}
|
|
974
|
-
chainId={quote.originChain.id}
|
|
975
|
-
contractAddress={
|
|
976
|
-
quote.originToken.contractAddress
|
|
977
|
-
}
|
|
978
|
-
size={16}
|
|
979
|
-
/>
|
|
980
|
-
{quote.originAmountDisplay}{" "}
|
|
981
|
-
{quote.originToken.symbol}
|
|
982
|
-
</div>
|
|
983
|
-
</a>
|
|
984
|
-
{quote.originAmountUsdDisplay && (
|
|
985
|
-
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
986
|
-
≈ {quote.originAmountUsdDisplay}
|
|
987
|
-
</div>
|
|
988
|
-
)}
|
|
989
|
-
</>
|
|
889
|
+
{/* Destination Target Amount */}
|
|
890
|
+
{quote?.destinationToken.symbol &&
|
|
891
|
+
quote?.destinationAmount &&
|
|
892
|
+
quote?.destinationAmountUsdDisplay &&
|
|
893
|
+
quote?.destinationChain.id && (
|
|
894
|
+
<div className="flex justify-between items-start">
|
|
895
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
896
|
+
Destination Target Amount
|
|
897
|
+
<Tooltip message="The amount of tokens you will receive on the destination chain after the swap and/or bridge">
|
|
898
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
899
|
+
</Tooltip>
|
|
900
|
+
</span>
|
|
901
|
+
<div className="text-right">
|
|
902
|
+
{quote.destinationToken.contractAddress ===
|
|
903
|
+
"0x0000000000000000000000000000000000000000" ? (
|
|
904
|
+
<>
|
|
905
|
+
<div className="font-medium text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1 justify-end">
|
|
906
|
+
<TokenImage
|
|
907
|
+
imageUrl={quote.destinationToken.imageUrl}
|
|
908
|
+
symbol={quote.destinationToken.symbol}
|
|
909
|
+
chainId={quote.destinationChain.id}
|
|
910
|
+
contractAddress={
|
|
911
|
+
quote.destinationToken.contractAddress
|
|
912
|
+
}
|
|
913
|
+
size={16}
|
|
914
|
+
/>
|
|
915
|
+
{quote.destinationAmountDisplay}{" "}
|
|
916
|
+
{quote.destinationToken.symbol}
|
|
917
|
+
</div>
|
|
918
|
+
{quote.destinationAmountUsdDisplay && (
|
|
919
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
920
|
+
≈ {quote.destinationAmountUsdDisplay}
|
|
921
|
+
</div>
|
|
990
922
|
)}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
{quote.destinationAmountDisplay}{" "}
|
|
1022
|
-
{quote.destinationToken.symbol}
|
|
1023
|
-
</div>
|
|
1024
|
-
{quote.destinationAmountUsdDisplay && (
|
|
1025
|
-
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
1026
|
-
≈ {quote.destinationAmountUsdDisplay}
|
|
1027
|
-
</div>
|
|
1028
|
-
)}
|
|
1029
|
-
</>
|
|
1030
|
-
) : (
|
|
1031
|
-
<>
|
|
1032
|
-
<a
|
|
1033
|
-
href={getExplorerUrlForAddress({
|
|
1034
|
-
address:
|
|
1035
|
-
quote.destinationToken.contractAddress,
|
|
1036
|
-
chainId: quote.destinationChain.id,
|
|
1037
|
-
})}
|
|
1038
|
-
target="_blank"
|
|
1039
|
-
rel="noopener noreferrer"
|
|
1040
|
-
className="hover:underline cursor-pointer"
|
|
1041
|
-
>
|
|
1042
|
-
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
1043
|
-
<TokenImage
|
|
1044
|
-
imageUrl={quote.destinationToken.imageUrl}
|
|
1045
|
-
symbol={quote.destinationToken.symbol}
|
|
1046
|
-
chainId={quote.destinationChain.id}
|
|
1047
|
-
contractAddress={
|
|
1048
|
-
quote.destinationToken.contractAddress
|
|
1049
|
-
}
|
|
1050
|
-
size={16}
|
|
1051
|
-
/>
|
|
1052
|
-
{quote.destinationAmountDisplay}{" "}
|
|
1053
|
-
{quote.destinationToken.symbol}
|
|
1054
|
-
</div>
|
|
1055
|
-
</a>
|
|
1056
|
-
{quote.destinationAmountUsdDisplay && (
|
|
1057
|
-
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
1058
|
-
≈ {quote.destinationAmountUsdDisplay}
|
|
1059
|
-
</div>
|
|
1060
|
-
)}
|
|
1061
|
-
</>
|
|
923
|
+
</>
|
|
924
|
+
) : (
|
|
925
|
+
<>
|
|
926
|
+
<a
|
|
927
|
+
href={getExplorerUrlForAddress({
|
|
928
|
+
address: quote.destinationToken.contractAddress,
|
|
929
|
+
chainId: quote.destinationChain.id,
|
|
930
|
+
})}
|
|
931
|
+
target="_blank"
|
|
932
|
+
rel="noopener noreferrer"
|
|
933
|
+
className="hover:underline cursor-pointer"
|
|
934
|
+
>
|
|
935
|
+
<div className="font-medium text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1 justify-end">
|
|
936
|
+
<TokenImage
|
|
937
|
+
imageUrl={quote.destinationToken.imageUrl}
|
|
938
|
+
symbol={quote.destinationToken.symbol}
|
|
939
|
+
chainId={quote.destinationChain.id}
|
|
940
|
+
contractAddress={
|
|
941
|
+
quote.destinationToken.contractAddress
|
|
942
|
+
}
|
|
943
|
+
size={16}
|
|
944
|
+
/>
|
|
945
|
+
{quote.destinationAmountDisplay}{" "}
|
|
946
|
+
{quote.destinationToken.symbol}
|
|
947
|
+
</div>
|
|
948
|
+
</a>
|
|
949
|
+
{quote.destinationAmountUsdDisplay && (
|
|
950
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
951
|
+
≈ {quote.destinationAmountUsdDisplay}
|
|
952
|
+
</div>
|
|
1062
953
|
)}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
)}
|
|
1066
|
-
|
|
1067
|
-
{/* Origin Deposit Address */}
|
|
1068
|
-
{quote?.originDepositAddress && (
|
|
1069
|
-
<div className="flex justify-between items-center">
|
|
1070
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
1071
|
-
Origin Deposit Address:
|
|
1072
|
-
<Tooltip message="This is the intent address to deposit to that will then execute the swap and/or bridge">
|
|
1073
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
1074
|
-
</Tooltip>
|
|
1075
|
-
</span>
|
|
1076
|
-
<a
|
|
1077
|
-
href={getExplorerUrlForAddress({
|
|
1078
|
-
address: quote.originDepositAddress,
|
|
1079
|
-
chainId: quote.originChain.id,
|
|
1080
|
-
})}
|
|
1081
|
-
target="_blank"
|
|
1082
|
-
rel="noopener noreferrer"
|
|
1083
|
-
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
1084
|
-
>
|
|
1085
|
-
{truncateAddress(quote.originDepositAddress)}
|
|
1086
|
-
<svg
|
|
1087
|
-
className="w-3 h-3"
|
|
1088
|
-
fill="none"
|
|
1089
|
-
stroke="currentColor"
|
|
1090
|
-
viewBox="0 0 24 24"
|
|
1091
|
-
aria-hidden="true"
|
|
1092
|
-
>
|
|
1093
|
-
<path
|
|
1094
|
-
strokeLinecap="round"
|
|
1095
|
-
strokeLinejoin="round"
|
|
1096
|
-
strokeWidth={2}
|
|
1097
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1098
|
-
/>
|
|
1099
|
-
</svg>
|
|
1100
|
-
</a>
|
|
954
|
+
</>
|
|
955
|
+
)}
|
|
1101
956
|
</div>
|
|
1102
|
-
|
|
957
|
+
</div>
|
|
958
|
+
)}
|
|
1103
959
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
</div>
|
|
1141
|
-
)}
|
|
960
|
+
{/* Origin Deposit Address */}
|
|
961
|
+
{quote?.originDepositAddress && (
|
|
962
|
+
<div className="flex justify-between items-center">
|
|
963
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
964
|
+
Origin Deposit Address
|
|
965
|
+
<Tooltip message="This is the intent address to deposit to that will then execute the swap and/or bridge">
|
|
966
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
967
|
+
</Tooltip>
|
|
968
|
+
</span>
|
|
969
|
+
<a
|
|
970
|
+
href={getExplorerUrlForAddress({
|
|
971
|
+
address: quote.originDepositAddress,
|
|
972
|
+
chainId: quote.originChain.id,
|
|
973
|
+
})}
|
|
974
|
+
target="_blank"
|
|
975
|
+
rel="noopener noreferrer"
|
|
976
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-blue-500"
|
|
977
|
+
>
|
|
978
|
+
{truncateAddress(quote.originDepositAddress)}
|
|
979
|
+
<svg
|
|
980
|
+
className="w-3 h-3"
|
|
981
|
+
fill="none"
|
|
982
|
+
stroke="currentColor"
|
|
983
|
+
viewBox="0 0 24 24"
|
|
984
|
+
aria-hidden="true"
|
|
985
|
+
>
|
|
986
|
+
<path
|
|
987
|
+
strokeLinecap="round"
|
|
988
|
+
strokeLinejoin="round"
|
|
989
|
+
strokeWidth={2}
|
|
990
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
991
|
+
/>
|
|
992
|
+
</svg>
|
|
993
|
+
</a>
|
|
994
|
+
</div>
|
|
995
|
+
)}
|
|
1142
996
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
997
|
+
{/* Destination Deposit Address */}
|
|
998
|
+
{quote?.destinationDepositAddress &&
|
|
999
|
+
quote?.destinationDepositAddress !==
|
|
1000
|
+
quote?.originDepositAddress && (
|
|
1001
|
+
<div className="flex justify-between items-center">
|
|
1002
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
1003
|
+
Destination Deposit Address
|
|
1004
|
+
<Tooltip message="This is the address that will receive the tokens after any swap and/or bridge from the origin chain">
|
|
1005
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
1006
|
+
</Tooltip>
|
|
1007
|
+
</span>
|
|
1008
|
+
<a
|
|
1009
|
+
href={getExplorerUrlForAddress({
|
|
1010
|
+
address: quote.destinationDepositAddress,
|
|
1011
|
+
chainId: quote.destinationChain.id,
|
|
1012
|
+
})}
|
|
1013
|
+
target="_blank"
|
|
1014
|
+
rel="noopener noreferrer"
|
|
1015
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-blue-500"
|
|
1016
|
+
>
|
|
1017
|
+
{truncateAddress(quote.destinationDepositAddress)}
|
|
1018
|
+
<svg
|
|
1019
|
+
className="w-3 h-3"
|
|
1020
|
+
fill="none"
|
|
1021
|
+
stroke="currentColor"
|
|
1022
|
+
viewBox="0 0 24 24"
|
|
1023
|
+
aria-hidden="true"
|
|
1160
1024
|
>
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
strokeLinejoin="round"
|
|
1172
|
-
strokeWidth={2}
|
|
1173
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1174
|
-
/>
|
|
1175
|
-
</svg>
|
|
1176
|
-
</a>
|
|
1177
|
-
</div>
|
|
1178
|
-
)}
|
|
1025
|
+
<path
|
|
1026
|
+
strokeLinecap="round"
|
|
1027
|
+
strokeLinejoin="round"
|
|
1028
|
+
strokeWidth={2}
|
|
1029
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1030
|
+
/>
|
|
1031
|
+
</svg>
|
|
1032
|
+
</a>
|
|
1033
|
+
</div>
|
|
1034
|
+
)}
|
|
1179
1035
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1036
|
+
{/* Destination Target Address */}
|
|
1037
|
+
{quote?.destinationAddress && (
|
|
1038
|
+
<div className="flex justify-between items-center">
|
|
1039
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
1040
|
+
Destination Target Address
|
|
1041
|
+
<Tooltip message="This is the final execution address or recipient address">
|
|
1042
|
+
<Info className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
1043
|
+
</Tooltip>
|
|
1044
|
+
</span>
|
|
1045
|
+
<a
|
|
1046
|
+
href={getExplorerUrlForAddress({
|
|
1047
|
+
address: quote.destinationAddress,
|
|
1048
|
+
chainId: quote.destinationChain.id,
|
|
1049
|
+
})}
|
|
1050
|
+
target="_blank"
|
|
1051
|
+
rel="noopener noreferrer"
|
|
1052
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-blue-500"
|
|
1053
|
+
>
|
|
1054
|
+
{truncateAddress(quote.destinationAddress)}
|
|
1055
|
+
<svg
|
|
1056
|
+
className="w-3 h-3"
|
|
1057
|
+
fill="none"
|
|
1058
|
+
stroke="currentColor"
|
|
1059
|
+
viewBox="0 0 24 24"
|
|
1060
|
+
aria-hidden="true"
|
|
1061
|
+
>
|
|
1062
|
+
<path
|
|
1063
|
+
strokeLinecap="round"
|
|
1064
|
+
strokeLinejoin="round"
|
|
1065
|
+
strokeWidth={2}
|
|
1066
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1067
|
+
/>
|
|
1068
|
+
</svg>
|
|
1069
|
+
</a>
|
|
1070
|
+
</div>
|
|
1071
|
+
)}
|
|
1072
|
+
|
|
1073
|
+
{/* Custom Calldata */}
|
|
1074
|
+
{quote?.destinationCalldata && (
|
|
1075
|
+
<div className="space-y-2">
|
|
1076
|
+
<button
|
|
1077
|
+
type="button"
|
|
1078
|
+
onClick={() => {
|
|
1079
|
+
setShowCalldata(!showCalldata)
|
|
1080
|
+
// Auto-scroll to calldata when expanding
|
|
1081
|
+
if (!showCalldata) {
|
|
1082
|
+
setTimeout(() => {
|
|
1083
|
+
if (calldataRef.current) {
|
|
1084
|
+
calldataRef.current.scrollIntoView({
|
|
1085
|
+
behavior: "smooth",
|
|
1086
|
+
block: "nearest",
|
|
1087
|
+
})
|
|
1197
1088
|
}
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1089
|
+
}, 150) // Delay to let the expansion animation start
|
|
1090
|
+
}
|
|
1091
|
+
}}
|
|
1092
|
+
className="flex items-center gap-1 text-xs hover:underline cursor-pointer transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
|
|
1093
|
+
aria-label={
|
|
1094
|
+
showCalldata
|
|
1095
|
+
? "Hide custom calldata"
|
|
1096
|
+
: "Show custom calldata"
|
|
1097
|
+
}
|
|
1098
|
+
>
|
|
1099
|
+
<span className="text-[10px]">
|
|
1100
|
+
Includes custom destination calldata
|
|
1101
|
+
</span>
|
|
1102
|
+
<svg
|
|
1103
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
1104
|
+
showCalldata ? "rotate-180" : ""
|
|
1105
|
+
}`}
|
|
1106
|
+
fill="none"
|
|
1107
|
+
stroke="currentColor"
|
|
1108
|
+
viewBox="0 0 24 24"
|
|
1109
|
+
aria-hidden="true"
|
|
1110
|
+
>
|
|
1111
|
+
<path
|
|
1112
|
+
strokeLinecap="round"
|
|
1113
|
+
strokeLinejoin="round"
|
|
1114
|
+
strokeWidth={2}
|
|
1115
|
+
d="M19 9l-7 7-7-7"
|
|
1116
|
+
/>
|
|
1117
|
+
</svg>
|
|
1118
|
+
</button>
|
|
1119
|
+
<div
|
|
1120
|
+
ref={calldataRef}
|
|
1121
|
+
className={`overflow-hidden transition-all duration-300 ease-out ${
|
|
1122
|
+
showCalldata
|
|
1123
|
+
? "max-h-32 opacity-100"
|
|
1124
|
+
: "max-h-0 opacity-0"
|
|
1125
|
+
}`}
|
|
1126
|
+
>
|
|
1127
|
+
<div className="mt-2">
|
|
1128
|
+
<textarea
|
|
1129
|
+
value={quote.destinationCalldata}
|
|
1130
|
+
readOnly
|
|
1131
|
+
className={`w-full p-2 text-xs font-mono rounded border border-solid resize-none transition-all duration-200 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 text-gray-800 dark:text-gray-200`}
|
|
1132
|
+
rows={4}
|
|
1133
|
+
placeholder="No custom calldata"
|
|
1134
|
+
/>
|
|
1244
1135
|
</div>
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
{/* Children content */}
|
|
1248
|
-
{children && <div className="mb-0">{children}</div>}
|
|
1136
|
+
</div>
|
|
1249
1137
|
</div>
|
|
1250
|
-
|
|
1138
|
+
)}
|
|
1139
|
+
|
|
1140
|
+
{/* Children content */}
|
|
1141
|
+
{children && <div className="mb-0">{children}</div>}
|
|
1251
1142
|
</div>
|
|
1252
1143
|
</div>
|
|
1253
1144
|
</div>
|