0xtrails 0.2.1 → 0.2.4
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.map +1 -1
- package/dist/{ccip-BbfANth7.js → ccip-BlV1Mry3.js} +1 -1
- package/dist/chains.d.ts +5 -1
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/{index-WpIVoh3X.js → index-BNWCIGfQ.js} +49015 -46131
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/intentEntrypoint.d.ts +0 -8
- package/dist/intentEntrypoint.d.ts.map +1 -1
- package/dist/metaTxnMonitor.d.ts +5 -4
- 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/prepareSend.d.ts +3 -3
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/relayer.d.ts +10 -7
- package/dist/relayer.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +3 -2
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +7 -0
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +2 -2
- package/dist/trails.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/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/EarnPools.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +1 -0
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +1 -0
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/Recipients.d.ts.map +1 -1
- package/dist/widget/components/RefundWarning.d.ts +1 -0
- package/dist/widget/components/RefundWarning.d.ts.map +1 -1
- package/dist/widget/hooks/useBack.d.ts +5 -0
- package/dist/widget/hooks/useBack.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useInitialRedirect.d.ts +7 -0
- package/dist/widget/hooks/useInitialRedirect.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +18 -17
- package/src/aave.ts +90 -74
- package/src/chains.ts +23 -3
- package/src/constants.ts +10 -17
- package/src/error.ts +1 -1
- package/src/index.ts +8 -3
- package/src/intentEntrypoint.ts +0 -15
- package/src/metaTxnMonitor.ts +28 -22
- package/src/metaTxns.ts +5 -3
- package/src/prepareSend.ts +217 -286
- package/src/relayer.ts +15 -16
- package/src/sequenceWallet.ts +7 -3
- package/src/tokenBalances.ts +55 -1
- package/src/tokens.ts +10 -0
- package/src/trails.ts +2 -2
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountActionsDropdown.tsx +6 -2
- package/src/widget/components/AccountIntentTransactionHistory.tsx +1 -1
- package/src/widget/components/AccountSettings.tsx +5 -4
- package/src/widget/components/ChainFilterDropdown.tsx +1 -1
- package/src/widget/components/ChainList.tsx +1 -1
- package/src/widget/components/ConnectWallet.tsx +6 -2
- package/src/widget/components/EarnPools.tsx +2 -1
- package/src/widget/components/Fund.tsx +50 -27
- package/src/widget/components/Pay.tsx +24 -1
- package/src/widget/components/Receive.tsx +1 -1
- package/src/widget/components/Recipients.tsx +4 -2
- package/src/widget/components/RefundWarning.tsx +5 -1
- package/src/widget/components/SwapSettings.tsx +9 -9
- package/src/widget/components/TokenSelector.tsx +1 -1
- package/src/widget/components/WalletList.tsx +3 -3
- package/src/widget/hooks/useBack.tsx +111 -9
- package/src/widget/hooks/useDefaultTokenSelection.tsx +5 -1
- package/src/widget/hooks/useInitialRedirect.tsx +70 -0
- package/src/widget/hooks/useSelectedFeeToken.tsx +10 -16
- package/src/widget/hooks/useSendForm.ts +10 -10
- package/src/widget/hooks/useTokenList.ts +11 -2
- package/src/widget/widget.tsx +85 -106
- /package/dist/{style.css → 0xtrails.css} +0 -0
|
@@ -109,11 +109,12 @@ export const EarnPools: React.FC<EarnPoolsProps> = ({
|
|
|
109
109
|
|
|
110
110
|
// Search filter - split by spaces to allow "usdc base" type searches
|
|
111
111
|
const searchTerms = searchFilter
|
|
112
|
+
.trim()
|
|
112
113
|
.toLowerCase()
|
|
113
114
|
.split(/\s+/)
|
|
114
115
|
.filter((term) => term.length > 0)
|
|
115
116
|
const searchMatch =
|
|
116
|
-
!searchFilter ||
|
|
117
|
+
!searchFilter.trim() ||
|
|
117
118
|
searchTerms.every(
|
|
118
119
|
(term) =>
|
|
119
120
|
pool.token?.symbol?.toLowerCase().includes(term) ||
|
|
@@ -48,6 +48,7 @@ interface FundProps {
|
|
|
48
48
|
onSend: (amount: string, recipient: string) => void
|
|
49
49
|
paymasterUrls?: Array<{ chainId: number; url: string }>
|
|
50
50
|
gasless?: boolean
|
|
51
|
+
isSequenceWallet?: boolean
|
|
51
52
|
setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
|
|
52
53
|
quoteProvider?: string
|
|
53
54
|
fundMethod?: string
|
|
@@ -83,6 +84,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
83
84
|
onSend,
|
|
84
85
|
paymasterUrls,
|
|
85
86
|
gasless,
|
|
87
|
+
isSequenceWallet = false,
|
|
86
88
|
setWalletConfirmRetryHandler,
|
|
87
89
|
quoteProvider,
|
|
88
90
|
fundMethod,
|
|
@@ -819,9 +821,11 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
819
821
|
<div className="flex items-center space-x-2">
|
|
820
822
|
{/* Amount Input */}
|
|
821
823
|
<div className="flex-1">
|
|
822
|
-
<
|
|
823
|
-
|
|
824
|
+
<button
|
|
825
|
+
type="button"
|
|
826
|
+
className="flex items-center justify-start cursor-text bg-transparent border-none p-0 w-full"
|
|
824
827
|
onClick={() => inputRef.current?.focus()}
|
|
828
|
+
aria-label="Focus amount input"
|
|
825
829
|
>
|
|
826
830
|
<div className="flex items-center">
|
|
827
831
|
<input
|
|
@@ -861,7 +865,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
861
865
|
<div className="ml-2 animate-spin rounded-full h-4 w-4 border-solid border-b-2 trails-primary" />
|
|
862
866
|
)}
|
|
863
867
|
</div>
|
|
864
|
-
</
|
|
868
|
+
</button>
|
|
865
869
|
</div>
|
|
866
870
|
|
|
867
871
|
{/* Token Selection Button */}
|
|
@@ -1050,7 +1054,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
1050
1054
|
<div className="relative">
|
|
1051
1055
|
{toToken ? (
|
|
1052
1056
|
/* Display only - destination token is fixed */
|
|
1053
|
-
<div className="w-full flex items-center justify-between space-x-3 trails-bg-secondary trails-border-radius-list-button px-4 py-2">
|
|
1057
|
+
<div className="w-full flex items-center justify-between space-x-3 trails-bg-secondary trails-border-radius-list-button px-4 py-2 pb-6">
|
|
1054
1058
|
<div className="text-left">
|
|
1055
1059
|
<div className="font-medium trails-text-primary text-sm whitespace-nowrap">
|
|
1056
1060
|
Receiving amount
|
|
@@ -1059,17 +1063,26 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
1059
1063
|
<div className="flex items-center space-x-2">
|
|
1060
1064
|
{selectedDestToken ? (
|
|
1061
1065
|
<>
|
|
1062
|
-
<div className="
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1066
|
+
<div className="relative">
|
|
1067
|
+
<div className="font-medium trails-text-primary text-sm">
|
|
1068
|
+
{isLoadingQuote ? (
|
|
1069
|
+
<div className="h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
|
|
1070
|
+
) : prepareSendQuote?.destinationAmountFormatted ? (
|
|
1071
|
+
<span className="whitespace-nowrap">
|
|
1072
|
+
{prepareSendQuote.destinationAmountFormatted}{" "}
|
|
1073
|
+
{selectedDestToken.symbol}
|
|
1074
|
+
</span>
|
|
1075
|
+
) : (
|
|
1076
|
+
""
|
|
1077
|
+
)}
|
|
1078
|
+
</div>
|
|
1079
|
+
{/* USD Display - Hidden during loading, absolutely positioned */}
|
|
1080
|
+
{!isLoadingQuote &&
|
|
1081
|
+
prepareSendQuote?.destinationAmountUsdDisplay && (
|
|
1082
|
+
<div className="absolute top-full right-0 text-xs trails-text-muted mt-0.5">
|
|
1083
|
+
≈ {prepareSendQuote.destinationAmountUsdDisplay}
|
|
1084
|
+
</div>
|
|
1085
|
+
)}
|
|
1073
1086
|
</div>
|
|
1074
1087
|
<TokenImage
|
|
1075
1088
|
symbol={selectedDestToken.symbol}
|
|
@@ -1095,7 +1108,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
1095
1108
|
<button
|
|
1096
1109
|
type="button"
|
|
1097
1110
|
onClick={() => setShowDestinationTokenSelector(true)}
|
|
1098
|
-
className="w-full flex items-center justify-between space-x-3 hover:trails-hover-bg hover:bg-gray-50 dark:hover:bg-gray-700 trails-border-radius-list-button px-4 py-2 transition-all duration-200 cursor-pointer"
|
|
1111
|
+
className="w-full flex items-center justify-between space-x-3 hover:trails-hover-bg hover:bg-gray-50 dark:hover:bg-gray-700 trails-border-radius-list-button px-4 py-2 pb-6 transition-all duration-200 cursor-pointer"
|
|
1099
1112
|
>
|
|
1100
1113
|
<div className="text-left">
|
|
1101
1114
|
<div className="font-medium trails-text-primary text-sm whitespace-nowrap">
|
|
@@ -1106,17 +1119,26 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
1106
1119
|
<div className="flex items-center space-x-2">
|
|
1107
1120
|
{selectedDestToken ? (
|
|
1108
1121
|
<>
|
|
1109
|
-
<div className="
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1122
|
+
<div className="relative">
|
|
1123
|
+
<div className="font-medium trails-text-primary text-sm">
|
|
1124
|
+
{isLoadingQuote ? (
|
|
1125
|
+
<div className="h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
|
|
1126
|
+
) : prepareSendQuote?.destinationAmountFormatted ? (
|
|
1127
|
+
<span className="whitespace-nowrap">
|
|
1128
|
+
{prepareSendQuote.destinationAmountFormatted}{" "}
|
|
1129
|
+
{selectedDestToken.symbol}
|
|
1130
|
+
</span>
|
|
1131
|
+
) : (
|
|
1132
|
+
""
|
|
1133
|
+
)}
|
|
1134
|
+
</div>
|
|
1135
|
+
{/* USD Display - Hidden during loading, absolutely positioned */}
|
|
1136
|
+
{!isLoadingQuote &&
|
|
1137
|
+
prepareSendQuote?.destinationAmountUsdDisplay && (
|
|
1138
|
+
<div className="absolute top-full right-0 text-xs trails-text-muted mt-0.5">
|
|
1139
|
+
≈ {prepareSendQuote.destinationAmountUsdDisplay}
|
|
1140
|
+
</div>
|
|
1141
|
+
)}
|
|
1120
1142
|
</div>
|
|
1121
1143
|
<TokenImage
|
|
1122
1144
|
symbol={selectedDestToken.symbol}
|
|
@@ -1149,6 +1171,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
1149
1171
|
fundMethod={fundMethod}
|
|
1150
1172
|
isSenderContractOnOrigin={isSenderContractOnOrigin}
|
|
1151
1173
|
isSenderContractOnDestination={isSenderContractOnDestination}
|
|
1174
|
+
isSequenceWallet={isSequenceWallet}
|
|
1152
1175
|
/>
|
|
1153
1176
|
|
|
1154
1177
|
{/* Error Display */}
|
|
@@ -45,6 +45,7 @@ interface PayProps {
|
|
|
45
45
|
onSend: (amount: string, recipient: string) => void
|
|
46
46
|
paymasterUrls?: Array<{ chainId: number; url: string }>
|
|
47
47
|
gasless?: boolean
|
|
48
|
+
isSequenceWallet?: boolean
|
|
48
49
|
setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
|
|
49
50
|
quoteProvider?: string
|
|
50
51
|
fundMethod?: string
|
|
@@ -82,6 +83,7 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
82
83
|
onSend,
|
|
83
84
|
paymasterUrls,
|
|
84
85
|
gasless,
|
|
86
|
+
isSequenceWallet = false,
|
|
85
87
|
setWalletConfirmRetryHandler,
|
|
86
88
|
quoteProvider,
|
|
87
89
|
fundMethod,
|
|
@@ -143,6 +145,18 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
143
145
|
allSupportedTokens: true, // Show all tokens for destination selection
|
|
144
146
|
})
|
|
145
147
|
|
|
148
|
+
// Get origin token balance for display
|
|
149
|
+
const originTokenBalance = useMemo(() => {
|
|
150
|
+
if (!originToken || !filteredTokensFormatted) return null
|
|
151
|
+
|
|
152
|
+
return filteredTokensFormatted.find(
|
|
153
|
+
(token) =>
|
|
154
|
+
token.contractAddress?.toLowerCase() ===
|
|
155
|
+
originToken.contractAddress?.toLowerCase() &&
|
|
156
|
+
token.chainId === originToken.chainId,
|
|
157
|
+
)
|
|
158
|
+
}, [originToken, filteredTokensFormatted])
|
|
159
|
+
|
|
146
160
|
// Use useSendForm for quote functionality with EXACT_OUTPUT trade type
|
|
147
161
|
const {
|
|
148
162
|
amountUsdDisplay,
|
|
@@ -729,8 +743,16 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
729
743
|
<span> </span>
|
|
730
744
|
)}
|
|
731
745
|
</div>
|
|
746
|
+
{/* Token Balance */}
|
|
732
747
|
<div className="text-xs trails-text-muted">
|
|
733
|
-
|
|
748
|
+
{originTokenBalance?.balanceFormatted ? (
|
|
749
|
+
<>
|
|
750
|
+
Balance: {originTokenBalance.balanceFormatted}{" "}
|
|
751
|
+
{originToken?.symbol}
|
|
752
|
+
</>
|
|
753
|
+
) : (
|
|
754
|
+
<span> </span>
|
|
755
|
+
)}
|
|
734
756
|
</div>
|
|
735
757
|
</div>
|
|
736
758
|
</div>
|
|
@@ -999,6 +1021,7 @@ export const Pay: React.FC<PayProps> = ({
|
|
|
999
1021
|
fundMethod={fundMethod}
|
|
1000
1022
|
isSenderContractOnOrigin={isSenderContractOnOrigin}
|
|
1001
1023
|
isSenderContractOnDestination={isSenderContractOnDestination}
|
|
1024
|
+
isSequenceWallet={isSequenceWallet}
|
|
1002
1025
|
/>
|
|
1003
1026
|
|
|
1004
1027
|
{/* Error Display */}
|
|
@@ -104,7 +104,7 @@ export const Receive: React.FC<ReceiveProps> = ({
|
|
|
104
104
|
{/* QR Code Section */}
|
|
105
105
|
<div className="space-y-3 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
|
106
106
|
<div className="flex justify-center">
|
|
107
|
-
<div className="flex flex-col items-center">
|
|
107
|
+
<div className="flex flex-col items-center" title={qrCodeUrl}>
|
|
108
108
|
<QrCode url={qrCodeUrl} size={300} />
|
|
109
109
|
</div>
|
|
110
110
|
</div>
|
|
@@ -236,7 +236,8 @@ export const Recipients: React.FC<RecipientsProps> = ({
|
|
|
236
236
|
const isHighlighted =
|
|
237
237
|
searchQuery &&
|
|
238
238
|
isAddress(searchQuery) &&
|
|
239
|
-
recipient.address.toLowerCase() ===
|
|
239
|
+
recipient.address.toLowerCase() ===
|
|
240
|
+
searchQuery.trim().toLowerCase()
|
|
240
241
|
|
|
241
242
|
return (
|
|
242
243
|
<button
|
|
@@ -339,7 +340,8 @@ export const Recipients: React.FC<RecipientsProps> = ({
|
|
|
339
340
|
const isHighlighted =
|
|
340
341
|
searchQuery &&
|
|
341
342
|
isAddress(searchQuery) &&
|
|
342
|
-
wallet.address.toLowerCase() ===
|
|
343
|
+
wallet.address.toLowerCase() ===
|
|
344
|
+
searchQuery.trim().toLowerCase()
|
|
343
345
|
|
|
344
346
|
return (
|
|
345
347
|
<button
|
|
@@ -4,17 +4,21 @@ interface RefundWarningProps {
|
|
|
4
4
|
fundMethod?: string
|
|
5
5
|
isSenderContractOnOrigin?: boolean
|
|
6
6
|
isSenderContractOnDestination?: boolean
|
|
7
|
+
isSequenceWallet?: boolean
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export const RefundWarning: React.FC<RefundWarningProps> = ({
|
|
10
11
|
fundMethod,
|
|
11
12
|
isSenderContractOnOrigin,
|
|
12
13
|
isSenderContractOnDestination,
|
|
14
|
+
isSequenceWallet = false,
|
|
13
15
|
}) => {
|
|
14
16
|
// Determine if we should show the warning
|
|
15
17
|
const shouldShowWarning =
|
|
16
18
|
fundMethod === "exchange" ||
|
|
17
|
-
(isSenderContractOnOrigin &&
|
|
19
|
+
(isSenderContractOnOrigin &&
|
|
20
|
+
!isSenderContractOnDestination &&
|
|
21
|
+
!isSequenceWallet)
|
|
18
22
|
|
|
19
23
|
if (!shouldShowWarning) {
|
|
20
24
|
return null
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Settings } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useEffect, useRef, useState } from "react"
|
|
4
|
-
import { SwapDisplayMode } from "./SwapDisplayMode.js"
|
|
4
|
+
// import { SwapDisplayMode } from "./SwapDisplayMode.js"
|
|
5
5
|
import { SlippageToleranceSettings } from "./SlippageToleranceSettings.js"
|
|
6
|
-
import { useSwapSettings } from "../hooks/useSwapSettings.js"
|
|
6
|
+
// import { useSwapSettings } from "../hooks/useSwapSettings.js"
|
|
7
7
|
|
|
8
8
|
export const SwapSettings: React.FC = () => {
|
|
9
|
-
const { isSimpleSwapMode, setIsSimpleSwapModeWithStorage } = useSwapSettings()
|
|
9
|
+
//const { isSimpleSwapMode, setIsSimpleSwapModeWithStorage } = useSwapSettings()
|
|
10
10
|
const [isSettingsDropdownOpen, setIsSettingsDropdownOpen] = useState(false)
|
|
11
11
|
const settingsDropdownRef = useRef<HTMLDivElement>(null)
|
|
12
12
|
|
|
@@ -27,10 +27,10 @@ export const SwapSettings: React.FC = () => {
|
|
|
27
27
|
}
|
|
28
28
|
}, [isSettingsDropdownOpen])
|
|
29
29
|
|
|
30
|
-
const handleModeSelect = (isSimple: boolean) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
30
|
+
// const handleModeSelect = (isSimple: boolean) => {
|
|
31
|
+
// setIsSimpleSwapModeWithStorage(isSimple)
|
|
32
|
+
// setIsSettingsDropdownOpen(false)
|
|
33
|
+
// }
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<div className="relative" ref={settingsDropdownRef}>
|
|
@@ -47,10 +47,10 @@ export const SwapSettings: React.FC = () => {
|
|
|
47
47
|
{isSettingsDropdownOpen && (
|
|
48
48
|
<div className="absolute right-0 top-full mt-2 w-80 trails-bg-card rounded-lg shadow-lg border trails-border-primary z-20">
|
|
49
49
|
<div className="p-4 space-y-4">
|
|
50
|
-
<SwapDisplayMode
|
|
50
|
+
{/* <SwapDisplayMode
|
|
51
51
|
isSimpleMode={isSimpleSwapMode}
|
|
52
52
|
onModeChange={handleModeSelect}
|
|
53
|
-
/>
|
|
53
|
+
/> */}
|
|
54
54
|
|
|
55
55
|
<div className="border-t border-gray-200 dark:border-gray-700 pt-4">
|
|
56
56
|
<SlippageToleranceSettings />
|
|
@@ -120,7 +120,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
120
120
|
// Then apply search filtering
|
|
121
121
|
if (!searchQuery.trim()) return true
|
|
122
122
|
|
|
123
|
-
const query = searchQuery.toLowerCase()
|
|
123
|
+
const query = searchQuery.trim().toLowerCase()
|
|
124
124
|
return (
|
|
125
125
|
recentToken.symbol.toLowerCase().includes(query) ||
|
|
126
126
|
recentToken.name.toLowerCase().includes(query) ||
|
|
@@ -45,10 +45,11 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
45
45
|
const filteredWalletOptions = useMemo(() => {
|
|
46
46
|
if (!searchTerm.trim()) return prefilteredWalletOptions
|
|
47
47
|
|
|
48
|
+
const query = searchTerm.trim().toLowerCase()
|
|
48
49
|
return prefilteredWalletOptions.filter((wallet) => {
|
|
49
50
|
return (
|
|
50
|
-
wallet.name.toLowerCase().includes(
|
|
51
|
-
wallet.id.toLowerCase().includes(
|
|
51
|
+
wallet.name.toLowerCase().includes(query) ||
|
|
52
|
+
wallet.id.toLowerCase().includes(query)
|
|
52
53
|
)
|
|
53
54
|
})
|
|
54
55
|
}, [prefilteredWalletOptions, searchTerm])
|
|
@@ -63,7 +64,6 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
63
64
|
headerContent="More Wallets"
|
|
64
65
|
headerContentAlign="left"
|
|
65
66
|
onBack={onBack}
|
|
66
|
-
showAccountActions={true}
|
|
67
67
|
/>
|
|
68
68
|
|
|
69
69
|
{/* Search Input */}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
useEffect,
|
|
6
|
+
useCallback,
|
|
7
|
+
} from "react"
|
|
2
8
|
import type { ReactNode } from "react"
|
|
3
9
|
import { useCurrentScreen, type Screen } from "./useCurrentScreen.js"
|
|
4
10
|
import { logger } from "../../logger.js"
|
|
@@ -9,6 +15,11 @@ interface BackContextType {
|
|
|
9
15
|
clearHistory: () => void
|
|
10
16
|
isNavigatingBack: boolean
|
|
11
17
|
getHistory: () => Screen[]
|
|
18
|
+
getBreadcrumbHistory: () => Screen[]
|
|
19
|
+
addBreadcrumb: (screen: Screen) => void
|
|
20
|
+
setAccountSettingsSource: (screen: Screen) => void
|
|
21
|
+
getAccountSettingsSource: () => Screen | null
|
|
22
|
+
setCurrentScreenWithBack: (screen: Screen, backTo?: Screen) => void
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
const BackContext = createContext<BackContextType | null>(null)
|
|
@@ -20,6 +31,9 @@ interface BackProviderProps {
|
|
|
20
31
|
export function BackProvider({ children }: BackProviderProps) {
|
|
21
32
|
const { currentScreen, setCurrentScreen } = useCurrentScreen()
|
|
22
33
|
const [history, setHistory] = useState<Screen[]>([])
|
|
34
|
+
const [navigationStack, setNavigationStack] = useState<
|
|
35
|
+
Array<[Screen, Screen?]>
|
|
36
|
+
>([])
|
|
23
37
|
const [isNavigatingBack, setIsNavigatingBack] = useState(false)
|
|
24
38
|
|
|
25
39
|
// Track screen changes and update history
|
|
@@ -45,20 +59,83 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
45
59
|
})
|
|
46
60
|
}, [currentScreen])
|
|
47
61
|
|
|
48
|
-
|
|
62
|
+
// Get the previous screen from navigation stack
|
|
63
|
+
const getPreviousScreen = (): Screen | null => {
|
|
64
|
+
if (navigationStack.length === 0) {
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Find the current screen in the navigation stack
|
|
69
|
+
const currentIndex = navigationStack.findIndex(
|
|
70
|
+
([screen]) => screen === currentScreen,
|
|
71
|
+
)
|
|
72
|
+
if (currentIndex === -1) {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const currentEntry = navigationStack[currentIndex]
|
|
77
|
+
if (!currentEntry) {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
const [, backToScreen] = currentEntry
|
|
81
|
+
|
|
82
|
+
// If this screen has a specific back target, use it
|
|
83
|
+
if (backToScreen) {
|
|
84
|
+
return backToScreen
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Otherwise, go to the previous screen in the stack
|
|
88
|
+
if (currentIndex > 0) {
|
|
89
|
+
const previousEntry = navigationStack[currentIndex - 1]
|
|
90
|
+
if (previousEntry) {
|
|
91
|
+
const [previousScreen] = previousEntry
|
|
92
|
+
return previousScreen
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Function to set current screen with optional back target
|
|
100
|
+
const setCurrentScreenWithBack = useCallback(
|
|
101
|
+
(screen: Screen, backTo?: Screen) => {
|
|
102
|
+
setNavigationStack((prevStack) => {
|
|
103
|
+
// Remove any existing entry for this screen
|
|
104
|
+
const filteredStack = prevStack.filter(
|
|
105
|
+
([existingScreen]) => existingScreen !== screen,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
// Add new entry
|
|
109
|
+
const newEntry: [Screen, Screen?] = backTo ? [screen, backTo] : [screen]
|
|
110
|
+
const newStack = [...filteredStack, newEntry]
|
|
111
|
+
|
|
112
|
+
// Keep stack limited to last 10 entries
|
|
113
|
+
if (newStack.length > 10) {
|
|
114
|
+
return newStack.slice(-10)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return newStack
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
setCurrentScreen(screen)
|
|
121
|
+
},
|
|
122
|
+
[setCurrentScreen],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
const canGoBack = navigationStack.length > 0 || history.length > 1
|
|
49
126
|
|
|
50
127
|
const goBack = canGoBack
|
|
51
128
|
? () => {
|
|
52
|
-
|
|
53
|
-
const newHistory = history.slice(0, -1)
|
|
54
|
-
const previousScreen = newHistory[newHistory.length - 1]
|
|
129
|
+
const previousScreen = getPreviousScreen()
|
|
55
130
|
|
|
56
131
|
logger.console.log(
|
|
57
|
-
"[trails-sdk] goBack",
|
|
132
|
+
"[trails-sdk] goBack (navigation stack)",
|
|
58
133
|
"previousScreen:",
|
|
59
134
|
previousScreen,
|
|
60
135
|
"currentScreen:",
|
|
61
136
|
currentScreen,
|
|
137
|
+
"navigationStack:",
|
|
138
|
+
navigationStack,
|
|
62
139
|
)
|
|
63
140
|
|
|
64
141
|
// Set flag to prevent auto-selection when navigating back
|
|
@@ -67,24 +144,44 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
67
144
|
}
|
|
68
145
|
|
|
69
146
|
if (previousScreen) {
|
|
70
|
-
|
|
147
|
+
// Remove current screen from navigation stack
|
|
148
|
+
setNavigationStack((prevStack) =>
|
|
149
|
+
prevStack.filter(([screen]) => screen !== currentScreen),
|
|
150
|
+
)
|
|
71
151
|
setCurrentScreen(previousScreen)
|
|
152
|
+
} else {
|
|
153
|
+
// Fallback: if no navigation stack, use regular history
|
|
154
|
+
const regularHistory = history
|
|
155
|
+
if (regularHistory.length > 1) {
|
|
156
|
+
const fallbackScreen = regularHistory[regularHistory.length - 2]
|
|
157
|
+
if (fallbackScreen) {
|
|
158
|
+
logger.console.log(
|
|
159
|
+
"[trails-sdk] goBack (fallback to regular history)",
|
|
160
|
+
"previousScreen:",
|
|
161
|
+
fallbackScreen,
|
|
162
|
+
)
|
|
163
|
+
setCurrentScreen(fallbackScreen)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
72
166
|
}
|
|
73
167
|
|
|
74
|
-
// Reset the flag after a
|
|
168
|
+
// Reset the flag after a longer delay to allow the screen change to complete
|
|
169
|
+
// and prevent post-connection navigation from interfering with manual back navigation
|
|
75
170
|
if (setIsNavigatingBack) {
|
|
76
171
|
setTimeout(() => {
|
|
77
172
|
setIsNavigatingBack(false)
|
|
78
|
-
},
|
|
173
|
+
}, 500)
|
|
79
174
|
}
|
|
80
175
|
}
|
|
81
176
|
: undefined
|
|
82
177
|
|
|
83
178
|
const clearHistory = () => {
|
|
84
179
|
setHistory([currentScreen])
|
|
180
|
+
setNavigationStack([[currentScreen]])
|
|
85
181
|
}
|
|
86
182
|
|
|
87
183
|
const getHistory = () => history
|
|
184
|
+
const getBreadcrumbHistory = () => navigationStack.map(([screen]) => screen)
|
|
88
185
|
|
|
89
186
|
const value: BackContextType = {
|
|
90
187
|
goBack,
|
|
@@ -92,6 +189,11 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
92
189
|
clearHistory,
|
|
93
190
|
isNavigatingBack,
|
|
94
191
|
getHistory,
|
|
192
|
+
getBreadcrumbHistory,
|
|
193
|
+
addBreadcrumb: () => {}, // Deprecated, kept for compatibility
|
|
194
|
+
setAccountSettingsSource: () => {}, // Deprecated, kept for compatibility
|
|
195
|
+
getAccountSettingsSource: () => null, // Deprecated, kept for compatibility
|
|
196
|
+
setCurrentScreenWithBack,
|
|
95
197
|
}
|
|
96
198
|
|
|
97
199
|
return <BackContext.Provider value={value}>{children}</BackContext.Provider>
|
|
@@ -187,7 +187,11 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
187
187
|
tokenWithInfo.contractInfo?.logoURI || tokenWithInfo.imageUrl || ""
|
|
188
188
|
const decimals = token.contractInfo?.decimals
|
|
189
189
|
if (!decimals) {
|
|
190
|
-
|
|
190
|
+
logger.console.warn("[trails-sdk] Missing decimals for token:", {
|
|
191
|
+
token: token.contractInfo,
|
|
192
|
+
chainId: token.chainId,
|
|
193
|
+
})
|
|
194
|
+
return null // Return null instead of throwing
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
return {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useCurrentScreen, type Screen } from "./useCurrentScreen.js"
|
|
3
|
+
import { useBack } from "./useBack.js"
|
|
4
|
+
import { logger } from "../../logger.js"
|
|
5
|
+
import type { Mode } from "../../mode.js"
|
|
6
|
+
|
|
7
|
+
export function useInitialRedirect(
|
|
8
|
+
isConnected: boolean,
|
|
9
|
+
currentMode: Mode,
|
|
10
|
+
getInitialScreenForMode: (mode: Mode) => Screen,
|
|
11
|
+
) {
|
|
12
|
+
const { setCurrentScreen } = useCurrentScreen()
|
|
13
|
+
const { getBreadcrumbHistory } = useBack()
|
|
14
|
+
const [hasConnectedBefore, setHasConnectedBefore] = useState(false)
|
|
15
|
+
const [isInitialScreenSet, setIsInitialScreenSet] = useState(false)
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!isConnected || isInitialScreenSet) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check if this is the first time connecting (no previous wallet connected)
|
|
23
|
+
const isFirstTimeConnection = !hasConnectedBefore
|
|
24
|
+
|
|
25
|
+
if (isFirstTimeConnection) {
|
|
26
|
+
// First time connecting - go to appropriate mode screen
|
|
27
|
+
const initialScreen = getInitialScreenForMode(currentMode)
|
|
28
|
+
logger.console.log(
|
|
29
|
+
"[trails-sdk] First time connection, redirecting to:",
|
|
30
|
+
initialScreen,
|
|
31
|
+
)
|
|
32
|
+
setCurrentScreen(initialScreen)
|
|
33
|
+
setHasConnectedBefore(true)
|
|
34
|
+
} else {
|
|
35
|
+
// Subsequent connections - check if user came from account-settings
|
|
36
|
+
const breadcrumbHistory = getBreadcrumbHistory()
|
|
37
|
+
const lastBreadcrumbScreen =
|
|
38
|
+
breadcrumbHistory.length > 0
|
|
39
|
+
? breadcrumbHistory[breadcrumbHistory.length - 1]
|
|
40
|
+
: null
|
|
41
|
+
|
|
42
|
+
if (lastBreadcrumbScreen === "account-settings") {
|
|
43
|
+
// User came from account-settings, return there
|
|
44
|
+
logger.console.log(
|
|
45
|
+
"[trails-sdk] Returning to account-settings after wallet connection",
|
|
46
|
+
)
|
|
47
|
+
setCurrentScreen("account-settings")
|
|
48
|
+
} else {
|
|
49
|
+
// User came from elsewhere, go to appropriate mode screen
|
|
50
|
+
const initialScreen = getInitialScreenForMode(currentMode)
|
|
51
|
+
logger.console.log(
|
|
52
|
+
"[trails-sdk] Subsequent connection, redirecting to:",
|
|
53
|
+
initialScreen,
|
|
54
|
+
)
|
|
55
|
+
setCurrentScreen(initialScreen)
|
|
56
|
+
}
|
|
57
|
+
setIsInitialScreenSet(true)
|
|
58
|
+
}
|
|
59
|
+
}, [
|
|
60
|
+
isConnected,
|
|
61
|
+
currentMode,
|
|
62
|
+
hasConnectedBefore,
|
|
63
|
+
getInitialScreenForMode,
|
|
64
|
+
setCurrentScreen,
|
|
65
|
+
getBreadcrumbHistory,
|
|
66
|
+
isInitialScreenSet,
|
|
67
|
+
])
|
|
68
|
+
|
|
69
|
+
return { hasConnectedBefore, isInitialScreenSet }
|
|
70
|
+
}
|
|
@@ -65,22 +65,16 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
65
65
|
const [availableTokens, setAvailableTokens] = useState<TokenWithBalance[]>([])
|
|
66
66
|
|
|
67
67
|
// Wrapper to log all state changes to selectedFeeToken
|
|
68
|
-
const setSelectedFeeTokenInternal = useCallback(
|
|
69
|
-
(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
)
|
|
80
|
-
setSelectedFeeTokenInternalRaw(token)
|
|
81
|
-
},
|
|
82
|
-
[selectedFeeToken],
|
|
83
|
-
)
|
|
68
|
+
const setSelectedFeeTokenInternal = useCallback((token: FeeOption | null) => {
|
|
69
|
+
logger.console.log(
|
|
70
|
+
"[trails-sdk] [FEE-SELECT] selectedFeeToken state changing:",
|
|
71
|
+
{
|
|
72
|
+
to: token,
|
|
73
|
+
toNull: token === null,
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
setSelectedFeeTokenInternalRaw(token)
|
|
77
|
+
}, [])
|
|
84
78
|
|
|
85
79
|
// Wrapper to track when user makes an explicit selection
|
|
86
80
|
const setSelectedFeeToken = useCallback(
|