0xtrails 0.2.5 → 0.2.6
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/abortController.d.ts +8 -0
- package/dist/abortController.d.ts.map +1 -0
- package/dist/{ccip-CXlshvBY.js → ccip-Xjh9d1gb.js} +7 -7
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/fees.d.ts +19 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/{index-_QuyGrjU.js → index-BnhdZ8Ho.js} +34769 -34247
- package/dist/index.js +726 -520
- package/dist/prepareSend.d.ts +11 -77
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -2
- package/dist/transactions.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -2
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
- package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
- package/dist/widget/components/Earn.d.ts +2 -2
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
- package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
- package/dist/widget/components/FeeBreakdown.d.ts +9 -0
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
- package/dist/widget/components/Fund.d.ts +2 -2
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +2 -2
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Identicon.d.ts.map +1 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +2 -2
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +3 -2
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -2
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts +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/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -2
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +9 -0
- package/dist/widget/components/Tooltip.d.ts.map +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useQuote.d.ts +83 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +2 -2
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +2 -2
- package/dist/widget/widget.d.ts +5 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/abortController.ts +35 -0
- package/src/constants.ts +3 -0
- package/src/fees.ts +199 -0
- package/src/prepareSend.ts +225 -398
- package/src/trails.ts +3 -3
- package/src/transactions.ts +62 -18
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
- package/src/widget/components/AccountSettings.tsx +48 -36
- package/src/widget/components/ChainFilterDropdown.tsx +24 -3
- package/src/widget/components/ClassicSwap.tsx +24 -62
- package/src/widget/components/ConnectWallet.tsx +4 -1
- package/src/widget/components/ConnectedWallets.tsx +21 -21
- package/src/widget/components/DynamicInputStyles.tsx +76 -0
- package/src/widget/components/Earn.tsx +34 -29
- package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
- package/src/widget/components/FeeBreakdown.tsx +155 -0
- package/src/widget/components/Fund.tsx +10 -26
- package/src/widget/components/FundSwap.tsx +2 -2
- package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
- package/src/widget/components/Identicon.tsx +164 -95
- package/src/widget/components/MeshConnectExchanges.tsx +2 -15
- package/src/widget/components/Modal.tsx +0 -12
- package/src/widget/components/Pay.tsx +65 -63
- package/src/widget/components/PoolDeposit.tsx +206 -230
- package/src/widget/components/PoolWithdraw.tsx +219 -238
- package/src/widget/components/PriceImpactWarning.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +25 -8
- package/src/widget/components/Receipt.tsx +16 -2
- package/src/widget/components/RecipientSelectorButton.tsx +7 -5
- package/src/widget/components/Recipients.tsx +1 -1
- package/src/widget/components/ScreenHeader.tsx +60 -36
- package/src/widget/components/Swap.tsx +2 -2
- package/src/widget/components/ThemeProvider.tsx +2 -1
- package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
- package/src/widget/components/TokenImage.tsx +1 -1
- package/src/widget/components/TokenSelector.tsx +62 -53
- package/src/widget/components/TokenSelectorButton.tsx +38 -15
- package/src/widget/components/Tooltip.tsx +51 -0
- package/src/widget/components/TransferPendingVertical.tsx +1 -1
- package/src/widget/components/WaasFeeOptions.tsx +124 -5
- package/src/widget/components/WalletConfirmation.tsx +23 -13
- package/src/widget/components/WalletConnect.tsx +93 -29
- package/src/widget/hooks/useQuote.ts +413 -0
- package/src/widget/hooks/useSendForm.ts +8 -4
- package/src/widget/widget.tsx +175 -190
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from "react"
|
|
2
2
|
import { useWaasFeeOptions } from "@0xsequence/connect"
|
|
3
3
|
import { TokenImage } from "./TokenImage.js"
|
|
4
|
-
import { ChevronDown, ChevronUp } from "lucide-react"
|
|
4
|
+
import { ChevronDown, ChevronUp, Copy } from "lucide-react"
|
|
5
5
|
import { formatUnits } from "viem"
|
|
6
6
|
|
|
7
7
|
// Define types based on the @0xsequence/connect documentation
|
|
@@ -29,12 +29,14 @@ interface WaasFeeOptionsProps {
|
|
|
29
29
|
chainId?: number
|
|
30
30
|
setIsFeeOptionConfirmed: (isFeeOptionConfirmed: boolean) => void
|
|
31
31
|
onFeeOptionsLoaded?: () => void
|
|
32
|
+
setIsError?: (isError: boolean) => void
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
35
36
|
chainId,
|
|
36
37
|
setIsFeeOptionConfirmed,
|
|
37
38
|
onFeeOptionsLoaded,
|
|
39
|
+
setIsError,
|
|
38
40
|
}) => {
|
|
39
41
|
const [
|
|
40
42
|
pendingFeeOptionConfirmation,
|
|
@@ -47,6 +49,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
47
49
|
const [isExpanded, setIsExpanded] = useState(false)
|
|
48
50
|
const [isProcessing, setIsProcessing] = useState(false)
|
|
49
51
|
const [isLoading, setIsLoading] = useState(false)
|
|
52
|
+
const [copiedAddress, setCopiedAddress] = useState<string | null>(null)
|
|
50
53
|
|
|
51
54
|
// Debug logging
|
|
52
55
|
useEffect(() => {
|
|
@@ -88,6 +91,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
88
91
|
|
|
89
92
|
// Initialize with first option when fee options become available
|
|
90
93
|
useEffect(() => {
|
|
94
|
+
setIsError?.(false)
|
|
91
95
|
if (pendingFeeOptionConfirmation) {
|
|
92
96
|
console.log(
|
|
93
97
|
"[trails-sdk] Pending fee options: ",
|
|
@@ -97,7 +101,10 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
97
101
|
// Notify parent that fee options are loaded
|
|
98
102
|
if (
|
|
99
103
|
onFeeOptionsLoaded &&
|
|
100
|
-
pendingFeeOptionConfirmation.options?.length > 0
|
|
104
|
+
pendingFeeOptionConfirmation.options?.length > 0 &&
|
|
105
|
+
pendingFeeOptionConfirmation.options.find(
|
|
106
|
+
(option: any) => option.hasEnoughBalanceForFee,
|
|
107
|
+
)
|
|
101
108
|
) {
|
|
102
109
|
onFeeOptionsLoaded()
|
|
103
110
|
}
|
|
@@ -112,7 +119,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
112
119
|
}
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
|
-
}, [pendingFeeOptionConfirmation, onFeeOptionsLoaded])
|
|
122
|
+
}, [pendingFeeOptionConfirmation, onFeeOptionsLoaded, setIsError])
|
|
116
123
|
|
|
117
124
|
// Handle fee option selection and confirmation
|
|
118
125
|
const handleConfirmFee = async (tokenAddress: string | null) => {
|
|
@@ -139,6 +146,30 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
148
|
|
|
149
|
+
// Handle copy address to clipboard
|
|
150
|
+
const handleCopyAddress = async (address: string, e: React.MouseEvent) => {
|
|
151
|
+
e.preventDefault()
|
|
152
|
+
e.stopPropagation()
|
|
153
|
+
try {
|
|
154
|
+
await navigator.clipboard.writeText(address)
|
|
155
|
+
setCopiedAddress(address)
|
|
156
|
+
setTimeout(() => setCopiedAddress(null), 2000)
|
|
157
|
+
} catch (error) {
|
|
158
|
+
try {
|
|
159
|
+
const textArea = document.createElement("textarea")
|
|
160
|
+
textArea.value = address
|
|
161
|
+
document.body.appendChild(textArea)
|
|
162
|
+
textArea.select()
|
|
163
|
+
document.execCommand("copy")
|
|
164
|
+
document.body.removeChild(textArea)
|
|
165
|
+
setCopiedAddress(address)
|
|
166
|
+
setTimeout(() => setCopiedAddress(null), 2000)
|
|
167
|
+
} catch (fallbackError) {
|
|
168
|
+
console.error("Fallback copy failed:", fallbackError)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
142
173
|
// Don't render if no pending fee confirmation
|
|
143
174
|
if (!pendingFeeOptionConfirmation) {
|
|
144
175
|
return null
|
|
@@ -162,6 +193,94 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
162
193
|
| FeeOptionExtended
|
|
163
194
|
| undefined
|
|
164
195
|
|
|
196
|
+
const hasTokenForFee = pendingFeeOptionConfirmation.options.find(
|
|
197
|
+
(option: any) => option.hasEnoughBalanceForFee,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if (!hasTokenForFee) {
|
|
201
|
+
setIsError?.(true)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!hasTokenForFee) {
|
|
205
|
+
return (
|
|
206
|
+
<div className="space-y-4 py-6">
|
|
207
|
+
<div className="text-center space-y-1">
|
|
208
|
+
<p className="text-xs trails-text-muted">
|
|
209
|
+
Fund your wallet with one of the following tokens
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<div className="flex flex-col space-y-2">
|
|
214
|
+
{pendingFeeOptionConfirmation.options.map((option: any) => {
|
|
215
|
+
const contractAddress = option.token.contractAddress
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
key={option.token.symbol || contractAddress}
|
|
220
|
+
className="flex items-center space-x-3 p-3 trails-bg-secondary trails-border-radius-container border border-transparent"
|
|
221
|
+
>
|
|
222
|
+
<div className="flex items-center shrink-0">
|
|
223
|
+
<TokenImage
|
|
224
|
+
symbol={option.token.symbol}
|
|
225
|
+
imageUrl={(option.token as any).logoURL}
|
|
226
|
+
chainId={chainId}
|
|
227
|
+
size={32}
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
<div className="flex-1 min-w-0 flex flex-col items-start">
|
|
231
|
+
<span className="text-sm font-bold trails-text-primary leading-tight">
|
|
232
|
+
{option.token.symbol}
|
|
233
|
+
</span>
|
|
234
|
+
{contractAddress ? (
|
|
235
|
+
<div className="flex items-center space-x-1.5 mt-0.5">
|
|
236
|
+
<span className="text-xs trails-text-muted leading-tight">
|
|
237
|
+
{contractAddress.slice(0, 4)}...
|
|
238
|
+
{contractAddress.slice(-4)}
|
|
239
|
+
</span>
|
|
240
|
+
<button
|
|
241
|
+
type="button"
|
|
242
|
+
onClick={(e) => handleCopyAddress(contractAddress, e)}
|
|
243
|
+
className="shrink-0 p-0.5 rounded transition-colors cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 flex items-center justify-center"
|
|
244
|
+
title={
|
|
245
|
+
copiedAddress === contractAddress
|
|
246
|
+
? "Copied!"
|
|
247
|
+
: "Copy address"
|
|
248
|
+
}
|
|
249
|
+
>
|
|
250
|
+
{copiedAddress === contractAddress ? (
|
|
251
|
+
<svg
|
|
252
|
+
className="w-3 h-3 text-green-600 dark:text-green-400"
|
|
253
|
+
fill="none"
|
|
254
|
+
viewBox="0 0 24 24"
|
|
255
|
+
stroke="currentColor"
|
|
256
|
+
aria-label="Copied"
|
|
257
|
+
>
|
|
258
|
+
<path
|
|
259
|
+
strokeLinecap="round"
|
|
260
|
+
strokeLinejoin="round"
|
|
261
|
+
strokeWidth={2}
|
|
262
|
+
d="M5 13l4 4L19 7"
|
|
263
|
+
/>
|
|
264
|
+
</svg>
|
|
265
|
+
) : (
|
|
266
|
+
<Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
|
|
267
|
+
)}
|
|
268
|
+
</button>
|
|
269
|
+
</div>
|
|
270
|
+
) : (
|
|
271
|
+
<span className="text-xs trails-text-muted mt-0.5 leading-tight">
|
|
272
|
+
Native Token
|
|
273
|
+
</span>
|
|
274
|
+
)}
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
)
|
|
278
|
+
})}
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
|
|
165
284
|
return (
|
|
166
285
|
<div className="space-y-2">
|
|
167
286
|
{/* Header */}
|
|
@@ -208,7 +327,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
208
327
|
{/* Display balance info if available */}
|
|
209
328
|
{selectedOption && "balanceFormatted" in selectedOption && (
|
|
210
329
|
<div className="text-right">
|
|
211
|
-
<div className="text-xs
|
|
330
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
212
331
|
Balance: {String(selectedOption.balanceFormatted)}
|
|
213
332
|
</div>
|
|
214
333
|
{!selectedOption.hasEnoughBalanceForFee && (
|
|
@@ -266,7 +385,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
|
|
|
266
385
|
{/* Display balance info if available */}
|
|
267
386
|
{"balanceFormatted" in option && (
|
|
268
387
|
<div className="text-right">
|
|
269
|
-
<div className="text-xs
|
|
388
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
270
389
|
Balance: {String(option.balanceFormatted)}
|
|
271
390
|
</div>
|
|
272
391
|
<div className="text-xs trails-text-muted">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TokenImage } from "./TokenImage.js"
|
|
2
|
+
import { ErrorAnimationIcon } from "./ErrorAnimationIcon.js"
|
|
2
3
|
import { ChevronLeft } from "lucide-react"
|
|
3
4
|
import type React from "react"
|
|
4
5
|
import { useEffect, useMemo, useState } from "react"
|
|
@@ -25,9 +26,11 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
25
26
|
const [showTimeoutWarning, setShowTimeoutWarning] = useState(false)
|
|
26
27
|
const [isFeeOptionConfirmed, setIsFeeOptionConfirmed] = useState(false)
|
|
27
28
|
const [areFeeOptionsLoaded, setAreFeeOptionsLoaded] = useState(false)
|
|
29
|
+
const [feeOptionsError, setFeeOptionsError] = useState<boolean>(false)
|
|
28
30
|
const { connector } = useAccount()
|
|
29
31
|
|
|
30
32
|
useEffect(() => {
|
|
33
|
+
setAreFeeOptionsLoaded(false)
|
|
31
34
|
setShowContent(true)
|
|
32
35
|
}, [])
|
|
33
36
|
|
|
@@ -80,21 +83,25 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
80
83
|
<div
|
|
81
84
|
className={`mx-auto flex items-center justify-center transition-all duration-500 ease-out relative mb-4 ${showContent ? "transform -translate-y-8" : ""}`}
|
|
82
85
|
>
|
|
83
|
-
{
|
|
86
|
+
{feeOptionsError === true ? (
|
|
87
|
+
<ErrorAnimationIcon />
|
|
88
|
+
) : retryEnabled ? (
|
|
84
89
|
<div className={`h-24 w-24`} />
|
|
85
90
|
) : (
|
|
86
91
|
<div className="animate-spin rounded-full h-24 w-24 border-solid border-b-2 border-blue-500 dark:border-blue-400" />
|
|
87
92
|
)}
|
|
88
93
|
|
|
89
|
-
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
{!feeOptionsError && (
|
|
95
|
+
<div className="absolute">
|
|
96
|
+
<TokenImage
|
|
97
|
+
imageUrl={quote?.originToken.imageUrl}
|
|
98
|
+
symbol={quote?.originToken.symbol}
|
|
99
|
+
chainId={quote?.originChain.id}
|
|
100
|
+
contractAddress={quote?.originToken.contractAddress}
|
|
101
|
+
size={64}
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
)}
|
|
98
105
|
</div>
|
|
99
106
|
|
|
100
107
|
<div
|
|
@@ -109,7 +116,9 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
109
116
|
? "Waiting for wallet…"
|
|
110
117
|
: areFeeOptionsLoaded
|
|
111
118
|
? "Waiting for fee selection…"
|
|
112
|
-
:
|
|
119
|
+
: feeOptionsError
|
|
120
|
+
? "No fee token found"
|
|
121
|
+
: "Waiting for fee options…"}
|
|
113
122
|
</h2>
|
|
114
123
|
<p className="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
|
115
124
|
{!isSequenceWaas
|
|
@@ -127,6 +136,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
127
136
|
<WaasFeeOptions
|
|
128
137
|
chainId={quote?.originChain.id}
|
|
129
138
|
setIsFeeOptionConfirmed={setIsFeeOptionConfirmed}
|
|
139
|
+
setIsError={setFeeOptionsError}
|
|
130
140
|
onFeeOptionsLoaded={() => {
|
|
131
141
|
console.log("[trails-sdk] Fee options loaded callback called")
|
|
132
142
|
setAreFeeOptionsLoaded(true)
|
|
@@ -144,7 +154,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
144
154
|
<div className="p-4 trails-border-radius-container text-sm bg-yellow-50 border border-solid border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-700/50">
|
|
145
155
|
<div className="flex items-start space-x-3">
|
|
146
156
|
<svg
|
|
147
|
-
className="w-5 h-5 mt-0.5
|
|
157
|
+
className="w-5 h-5 mt-0.5 shrink-0 text-yellow-600 dark:text-yellow-400"
|
|
148
158
|
fill="none"
|
|
149
159
|
viewBox="0 0 24 24"
|
|
150
160
|
stroke="currentColor"
|
|
@@ -187,7 +197,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
187
197
|
)}
|
|
188
198
|
|
|
189
199
|
{/* Transaction Details */}
|
|
190
|
-
<QuoteDetails quote={quote} showContent={true} />
|
|
200
|
+
<QuoteDetails quote={quote} showContent={true} compact={true} />
|
|
191
201
|
</div>
|
|
192
202
|
</div>
|
|
193
203
|
)
|
|
@@ -44,6 +44,7 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
44
44
|
const { isConnected, address, connector } = useAccount()
|
|
45
45
|
const [wcUri, setWcUri] = React.useState<string | null>(null)
|
|
46
46
|
const [showUri, setShowUri] = React.useState(false)
|
|
47
|
+
const [copied, setCopied] = React.useState(false)
|
|
47
48
|
const listenerRef = React.useRef<(() => void) | null>(null)
|
|
48
49
|
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
49
50
|
|
|
@@ -57,6 +58,21 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
57
58
|
setWcUri(uri)
|
|
58
59
|
}, 500) // 300ms debounce delay
|
|
59
60
|
}, [])
|
|
61
|
+
|
|
62
|
+
// Copy URI to clipboard
|
|
63
|
+
const handleCopyUri = useCallback(async () => {
|
|
64
|
+
if (!wcUri) return
|
|
65
|
+
try {
|
|
66
|
+
await navigator.clipboard.writeText(wcUri)
|
|
67
|
+
setCopied(true)
|
|
68
|
+
setTimeout(() => setCopied(false), 2000)
|
|
69
|
+
} catch (err) {
|
|
70
|
+
logger.console.error(
|
|
71
|
+
"[trails-sdk] [WalletConnect] Failed to copy URI",
|
|
72
|
+
err,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}, [wcUri])
|
|
60
76
|
const isWalletConnectConnector = React.useMemo(() => {
|
|
61
77
|
return connector?.name === "WalletConnect" && isConnected
|
|
62
78
|
}, [connector, isConnected])
|
|
@@ -68,18 +84,13 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
68
84
|
(c.id || "").toLowerCase().includes("walletconnect"),
|
|
69
85
|
)
|
|
70
86
|
|
|
71
|
-
// Only auto-navigate
|
|
87
|
+
// Only auto-navigate to home if we successfully connect a new wallet
|
|
72
88
|
// Don't auto-navigate if user was already connected when they entered this screen
|
|
73
89
|
useEffect(() => {
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
status === "success" &&
|
|
77
|
-
!wasConnectedOnMount.current &&
|
|
78
|
-
onBack
|
|
79
|
-
) {
|
|
80
|
-
onBack()
|
|
90
|
+
if (isConnected && status === "success" && !wasConnectedOnMount.current) {
|
|
91
|
+
onContinue()
|
|
81
92
|
}
|
|
82
|
-
}, [isConnected, status,
|
|
93
|
+
}, [isConnected, status, onContinue])
|
|
83
94
|
|
|
84
95
|
const handleConnect = useCallback(
|
|
85
96
|
async (force: boolean = false) => {
|
|
@@ -306,29 +317,82 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
306
317
|
getWalletIcon("walletconnect")
|
|
307
318
|
}
|
|
308
319
|
/>
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
className={`w-3 h-3 transition-transform ${showUri ? "rotate-180" : ""}`}
|
|
316
|
-
fill="none"
|
|
317
|
-
stroke="currentColor"
|
|
318
|
-
viewBox="0 0 24 24"
|
|
320
|
+
<div className="flex items-center justify-center gap-2 mt-2">
|
|
321
|
+
<button
|
|
322
|
+
type="button"
|
|
323
|
+
onClick={handleCopyUri}
|
|
324
|
+
className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer flex items-center gap-1 hover:underline"
|
|
325
|
+
title="Copy URI to clipboard"
|
|
319
326
|
>
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
327
|
+
{copied ? (
|
|
328
|
+
<>
|
|
329
|
+
<svg
|
|
330
|
+
className="w-3 h-3"
|
|
331
|
+
fill="none"
|
|
332
|
+
stroke="currentColor"
|
|
333
|
+
viewBox="0 0 24 24"
|
|
334
|
+
aria-hidden="true"
|
|
335
|
+
>
|
|
336
|
+
<path
|
|
337
|
+
strokeLinecap="round"
|
|
338
|
+
strokeLinejoin="round"
|
|
339
|
+
strokeWidth={2}
|
|
340
|
+
d="M5 13l4 4L19 7"
|
|
341
|
+
/>
|
|
342
|
+
</svg>
|
|
343
|
+
Copied!
|
|
344
|
+
</>
|
|
345
|
+
) : (
|
|
346
|
+
<>
|
|
347
|
+
<svg
|
|
348
|
+
className="w-3 h-3"
|
|
349
|
+
fill="none"
|
|
350
|
+
stroke="currentColor"
|
|
351
|
+
viewBox="0 0 24 24"
|
|
352
|
+
aria-hidden="true"
|
|
353
|
+
>
|
|
354
|
+
<path
|
|
355
|
+
strokeLinecap="round"
|
|
356
|
+
strokeLinejoin="round"
|
|
357
|
+
strokeWidth={2}
|
|
358
|
+
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
359
|
+
/>
|
|
360
|
+
</svg>
|
|
361
|
+
Copy URI
|
|
362
|
+
</>
|
|
363
|
+
)}
|
|
364
|
+
</button>
|
|
365
|
+
<button
|
|
366
|
+
type="button"
|
|
367
|
+
onClick={() => setShowUri(!showUri)}
|
|
368
|
+
className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:underline cursor-pointer flex items-center gap-1"
|
|
369
|
+
>
|
|
370
|
+
{showUri ? "Hide URI" : "Show URI"}
|
|
371
|
+
<svg
|
|
372
|
+
className={`w-3 h-3 transition-transform ${showUri ? "rotate-180" : ""}`}
|
|
373
|
+
fill="none"
|
|
374
|
+
stroke="currentColor"
|
|
375
|
+
viewBox="0 0 24 24"
|
|
376
|
+
aria-hidden="true"
|
|
377
|
+
>
|
|
378
|
+
<path
|
|
379
|
+
strokeLinecap="round"
|
|
380
|
+
strokeLinejoin="round"
|
|
381
|
+
strokeWidth={2}
|
|
382
|
+
d="M19 9l-7 7-7-7"
|
|
383
|
+
/>
|
|
384
|
+
</svg>
|
|
385
|
+
</button>
|
|
386
|
+
</div>
|
|
328
387
|
{showUri && (
|
|
329
|
-
<
|
|
388
|
+
<button
|
|
389
|
+
type="button"
|
|
390
|
+
className="mt-2 text-xs text-gray-600 dark:text-gray-400 break-all cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 p-2 rounded transition-colors text-left w-full"
|
|
391
|
+
onClick={handleCopyUri}
|
|
392
|
+
title="Click to copy URI"
|
|
393
|
+
>
|
|
330
394
|
{wcUri}
|
|
331
|
-
</
|
|
395
|
+
</button>
|
|
332
396
|
)}
|
|
333
397
|
</div>
|
|
334
398
|
) : (
|