0xtrails 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aave.d.ts +8 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/{ccip-ConT1gDe.js → ccip-CXlshvBY.js} +1 -1
- package/dist/chains.d.ts +5 -1
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/estimate.d.ts +52 -0
- package/dist/estimate.d.ts.map +1 -1
- package/dist/{index-CMh8uEbV.js → index-_QuyGrjU.js} +86304 -83380
- 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/intents.d.ts +40 -0
- package/dist/intents.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/morpho.d.ts +8 -0
- package/dist/morpho.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +16 -6
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/queryParams.d.ts.map +1 -1
- package/dist/relayer.d.ts +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/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -0
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts +4 -0
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/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/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/{FundSendForm.d.ts → FundSwap.d.ts} +11 -5
- package/dist/widget/components/FundSwap.d.ts.map +1 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +1 -0
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
- package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
- package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +11 -34
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
- package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +16 -8
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receive.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Recipients.d.ts.map +1 -1
- package/dist/widget/components/RefundWarning.d.ts +1 -0
- package/dist/widget/components/RefundWarning.d.ts.map +1 -1
- package/dist/widget/components/RequiredPropsError.d.ts +8 -0
- package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +1 -0
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/SwapSettings.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts +1 -0
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/UserPreferences.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +8 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +2 -0
- package/dist/widget/css/index.css +554 -0
- package/dist/widget/hooks/useBack.d.ts +6 -0
- package/dist/widget/hooks/useBack.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +1 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -3
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useInitialRedirect.d.ts +7 -0
- package/dist/widget/hooks/useInitialRedirect.d.ts.map +1 -0
- package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts +4 -4
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +30 -23
- package/src/aave.ts +32 -0
- package/src/chains.ts +23 -3
- package/src/config.ts +12 -4
- package/src/constants.ts +11 -16
- package/src/error.ts +20 -2
- package/src/estimate.ts +416 -5
- package/src/index.ts +8 -3
- package/src/intentEntrypoint.ts +0 -15
- package/src/intents.ts +161 -11
- package/src/metaTxnMonitor.ts +28 -22
- package/src/metaTxns.ts +3 -3
- package/src/morpho.ts +32 -0
- package/src/prepareSend.ts +710 -458
- package/src/queryParams.ts +2 -1
- package/src/relayer.ts +15 -16
- package/src/sequenceWallet.ts +7 -3
- package/src/tokenBalances.ts +47 -0
- package/src/tokens.ts +17 -1
- package/src/trails.ts +2 -2
- package/src/wallets.ts +8 -0
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountActionsDropdown.tsx +9 -15
- package/src/widget/components/AccountIntentTransactionHistory.tsx +1 -1
- package/src/widget/components/AccountSettings.tsx +10 -27
- package/src/widget/components/ChainFilterDropdown.tsx +1 -1
- package/src/widget/components/ChainList.tsx +1 -1
- package/src/widget/components/ClassicSwap.tsx +111 -155
- package/src/widget/components/ConnectWallet.tsx +10 -39
- package/src/widget/components/ConnectedWallets.tsx +113 -58
- package/src/widget/components/Earn.tsx +73 -589
- package/src/widget/components/EarnPools.tsx +2 -1
- package/src/widget/components/Fund.tsx +81 -109
- package/src/widget/components/FundMethods.tsx +82 -159
- package/src/widget/components/FundSwap.tsx +52 -0
- package/src/widget/components/FundingMethodSelectorButton.tsx +60 -0
- package/src/widget/components/Modal.tsx +6 -2
- package/src/widget/components/Pay.tsx +198 -200
- package/src/widget/components/PercentageMaxButtons.tsx +77 -0
- package/src/widget/components/PoolDeposit.tsx +593 -0
- package/src/widget/components/PoolWithdraw.tsx +903 -0
- package/src/widget/components/QuoteDetails.tsx +22 -8
- package/src/widget/components/Receive.tsx +1 -3
- package/src/widget/components/RecipientSelectorButton.tsx +42 -0
- package/src/widget/components/Recipients.tsx +64 -156
- package/src/widget/components/RefundWarning.tsx +5 -1
- package/src/widget/components/RequiredPropsError.tsx +33 -0
- package/src/widget/components/ScreenHeader.tsx +5 -1
- package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
- package/src/widget/components/Swap.tsx +2 -43
- package/src/widget/components/SwapSettings.tsx +3 -15
- package/src/widget/components/TokenImage.tsx +21 -4
- package/src/widget/components/TokenList.tsx +0 -1
- package/src/widget/components/TokenSelector.tsx +2 -1
- package/src/widget/components/TokenSelectorButton.tsx +75 -0
- package/src/widget/components/UserPreferences.tsx +6 -24
- package/src/widget/components/WaasFeeOptions.tsx +331 -0
- package/src/widget/components/WalletConfirmation.tsx +55 -3
- package/src/widget/components/WalletList.tsx +7 -5
- package/src/widget/hooks/useBack.tsx +113 -9
- package/src/widget/hooks/useCheckout.ts +36 -20
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
- package/src/widget/hooks/useInitialRedirect.tsx +70 -0
- package/src/widget/hooks/usePayMessage.tsx +86 -11
- package/src/widget/hooks/useSelectedFeeToken.tsx +10 -16
- package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
- package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
- package/src/widget/hooks/useSendForm.ts +34 -12
- package/src/widget/hooks/useTokenList.ts +1 -1
- package/src/widget/index.css +27 -0
- package/src/widget/widget.tsx +245 -208
- package/dist/widget/components/FundSendForm.d.ts.map +0 -1
- package/dist/widget/components/PaySendForm.d.ts.map +0 -1
- package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
- package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
- package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
- package/src/widget/components/FundSendForm.tsx +0 -903
- package/src/widget/components/PaySendForm.tsx +0 -869
- package/src/widget/components/SimpleSwap.tsx +0 -983
- package/src/widget/hooks/useSwapSettings.tsx +0 -100
- /package/dist/{style.css → 0xtrails.css} +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { TokenImage } from "./TokenImage.js"
|
|
2
2
|
import { ChevronLeft } from "lucide-react"
|
|
3
3
|
import type React from "react"
|
|
4
|
-
import { useEffect, useState } from "react"
|
|
4
|
+
import { useEffect, useMemo, useState } from "react"
|
|
5
5
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
6
6
|
import { QuoteDetails } from "./QuoteDetails.js"
|
|
7
|
+
import { WaasFeeOptions } from "./WaasFeeOptions.js"
|
|
8
|
+
import { useAccount } from "wagmi"
|
|
7
9
|
|
|
8
10
|
interface WalletConfirmationProps {
|
|
9
11
|
onBack?: () => void
|
|
@@ -21,6 +23,9 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
21
23
|
}) => {
|
|
22
24
|
const [showContent, setShowContent] = useState(false)
|
|
23
25
|
const [showTimeoutWarning, setShowTimeoutWarning] = useState(false)
|
|
26
|
+
const [isFeeOptionConfirmed, setIsFeeOptionConfirmed] = useState(false)
|
|
27
|
+
const [areFeeOptionsLoaded, setAreFeeOptionsLoaded] = useState(false)
|
|
28
|
+
const { connector } = useAccount()
|
|
24
29
|
|
|
25
30
|
useEffect(() => {
|
|
26
31
|
setShowContent(true)
|
|
@@ -39,6 +44,25 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
39
44
|
return () => clearTimeout(timer)
|
|
40
45
|
}, [retryEnabled])
|
|
41
46
|
|
|
47
|
+
const isSequenceWaas = useMemo(() => {
|
|
48
|
+
if (!connector) return false
|
|
49
|
+
const connectorName = connector.name?.toLowerCase() || ""
|
|
50
|
+
const connectorId = connector.id?.toLowerCase() || ""
|
|
51
|
+
const isSequenceWaas =
|
|
52
|
+
connectorName.includes("waas") ||
|
|
53
|
+
connectorId.includes("waas") ||
|
|
54
|
+
connectorId === "sequence-waas"
|
|
55
|
+
|
|
56
|
+
console.log("[trails-sdk] Sequence WaaS detection:", {
|
|
57
|
+
connectorName,
|
|
58
|
+
connectorId,
|
|
59
|
+
isSequenceWaas,
|
|
60
|
+
connector: connector.name,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return isSequenceWaas
|
|
64
|
+
}, [connector])
|
|
65
|
+
|
|
42
66
|
return (
|
|
43
67
|
<div className="space-y-6">
|
|
44
68
|
<div className="flex items-center relative">
|
|
@@ -67,6 +91,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
67
91
|
imageUrl={quote?.originToken.imageUrl}
|
|
68
92
|
symbol={quote?.originToken.symbol}
|
|
69
93
|
chainId={quote?.originChain.id}
|
|
94
|
+
contractAddress={quote?.originToken.contractAddress}
|
|
70
95
|
size={64}
|
|
71
96
|
/>
|
|
72
97
|
</div>
|
|
@@ -76,12 +101,39 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
|
|
|
76
101
|
className={`mb-2 transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
|
|
77
102
|
>
|
|
78
103
|
<h2 className="text-xl font-bold text-gray-900 dark:text-white">
|
|
79
|
-
{retryEnabled
|
|
104
|
+
{retryEnabled
|
|
105
|
+
? "Try again"
|
|
106
|
+
: !isSequenceWaas
|
|
107
|
+
? "Waiting for wallet…"
|
|
108
|
+
: isFeeOptionConfirmed
|
|
109
|
+
? "Waiting for wallet…"
|
|
110
|
+
: areFeeOptionsLoaded
|
|
111
|
+
? "Waiting for fee selection…"
|
|
112
|
+
: "Waiting for fee options…"}
|
|
80
113
|
</h2>
|
|
81
114
|
<p className="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
|
82
|
-
|
|
115
|
+
{!isSequenceWaas
|
|
116
|
+
? "Please approve the request in your wallet"
|
|
117
|
+
: isFeeOptionConfirmed
|
|
118
|
+
? "Please approve the request in your wallet"
|
|
119
|
+
: ""}
|
|
83
120
|
</p>
|
|
84
121
|
</div>
|
|
122
|
+
|
|
123
|
+
{isSequenceWaas && (
|
|
124
|
+
<div
|
|
125
|
+
className={`mb-2 mt-4 transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
|
|
126
|
+
>
|
|
127
|
+
<WaasFeeOptions
|
|
128
|
+
chainId={quote?.originChain.id}
|
|
129
|
+
setIsFeeOptionConfirmed={setIsFeeOptionConfirmed}
|
|
130
|
+
onFeeOptionsLoaded={() => {
|
|
131
|
+
console.log("[trails-sdk] Fee options loaded callback called")
|
|
132
|
+
setAreFeeOptionsLoaded(true)
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
)}
|
|
85
137
|
</div>
|
|
86
138
|
|
|
87
139
|
{/* Timeout Warning */}
|
|
@@ -21,7 +21,9 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
21
21
|
|
|
22
22
|
const prefilteredWalletOptions = useMemo(() => {
|
|
23
23
|
return walletOptions
|
|
24
|
-
.filter(
|
|
24
|
+
.filter(
|
|
25
|
+
(wallet) => wallet.id !== "injected" && wallet.id !== "sequence-waas",
|
|
26
|
+
)
|
|
25
27
|
.sort((a, b) => {
|
|
26
28
|
const aIndex = topShownWallets.indexOf(a.id)
|
|
27
29
|
const bIndex = topShownWallets.indexOf(b.id)
|
|
@@ -45,10 +47,11 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
45
47
|
const filteredWalletOptions = useMemo(() => {
|
|
46
48
|
if (!searchTerm.trim()) return prefilteredWalletOptions
|
|
47
49
|
|
|
50
|
+
const query = searchTerm.trim().toLowerCase()
|
|
48
51
|
return prefilteredWalletOptions.filter((wallet) => {
|
|
49
52
|
return (
|
|
50
|
-
wallet.name.toLowerCase().includes(
|
|
51
|
-
wallet.id.toLowerCase().includes(
|
|
53
|
+
wallet.name.toLowerCase().includes(query) ||
|
|
54
|
+
wallet.id.toLowerCase().includes(query)
|
|
52
55
|
)
|
|
53
56
|
})
|
|
54
57
|
}, [prefilteredWalletOptions, searchTerm])
|
|
@@ -60,10 +63,9 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
60
63
|
return (
|
|
61
64
|
<div className="space-y-6">
|
|
62
65
|
<ScreenHeader
|
|
63
|
-
headerContent="
|
|
66
|
+
headerContent="Connect a Wallet"
|
|
64
67
|
headerContentAlign="left"
|
|
65
68
|
onBack={onBack}
|
|
66
|
-
showAccountActions={true}
|
|
67
69
|
/>
|
|
68
70
|
|
|
69
71
|
{/* 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,12 @@ 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
|
|
23
|
+
getPreviousScreen: () => Screen | null
|
|
12
24
|
}
|
|
13
25
|
|
|
14
26
|
const BackContext = createContext<BackContextType | null>(null)
|
|
@@ -20,6 +32,9 @@ interface BackProviderProps {
|
|
|
20
32
|
export function BackProvider({ children }: BackProviderProps) {
|
|
21
33
|
const { currentScreen, setCurrentScreen } = useCurrentScreen()
|
|
22
34
|
const [history, setHistory] = useState<Screen[]>([])
|
|
35
|
+
const [navigationStack, setNavigationStack] = useState<
|
|
36
|
+
Array<[Screen, Screen?]>
|
|
37
|
+
>([])
|
|
23
38
|
const [isNavigatingBack, setIsNavigatingBack] = useState(false)
|
|
24
39
|
|
|
25
40
|
// Track screen changes and update history
|
|
@@ -45,20 +60,83 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
45
60
|
})
|
|
46
61
|
}, [currentScreen])
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
// Get the previous screen from navigation stack
|
|
64
|
+
const getPreviousScreen = (): Screen | null => {
|
|
65
|
+
if (navigationStack.length === 0) {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Find the current screen in the navigation stack
|
|
70
|
+
const currentIndex = navigationStack.findIndex(
|
|
71
|
+
([screen]) => screen === currentScreen,
|
|
72
|
+
)
|
|
73
|
+
if (currentIndex === -1) {
|
|
74
|
+
return null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const currentEntry = navigationStack[currentIndex]
|
|
78
|
+
if (!currentEntry) {
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
const [, backToScreen] = currentEntry
|
|
82
|
+
|
|
83
|
+
// If this screen has a specific back target, use it
|
|
84
|
+
if (backToScreen) {
|
|
85
|
+
return backToScreen
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Otherwise, go to the previous screen in the stack
|
|
89
|
+
if (currentIndex > 0) {
|
|
90
|
+
const previousEntry = navigationStack[currentIndex - 1]
|
|
91
|
+
if (previousEntry) {
|
|
92
|
+
const [previousScreen] = previousEntry
|
|
93
|
+
return previousScreen
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Function to set current screen with optional back target
|
|
101
|
+
const setCurrentScreenWithBack = useCallback(
|
|
102
|
+
(screen: Screen, backTo?: Screen) => {
|
|
103
|
+
setNavigationStack((prevStack) => {
|
|
104
|
+
// Remove any existing entry for this screen
|
|
105
|
+
const filteredStack = prevStack.filter(
|
|
106
|
+
([existingScreen]) => existingScreen !== screen,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
// Add new entry
|
|
110
|
+
const newEntry: [Screen, Screen?] = backTo ? [screen, backTo] : [screen]
|
|
111
|
+
const newStack = [...filteredStack, newEntry]
|
|
112
|
+
|
|
113
|
+
// Keep stack limited to last 10 entries
|
|
114
|
+
if (newStack.length > 10) {
|
|
115
|
+
return newStack.slice(-10)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return newStack
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
setCurrentScreen(screen)
|
|
122
|
+
},
|
|
123
|
+
[setCurrentScreen],
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
const canGoBack = navigationStack.length > 0 || history.length > 1
|
|
49
127
|
|
|
50
128
|
const goBack = canGoBack
|
|
51
129
|
? () => {
|
|
52
|
-
|
|
53
|
-
const newHistory = history.slice(0, -1)
|
|
54
|
-
const previousScreen = newHistory[newHistory.length - 1]
|
|
130
|
+
const previousScreen = getPreviousScreen()
|
|
55
131
|
|
|
56
132
|
logger.console.log(
|
|
57
|
-
"[trails-sdk] goBack",
|
|
133
|
+
"[trails-sdk] goBack (navigation stack)",
|
|
58
134
|
"previousScreen:",
|
|
59
135
|
previousScreen,
|
|
60
136
|
"currentScreen:",
|
|
61
137
|
currentScreen,
|
|
138
|
+
"navigationStack:",
|
|
139
|
+
navigationStack,
|
|
62
140
|
)
|
|
63
141
|
|
|
64
142
|
// Set flag to prevent auto-selection when navigating back
|
|
@@ -67,24 +145,44 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
67
145
|
}
|
|
68
146
|
|
|
69
147
|
if (previousScreen) {
|
|
70
|
-
|
|
148
|
+
// Remove current screen from navigation stack
|
|
149
|
+
setNavigationStack((prevStack) =>
|
|
150
|
+
prevStack.filter(([screen]) => screen !== currentScreen),
|
|
151
|
+
)
|
|
71
152
|
setCurrentScreen(previousScreen)
|
|
153
|
+
} else {
|
|
154
|
+
// Fallback: if no navigation stack, use regular history
|
|
155
|
+
const regularHistory = history
|
|
156
|
+
if (regularHistory.length > 1) {
|
|
157
|
+
const fallbackScreen = regularHistory[regularHistory.length - 2]
|
|
158
|
+
if (fallbackScreen) {
|
|
159
|
+
logger.console.log(
|
|
160
|
+
"[trails-sdk] goBack (fallback to regular history)",
|
|
161
|
+
"previousScreen:",
|
|
162
|
+
fallbackScreen,
|
|
163
|
+
)
|
|
164
|
+
setCurrentScreen(fallbackScreen)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
72
167
|
}
|
|
73
168
|
|
|
74
|
-
// Reset the flag after a
|
|
169
|
+
// Reset the flag after a longer delay to allow the screen change to complete
|
|
170
|
+
// and prevent post-connection navigation from interfering with manual back navigation
|
|
75
171
|
if (setIsNavigatingBack) {
|
|
76
172
|
setTimeout(() => {
|
|
77
173
|
setIsNavigatingBack(false)
|
|
78
|
-
},
|
|
174
|
+
}, 500)
|
|
79
175
|
}
|
|
80
176
|
}
|
|
81
177
|
: undefined
|
|
82
178
|
|
|
83
179
|
const clearHistory = () => {
|
|
84
180
|
setHistory([currentScreen])
|
|
181
|
+
setNavigationStack([[currentScreen]])
|
|
85
182
|
}
|
|
86
183
|
|
|
87
184
|
const getHistory = () => history
|
|
185
|
+
const getBreadcrumbHistory = () => navigationStack.map(([screen]) => screen)
|
|
88
186
|
|
|
89
187
|
const value: BackContextType = {
|
|
90
188
|
goBack,
|
|
@@ -92,6 +190,12 @@ export function BackProvider({ children }: BackProviderProps) {
|
|
|
92
190
|
clearHistory,
|
|
93
191
|
isNavigatingBack,
|
|
94
192
|
getHistory,
|
|
193
|
+
getBreadcrumbHistory,
|
|
194
|
+
addBreadcrumb: () => {}, // Deprecated, kept for compatibility
|
|
195
|
+
setAccountSettingsSource: () => {}, // Deprecated, kept for compatibility
|
|
196
|
+
getAccountSettingsSource: () => null, // Deprecated, kept for compatibility
|
|
197
|
+
setCurrentScreenWithBack,
|
|
198
|
+
getPreviousScreen,
|
|
95
199
|
}
|
|
96
200
|
|
|
97
201
|
return <BackContext.Provider value={value}>{children}</BackContext.Provider>
|
|
@@ -2,6 +2,7 @@ import { useCallback, useRef } from "react"
|
|
|
2
2
|
import { getSessionId } from "../../analytics.js"
|
|
3
3
|
import { logger } from "../../logger.js"
|
|
4
4
|
import { updatePersistentToast } from "../../toast.js"
|
|
5
|
+
import { getPrettifiedErrorMessage } from "../../error.js"
|
|
5
6
|
|
|
6
7
|
export type CheckoutCallbacks = {
|
|
7
8
|
onCheckoutStart?: (data: { sessionId: string }) => void
|
|
@@ -17,7 +18,7 @@ export type CheckoutCallbacks = {
|
|
|
17
18
|
export type CheckoutOnHandlers = {
|
|
18
19
|
triggerCheckoutStart: () => void
|
|
19
20
|
triggerCheckoutQuote: (quote: any) => void
|
|
20
|
-
triggerCheckoutComplete: () => void
|
|
21
|
+
triggerCheckoutComplete: (txStatus: "success" | "fail") => void
|
|
21
22
|
triggerCheckoutError: (error: string) => void
|
|
22
23
|
triggerCheckoutStatusUpdate: (transactionStates: any[]) => void
|
|
23
24
|
}
|
|
@@ -81,26 +82,38 @@ export function useCheckout({
|
|
|
81
82
|
[onCheckoutQuote],
|
|
82
83
|
)
|
|
83
84
|
|
|
84
|
-
const triggerCheckoutComplete = useCallback(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
const triggerCheckoutComplete = useCallback(
|
|
86
|
+
(txStatus: "success" | "fail") => {
|
|
87
|
+
if (onCheckoutComplete && sessionIdRef.current) {
|
|
88
|
+
try {
|
|
89
|
+
onCheckoutComplete({
|
|
90
|
+
sessionId: sessionIdRef.current,
|
|
91
|
+
})
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logger.console.error(
|
|
94
|
+
"[trails-sdk] Error calling onCheckoutComplete:",
|
|
95
|
+
error,
|
|
96
|
+
)
|
|
97
|
+
}
|
|
95
98
|
}
|
|
96
|
-
}
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
if (txStatus === "success") {
|
|
101
|
+
updatePersistentToast(
|
|
102
|
+
"Transaction Complete",
|
|
103
|
+
"Your transaction has been successfully processed",
|
|
104
|
+
"success",
|
|
105
|
+
)
|
|
106
|
+
} else {
|
|
107
|
+
// Default to error for any non-success status (including 'fail' and any unexpected values)
|
|
108
|
+
updatePersistentToast(
|
|
109
|
+
"Transaction Failed",
|
|
110
|
+
"Your transaction failed or was refunded",
|
|
111
|
+
"error",
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
[onCheckoutComplete],
|
|
116
|
+
)
|
|
104
117
|
|
|
105
118
|
const triggerCheckoutError = useCallback(
|
|
106
119
|
(error: string) => {
|
|
@@ -120,7 +133,10 @@ export function useCheckout({
|
|
|
120
133
|
|
|
121
134
|
updatePersistentToast(
|
|
122
135
|
"Transaction Failed",
|
|
123
|
-
|
|
136
|
+
getPrettifiedErrorMessage(
|
|
137
|
+
error,
|
|
138
|
+
"An error occurred while processing your transaction",
|
|
139
|
+
),
|
|
124
140
|
"error",
|
|
125
141
|
)
|
|
126
142
|
},
|
|
@@ -14,6 +14,7 @@ import { getChainInfo } from "../../chains.js"
|
|
|
14
14
|
import { logger } from "../../logger.js"
|
|
15
15
|
|
|
16
16
|
const MINIMUM_24H_VOLUME_USD = 1_000_000 // $1M
|
|
17
|
+
const MINIMUM_BALANCE_USD_FOR_PRIORITIZATION = 1 // $1
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Hook for intelligent default token selection in 0xtrails widget.
|
|
@@ -33,9 +34,9 @@ const MINIMUM_24H_VOLUME_USD = 1_000_000 // $1M
|
|
|
33
34
|
* - Fallback to any token with balance > 0
|
|
34
35
|
*
|
|
35
36
|
* Destination Token Logic (only when toToken/toChainId not provided):
|
|
36
|
-
* -
|
|
37
|
-
* - Default destination
|
|
38
|
-
* - Fallback
|
|
37
|
+
* - Default destination chain: Base if origin is not Base, Arbitrum if origin is Base
|
|
38
|
+
* - Default destination token: USDC on destination chain
|
|
39
|
+
* - Fallback: Same symbol on destination chain > ETH on destination chain > first available token on destination chain
|
|
39
40
|
*
|
|
40
41
|
* @returns defaultOriginToken - Best origin token that can cover targetAmountUsd (if specified)
|
|
41
42
|
* @returns defaultDestinationToken - Matching token on different chain (null if toToken/toChainId set)
|
|
@@ -231,8 +232,11 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
// Helper to sort tokens by balance USD and volume
|
|
234
|
-
const sortTokensByBalanceAndVolume = (
|
|
235
|
-
|
|
235
|
+
const sortTokensByBalanceAndVolume = (
|
|
236
|
+
tokens: TokenBalanceExtended[],
|
|
237
|
+
targetAmount?: number,
|
|
238
|
+
) => {
|
|
239
|
+
const sortedTokens = [...tokens].sort((a, b) => {
|
|
236
240
|
const aVolume = getToken24hVolume(a)
|
|
237
241
|
const bVolume = getToken24hVolume(b)
|
|
238
242
|
const aHighVolume = aVolume >= MINIMUM_24H_VOLUME_USD
|
|
@@ -247,6 +251,56 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
247
251
|
const bBalanceUsd = b.balanceUsd ?? 0
|
|
248
252
|
return bBalanceUsd - aBalanceUsd
|
|
249
253
|
})
|
|
254
|
+
|
|
255
|
+
// After initial sorting, prioritize USDC and native tokens at the top
|
|
256
|
+
const effectiveTargetAmount =
|
|
257
|
+
targetAmount ?? MINIMUM_BALANCE_USD_FOR_PRIORITIZATION
|
|
258
|
+
|
|
259
|
+
const prioritizedTokens: TokenBalanceExtended[] = []
|
|
260
|
+
const remainingTokens: TokenBalanceExtended[] = []
|
|
261
|
+
|
|
262
|
+
// Separate tokens into prioritized and remaining
|
|
263
|
+
for (const token of sortedTokens) {
|
|
264
|
+
const balanceUsd = token.balanceUsd ?? 0
|
|
265
|
+
const isNative =
|
|
266
|
+
!("contractAddress" in token) || token.contractAddress === zeroAddress
|
|
267
|
+
const isUSDC =
|
|
268
|
+
!isNative && token.contractInfo?.symbol?.toUpperCase() === "USDC"
|
|
269
|
+
|
|
270
|
+
if ((isUSDC || isNative) && balanceUsd >= effectiveTargetAmount) {
|
|
271
|
+
prioritizedTokens.push(token)
|
|
272
|
+
} else {
|
|
273
|
+
remainingTokens.push(token)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Sort prioritized tokens: USDC first, then native tokens
|
|
278
|
+
prioritizedTokens.sort((a, b) => {
|
|
279
|
+
const aIsNative =
|
|
280
|
+
!("contractAddress" in a) || a.contractAddress === zeroAddress
|
|
281
|
+
const bIsNative =
|
|
282
|
+
!("contractAddress" in b) || b.contractAddress === zeroAddress
|
|
283
|
+
const aIsUSDC =
|
|
284
|
+
!aIsNative && a.contractInfo?.symbol?.toUpperCase() === "USDC"
|
|
285
|
+
const bIsUSDC =
|
|
286
|
+
!bIsNative && b.contractInfo?.symbol?.toUpperCase() === "USDC"
|
|
287
|
+
|
|
288
|
+
// USDC comes first
|
|
289
|
+
if (aIsUSDC && !bIsUSDC) return -1
|
|
290
|
+
if (!aIsUSDC && bIsUSDC) return 1
|
|
291
|
+
|
|
292
|
+
// Then native tokens
|
|
293
|
+
if (aIsNative && !bIsNative) return -1
|
|
294
|
+
if (!aIsNative && bIsNative) return 1
|
|
295
|
+
|
|
296
|
+
// Within same type, sort by balance USD (highest first)
|
|
297
|
+
const aBalanceUsd = a.balanceUsd ?? 0
|
|
298
|
+
const bBalanceUsd = b.balanceUsd ?? 0
|
|
299
|
+
return bBalanceUsd - aBalanceUsd
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
// Return prioritized tokens first, then remaining tokens
|
|
303
|
+
return [...prioritizedTokens, ...remainingTokens]
|
|
250
304
|
}
|
|
251
305
|
|
|
252
306
|
// Find the best origin token using intelligent selection
|
|
@@ -281,7 +335,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
281
335
|
const sameChainTokens = tokensWithSufficientBalance.filter(
|
|
282
336
|
(token) => token.chainId === targetChainId,
|
|
283
337
|
)
|
|
284
|
-
const sortedSameChain = sortTokensByBalanceAndVolume(
|
|
338
|
+
const sortedSameChain = sortTokensByBalanceAndVolume(
|
|
339
|
+
sameChainTokens,
|
|
340
|
+
effectiveTargetAmount,
|
|
341
|
+
)
|
|
285
342
|
bestOriginToken = sortedSameChain[0] ?? null
|
|
286
343
|
if (bestOriginToken) {
|
|
287
344
|
logger.console.log(
|
|
@@ -296,7 +353,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
296
353
|
(token) =>
|
|
297
354
|
tokenMatches(token, toToken) && token.chainId !== targetChainId,
|
|
298
355
|
)
|
|
299
|
-
const sortedSameToken = sortTokensByBalanceAndVolume(
|
|
356
|
+
const sortedSameToken = sortTokensByBalanceAndVolume(
|
|
357
|
+
sameTokenDiffChain,
|
|
358
|
+
effectiveTargetAmount,
|
|
359
|
+
)
|
|
300
360
|
bestOriginToken = sortedSameToken[0] ?? null
|
|
301
361
|
if (bestOriginToken) {
|
|
302
362
|
logger.console.log(
|
|
@@ -310,8 +370,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
310
370
|
const diffChainDiffToken = tokensWithSufficientBalance.filter(
|
|
311
371
|
(token) => token.chainId !== targetChainId,
|
|
312
372
|
)
|
|
313
|
-
const sortedDiffChainDiffToken =
|
|
314
|
-
|
|
373
|
+
const sortedDiffChainDiffToken = sortTokensByBalanceAndVolume(
|
|
374
|
+
diffChainDiffToken,
|
|
375
|
+
effectiveTargetAmount,
|
|
376
|
+
)
|
|
315
377
|
bestOriginToken = sortedDiffChainDiffToken[0] ?? null
|
|
316
378
|
if (bestOriginToken) {
|
|
317
379
|
logger.console.log(
|
|
@@ -322,7 +384,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
322
384
|
|
|
323
385
|
// Fallback: If no token can cover target amount, use any token (sorted by balance/volume)
|
|
324
386
|
if (!bestOriginToken) {
|
|
325
|
-
const allTokensSorted = sortTokensByBalanceAndVolume(
|
|
387
|
+
const allTokensSorted = sortTokensByBalanceAndVolume(
|
|
388
|
+
tokensWithBalance,
|
|
389
|
+
effectiveTargetAmount,
|
|
390
|
+
)
|
|
326
391
|
bestOriginToken = allTokensSorted[0] ?? null
|
|
327
392
|
logger.console.log(
|
|
328
393
|
"[trails-sdk] Fallback: No token can cover target amount, using highest balance token",
|
|
@@ -330,8 +395,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
330
395
|
}
|
|
331
396
|
} else {
|
|
332
397
|
// When no specific destination is set, select highest value token with good liquidity
|
|
333
|
-
const sortedByBalanceAndVolume =
|
|
334
|
-
|
|
398
|
+
const sortedByBalanceAndVolume = sortTokensByBalanceAndVolume(
|
|
399
|
+
tokensWithBalance,
|
|
400
|
+
MINIMUM_BALANCE_USD_FOR_PRIORITIZATION,
|
|
401
|
+
) // Use minimum balance for prioritization
|
|
335
402
|
bestOriginToken = sortedByBalanceAndVolume[0] ?? null
|
|
336
403
|
logger.console.log(
|
|
337
404
|
"[trails-sdk] No destination specified, selected highest value token with best liquidity",
|
|
@@ -358,30 +425,39 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
358
425
|
let destinationToken: DefaultToken | null = null
|
|
359
426
|
|
|
360
427
|
if (shouldComputeDestination) {
|
|
361
|
-
// Determine
|
|
428
|
+
// Determine destination chain: Base if origin is not Base, Arbitrum if origin is Base
|
|
362
429
|
const defaultDestChainId =
|
|
363
430
|
originToken.chainId === base.id ? arbitrum.id : base.id
|
|
364
431
|
|
|
365
|
-
// Find
|
|
366
|
-
const
|
|
367
|
-
(token: any) =>
|
|
432
|
+
// Find USDC on destination chain first
|
|
433
|
+
const usdcOnDestChain = supportedTokens.find(
|
|
434
|
+
(token: any) =>
|
|
435
|
+
token.chainId === defaultDestChainId && token.symbol === "USDC",
|
|
368
436
|
)
|
|
369
437
|
|
|
370
438
|
let destToken: any = null
|
|
371
439
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return token.symbol.toUpperCase() === originToken.symbol.toUpperCase()
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
if (sameSymbolToken) {
|
|
378
|
-
destToken = sameSymbolToken
|
|
440
|
+
if (usdcOnDestChain) {
|
|
441
|
+
destToken = usdcOnDestChain
|
|
379
442
|
} else {
|
|
380
|
-
// Fallback:
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
443
|
+
// Fallback: Find matching token on destination chain
|
|
444
|
+
const destChainTokens = supportedTokens.filter(
|
|
445
|
+
(token: any) => token.chainId === defaultDestChainId,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
// Try to find same symbol on destination chain first
|
|
449
|
+
const sameSymbolOnDestChain = destChainTokens.find((token: any) => {
|
|
450
|
+
return token.symbol.toUpperCase() === originToken.symbol.toUpperCase()
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
if (sameSymbolOnDestChain) {
|
|
454
|
+
destToken = sameSymbolOnDestChain
|
|
455
|
+
} else {
|
|
456
|
+
// Fallback: ETH on destination chain > first available token on destination chain
|
|
457
|
+
destToken =
|
|
458
|
+
destChainTokens.find((token: any) => token.symbol === "ETH") ||
|
|
459
|
+
destChainTokens[0]
|
|
460
|
+
}
|
|
385
461
|
}
|
|
386
462
|
|
|
387
463
|
const decimals = destToken?.decimals
|