0xtrails 0.9.2 → 0.9.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/{ccip-g6lDdnrD.js → ccip-lAtzqne5.js} +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-D-QngA_s.js → index-D5AG6huo.js} +22290 -21786
- package/dist/index.js +3 -3
- package/dist/intents.d.ts +1 -1
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts +5 -2
- package/dist/mutations.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/constants.d.ts +1 -0
- package/dist/transactionIntent/constants.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +4 -1
- package/dist/transactionIntent/deposits/standardDeposit.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/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +2 -0
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/resilientDepositTracker.d.ts +25 -0
- package/dist/transactionIntent/utils/resilientDepositTracker.d.ts.map +1 -0
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +2 -2
- 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.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
- package/dist/widget/components/UserPreferences.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 +2 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +2 -0
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +1 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/config.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/error.ts +6 -1
- package/src/intents.ts +22 -1
- package/src/prices.ts +1 -1
- package/src/tokens.ts +4 -3
- package/src/transactionIntent/constants.ts +2 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +7 -0
- package/src/transactionIntent/deposits/standardDeposit.ts +194 -37
- package/src/transactionIntent/handlers/crossChain.ts +152 -105
- package/src/transactionIntent/handlers/sameChainSameToken.ts +1 -0
- package/src/transactionIntent/quote/normalizeQuote.ts +7 -4
- package/src/transactionIntent/types.ts +2 -0
- package/src/transactionIntent/utils/resilientDepositTracker.ts +281 -0
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +170 -87
- package/src/widget/components/ClassicSwap.tsx +7 -1
- package/src/widget/components/ConfigDisplay.tsx +5 -0
- package/src/widget/components/Earn.tsx +14 -1
- package/src/widget/components/EarnPools.tsx +180 -59
- package/src/widget/components/Fund.tsx +3 -1
- package/src/widget/components/PoolWithdraw.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +12 -35
- package/src/widget/components/Receipt.tsx +66 -40
- package/src/widget/components/SlippageToleranceSettings.tsx +86 -44
- package/src/widget/components/TransactionDetails.tsx +138 -218
- package/src/widget/components/UserPreferences.tsx +114 -41
- package/src/widget/components/WalletConnect.tsx +111 -48
- package/src/widget/hooks/useQuote.ts +389 -352
- package/src/widget/providers/TrailsProvider.tsx +5 -0
- package/src/widget/widget.tsx +2 -0
|
@@ -191,6 +191,8 @@ export type Quote = {
|
|
|
191
191
|
originTokenRate: string
|
|
192
192
|
routeProviders: RouteProviderInfo[]
|
|
193
193
|
destinationTokenRate: string
|
|
194
|
+
originTokenPriceUsd: number
|
|
195
|
+
destinationTokenPriceUsd: number
|
|
194
196
|
gasCostUsd: number | null
|
|
195
197
|
gasCostUsdDisplay: string
|
|
196
198
|
gasCost: string
|
|
@@ -585,394 +587,429 @@ export function useQuote({
|
|
|
585
587
|
return null
|
|
586
588
|
}
|
|
587
589
|
|
|
588
|
-
//
|
|
589
|
-
|
|
590
|
+
// Create a 20-second timeout
|
|
591
|
+
const timeoutId = setTimeout(() => {
|
|
592
|
+
logger.console.warn(
|
|
593
|
+
"[trails-sdk] [useQuote] Quote request timed out after 20 seconds",
|
|
594
|
+
)
|
|
595
|
+
abortControllerRef.current.abort()
|
|
596
|
+
}, 20000) // 20 seconds
|
|
597
|
+
|
|
590
598
|
try {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
balanceErrorMessage
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
599
|
+
// Get token balance using async method
|
|
600
|
+
let balances: any[] = []
|
|
601
|
+
try {
|
|
602
|
+
const result = await getTokenBalancesWithPrices({
|
|
603
|
+
account: walletClient.account!.address,
|
|
604
|
+
indexerGatewayClient,
|
|
605
|
+
trailsClient,
|
|
606
|
+
})
|
|
607
|
+
balances = result.balances
|
|
608
|
+
} catch (balanceError) {
|
|
609
|
+
const balanceErrorMessage = getFullErrorMessage(balanceError)
|
|
610
|
+
const isCorsError =
|
|
611
|
+
balanceErrorMessage.includes("Cross-Origin") ||
|
|
612
|
+
balanceErrorMessage.includes("CORS") ||
|
|
613
|
+
balanceErrorMessage.includes("Same Origin Policy")
|
|
614
|
+
const isNetworkError =
|
|
615
|
+
balanceErrorMessage.includes("fetch failed") ||
|
|
616
|
+
balanceErrorMessage.includes("network")
|
|
606
617
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
618
|
+
if (isCorsError || isNetworkError) {
|
|
619
|
+
logger.console.warn(
|
|
620
|
+
"[trails-sdk] [useQuote] Network or CORS error fetching balances, proceeding with quote using zero balance:",
|
|
621
|
+
{
|
|
622
|
+
error: balanceErrorMessage,
|
|
623
|
+
account: walletClient.account!.address,
|
|
624
|
+
},
|
|
625
|
+
)
|
|
626
|
+
// Continue with empty balances instead of crashing
|
|
627
|
+
balances = []
|
|
628
|
+
} else {
|
|
629
|
+
throw balanceError
|
|
630
|
+
}
|
|
619
631
|
}
|
|
620
|
-
}
|
|
621
632
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
633
|
+
const originTokenBalance = balances.find(
|
|
634
|
+
(b) =>
|
|
635
|
+
b.chainId === fromChainId &&
|
|
636
|
+
(b.contractAddress?.toLowerCase() ===
|
|
637
|
+
fromTokenAddress.toLowerCase() ||
|
|
638
|
+
(!b.contractAddress && fromTokenAddress === zeroAddress)),
|
|
639
|
+
)
|
|
631
640
|
|
|
632
|
-
|
|
633
|
-
// if (originTokenBalanceAmount === "0") {
|
|
634
|
-
// return null
|
|
635
|
-
// }
|
|
641
|
+
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
636
642
|
|
|
637
|
-
|
|
643
|
+
// Note: Disable this check for now to allow fetching a quote even when the origin balance is zero
|
|
644
|
+
// if (originTokenBalanceAmount === "0") {
|
|
645
|
+
// return null
|
|
646
|
+
// }
|
|
638
647
|
|
|
639
|
-
|
|
640
|
-
let originNativeTokenPriceUsd = 0
|
|
641
|
-
try {
|
|
642
|
-
const originChain = getChainInfo(fromChainId)
|
|
643
|
-
const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
|
|
644
|
-
if (nativeTokenSymbol) {
|
|
645
|
-
const nativePrice = await getTokenPrice(trailsClient, {
|
|
646
|
-
tokenSymbol: nativeTokenSymbol,
|
|
647
|
-
tokenAddress: zeroAddress,
|
|
648
|
-
chainId: fromChainId,
|
|
649
|
-
})
|
|
650
|
-
originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
|
|
651
|
-
logger.console.log(
|
|
652
|
-
"[trails-sdk] [useQuote] Origin native token price:",
|
|
653
|
-
{
|
|
654
|
-
chainId: fromChainId,
|
|
655
|
-
symbol: nativeTokenSymbol,
|
|
656
|
-
priceUsd: originNativeTokenPriceUsd,
|
|
657
|
-
},
|
|
658
|
-
)
|
|
659
|
-
}
|
|
660
|
-
} catch (error) {
|
|
661
|
-
logger.console.error(
|
|
662
|
-
"[trails-sdk] [useQuote] Error getting origin native token price:",
|
|
663
|
-
error,
|
|
664
|
-
)
|
|
665
|
-
}
|
|
648
|
+
// logger.console.log("supportedTokens", supportedTokens)
|
|
666
649
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
tokenAddress: string,
|
|
670
|
-
chainId: number,
|
|
671
|
-
): Promise<number | null> => {
|
|
650
|
+
// Get native token price for origin chain (for gas cost calculation)
|
|
651
|
+
let originNativeTokenPriceUsd = 0
|
|
672
652
|
try {
|
|
673
|
-
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
:
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
logger.console.
|
|
683
|
-
|
|
653
|
+
const originChain = getChainInfo(fromChainId)
|
|
654
|
+
const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
|
|
655
|
+
if (nativeTokenSymbol) {
|
|
656
|
+
const nativePrice = await getTokenPrice(trailsClient, {
|
|
657
|
+
tokenSymbol: nativeTokenSymbol,
|
|
658
|
+
tokenAddress: zeroAddress,
|
|
659
|
+
chainId: fromChainId,
|
|
660
|
+
})
|
|
661
|
+
originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
|
|
662
|
+
logger.console.log(
|
|
663
|
+
"[trails-sdk] [useQuote] Origin native token price:",
|
|
664
|
+
{
|
|
665
|
+
chainId: fromChainId,
|
|
666
|
+
symbol: nativeTokenSymbol,
|
|
667
|
+
priceUsd: originNativeTokenPriceUsd,
|
|
668
|
+
},
|
|
684
669
|
)
|
|
685
|
-
return null
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// For native tokens, return 18 decimals
|
|
689
|
-
if (tokenAddress.toLowerCase() === zeroAddress.toLowerCase()) {
|
|
690
|
-
const chainInfo = getChainInfo(chainId)
|
|
691
|
-
return chainInfo?.nativeCurrency.decimals ?? 18
|
|
692
670
|
}
|
|
693
|
-
|
|
694
|
-
const decimals = await publicClient.readContract({
|
|
695
|
-
address: tokenAddress as `0x${string}`,
|
|
696
|
-
abi: erc20Abi,
|
|
697
|
-
functionName: "decimals",
|
|
698
|
-
})
|
|
699
|
-
|
|
700
|
-
logger.console.log(
|
|
701
|
-
`[trails-sdk] Fetched decimals on-chain for token ${tokenAddress} on chain ${chainId}: ${decimals}`,
|
|
702
|
-
)
|
|
703
|
-
return decimals
|
|
704
671
|
} catch (error) {
|
|
705
672
|
logger.console.error(
|
|
706
|
-
|
|
673
|
+
"[trails-sdk] [useQuote] Error getting origin native token price:",
|
|
707
674
|
error,
|
|
708
675
|
)
|
|
709
|
-
return null
|
|
710
676
|
}
|
|
711
|
-
}
|
|
712
677
|
|
|
713
|
-
|
|
714
|
-
(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
678
|
+
// Helper function to fetch decimals on-chain if not found in token list
|
|
679
|
+
const fetchDecimalsOnChain = async (
|
|
680
|
+
tokenAddress: string,
|
|
681
|
+
chainId: number,
|
|
682
|
+
): Promise<number | null> => {
|
|
683
|
+
try {
|
|
684
|
+
// Use the hook-based RPC clients that are already available
|
|
685
|
+
const publicClient =
|
|
686
|
+
chainId === fromChainId
|
|
687
|
+
? originPublicClient
|
|
688
|
+
: chainId === toChainId
|
|
689
|
+
? destinationPublicClient
|
|
690
|
+
: null
|
|
723
691
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
692
|
+
if (!publicClient) {
|
|
693
|
+
logger.console.warn(
|
|
694
|
+
`[trails-sdk] No RPC client available for chain ${chainId}`,
|
|
695
|
+
)
|
|
696
|
+
return null
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// For native tokens, return 18 decimals
|
|
700
|
+
if (tokenAddress.toLowerCase() === zeroAddress.toLowerCase()) {
|
|
701
|
+
const chainInfo = getChainInfo(chainId)
|
|
702
|
+
return chainInfo?.nativeCurrency.decimals ?? 18
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const decimals = await publicClient.readContract({
|
|
706
|
+
address: tokenAddress as `0x${string}`,
|
|
707
|
+
abi: erc20Abi,
|
|
708
|
+
functionName: "decimals",
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
logger.console.log(
|
|
712
|
+
`[trails-sdk] Fetched decimals on-chain for token ${tokenAddress} on chain ${chainId}: ${decimals}`,
|
|
713
|
+
)
|
|
714
|
+
return decimals
|
|
715
|
+
} catch (error) {
|
|
716
|
+
logger.console.error(
|
|
717
|
+
`[trails-sdk] Error fetching decimals on-chain for token ${tokenAddress} on chain ${chainId}:`,
|
|
718
|
+
error,
|
|
719
|
+
)
|
|
720
|
+
return null
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const originToken = supportedTokens?.find(
|
|
725
|
+
(token) =>
|
|
726
|
+
token.contractAddress?.toLowerCase() ===
|
|
727
|
+
fromTokenAddress?.toLowerCase() &&
|
|
728
|
+
token.chainId === fromChainId,
|
|
733
729
|
)
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
730
|
+
const destinationToken = supportedTokens?.find(
|
|
731
|
+
(token) =>
|
|
732
|
+
token.contractAddress?.toLowerCase() ===
|
|
733
|
+
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
737
734
|
)
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
735
|
+
|
|
736
|
+
let sourceTokenDecimals = originToken?.decimals
|
|
737
|
+
if (!sourceTokenDecimals && fromTokenAddress && fromChainId) {
|
|
738
|
+
logger.console.warn(
|
|
739
|
+
"[trails-sdk] [useQuote] Source token decimals not found in token list, fetching on-chain:",
|
|
740
|
+
{
|
|
741
|
+
originToken,
|
|
742
|
+
fromTokenAddress,
|
|
743
|
+
fromChainId,
|
|
744
|
+
},
|
|
745
|
+
)
|
|
746
|
+
const onChainDecimals = await fetchDecimalsOnChain(
|
|
747
747
|
fromTokenAddress,
|
|
748
748
|
fromChainId,
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
let destinationTokenDecimals = destinationToken?.decimals
|
|
754
|
-
if (!destinationTokenDecimals && toTokenAddress && toChainId) {
|
|
755
|
-
logger.console.warn(
|
|
756
|
-
"[trails-sdk] Destination token decimals not found in token list, fetching on-chain:",
|
|
757
|
-
{
|
|
758
|
-
destinationToken,
|
|
759
|
-
toTokenAddress,
|
|
760
|
-
toChainId,
|
|
761
|
-
},
|
|
762
|
-
)
|
|
763
|
-
const onChainDecimals = await fetchDecimalsOnChain(
|
|
764
|
-
toTokenAddress,
|
|
765
|
-
toChainId,
|
|
766
|
-
)
|
|
767
|
-
if (onChainDecimals !== null) {
|
|
768
|
-
destinationTokenDecimals = onChainDecimals
|
|
749
|
+
)
|
|
750
|
+
if (onChainDecimals !== null) {
|
|
751
|
+
sourceTokenDecimals = onChainDecimals
|
|
752
|
+
}
|
|
769
753
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
754
|
+
if (!sourceTokenDecimals) {
|
|
755
|
+
logger.console.error(
|
|
756
|
+
"[trails-sdk] [useQuote] Source token decimals not found:",
|
|
757
|
+
{
|
|
758
|
+
originToken,
|
|
759
|
+
fromTokenAddress,
|
|
760
|
+
fromChainId,
|
|
761
|
+
},
|
|
762
|
+
)
|
|
763
|
+
throw new Error("Source token decimals not found")
|
|
764
|
+
}
|
|
765
|
+
let destinationTokenDecimals = destinationToken?.decimals
|
|
766
|
+
if (!destinationTokenDecimals && toTokenAddress && toChainId) {
|
|
767
|
+
logger.console.warn(
|
|
768
|
+
"[trails-sdk] Destination token decimals not found in token list, fetching on-chain:",
|
|
769
|
+
{
|
|
770
|
+
destinationToken,
|
|
771
|
+
toTokenAddress,
|
|
772
|
+
toChainId,
|
|
773
|
+
},
|
|
774
|
+
)
|
|
775
|
+
const onChainDecimals = await fetchDecimalsOnChain(
|
|
776
776
|
toTokenAddress,
|
|
777
777
|
toChainId,
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
778
|
+
)
|
|
779
|
+
if (onChainDecimals !== null) {
|
|
780
|
+
destinationTokenDecimals = onChainDecimals
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (!destinationTokenDecimals) {
|
|
784
|
+
logger.console.error(
|
|
785
|
+
"[trails-sdk] Destination token decimals not found:",
|
|
786
|
+
{
|
|
787
|
+
destinationToken,
|
|
788
|
+
toTokenAddress,
|
|
789
|
+
toChainId,
|
|
790
|
+
},
|
|
791
|
+
)
|
|
792
|
+
throw new Error("Destination token decimals not found")
|
|
793
|
+
}
|
|
794
|
+
const destinationTokenSymbol = destinationToken?.symbol ?? ""
|
|
795
|
+
const originTokenSymbol = originToken?.symbol ?? ""
|
|
784
796
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
797
|
+
// For qr-code and exchange fund methods, use a default amount of 100 tokens
|
|
798
|
+
// since the user will deposit from an external wallet (their connected wallet balance may be 0)
|
|
799
|
+
const effectiveOriginTokenBalance =
|
|
800
|
+
fundMethod === "qr-code" || fundMethod === "onramp-exchange"
|
|
801
|
+
? parseUnits("100", sourceTokenDecimals).toString()
|
|
802
|
+
: originTokenBalanceAmount
|
|
791
803
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
804
|
+
const options: PrepareSendOptions = {
|
|
805
|
+
account: walletClient.account!,
|
|
806
|
+
originTokenAddress: fromTokenAddress,
|
|
807
|
+
originChainId: fromChainId,
|
|
808
|
+
originTokenBalance: effectiveOriginTokenBalance,
|
|
809
|
+
destinationChainId: toChainId,
|
|
810
|
+
recipient: effectiveToAddress,
|
|
811
|
+
destinationTokenAddress: toTokenAddress,
|
|
812
|
+
swapAmount: debouncedSwapAmount.toString(),
|
|
813
|
+
tradeType: tradeType ?? TradeType.EXACT_OUTPUT,
|
|
814
|
+
originTokenSymbol: originTokenSymbol,
|
|
815
|
+
destinationTokenSymbol: destinationTokenSymbol,
|
|
816
|
+
destinationCalldata: toCalldata as string,
|
|
817
|
+
client: walletClient,
|
|
818
|
+
trailsClient,
|
|
819
|
+
sourceTokenDecimals,
|
|
820
|
+
destinationTokenDecimals,
|
|
821
|
+
onTransactionStateChange: onStatusUpdate ?? (() => {}),
|
|
822
|
+
slippageTolerance: slippageTolerance?.toString(),
|
|
823
|
+
swapProvider: effectiveSwapProvider,
|
|
824
|
+
bridgeProvider: effectiveBridgeProvider,
|
|
825
|
+
paymasterUrl: paymasterUrl,
|
|
826
|
+
selectedFeeOption: selectedFeeOption ?? null,
|
|
827
|
+
abortSignal: combinedAbortSignal,
|
|
828
|
+
originNativeTokenPriceUsd: originNativeTokenPriceUsd,
|
|
829
|
+
commitIntentFn: commitIntentMutation.mutateAsync,
|
|
830
|
+
executeIntentFn: executeIntentMutation.mutateAsync,
|
|
831
|
+
checkoutOnHandlers,
|
|
832
|
+
sequenceIndexerUrl,
|
|
833
|
+
sequenceProjectAccessKey,
|
|
834
|
+
originPublicClient: originPublicClient ?? undefined,
|
|
835
|
+
destinationPublicClient: destinationPublicClient ?? undefined,
|
|
836
|
+
isSmartWallet: isSmartWallet ?? undefined,
|
|
837
|
+
trailsApiKey,
|
|
838
|
+
trailsApiUrl,
|
|
839
|
+
fundMethod: fundMethod ?? undefined,
|
|
840
|
+
onramp: onramp ?? undefined,
|
|
841
|
+
}
|
|
830
842
|
|
|
831
|
-
|
|
843
|
+
logger.console.log("[trails-sdk] options", options)
|
|
832
844
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
845
|
+
const {
|
|
846
|
+
quote: prepareSendQuote,
|
|
847
|
+
send: prepareSendSend,
|
|
848
|
+
feeOptions: prepareSendFeeOptions,
|
|
849
|
+
} = await prepareSend(options)
|
|
838
850
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
prepareSendQuote.
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
prepareSendQuote.
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
prepareSendQuote.
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
851
|
+
const quote: Quote = {
|
|
852
|
+
// Backward compatible fields
|
|
853
|
+
fromAmount: prepareSendQuote.originAmount,
|
|
854
|
+
toAmount: prepareSendQuote.destinationAmount,
|
|
855
|
+
fromAmountMin: prepareSendQuote.originAmountMin,
|
|
856
|
+
toAmountMin: prepareSendQuote.destinationAmountMin,
|
|
857
|
+
fromAmountUsdDisplay: prepareSendQuote.originAmountUsdDisplay ?? "",
|
|
858
|
+
toAmountUsdDisplay:
|
|
859
|
+
prepareSendQuote.destinationAmountUsdDisplay ?? "",
|
|
860
|
+
toAmountMinUsdDisplay:
|
|
861
|
+
prepareSendQuote.destinationAmountMinUsdDisplay ?? "",
|
|
862
|
+
// PrepareSendQuote compatible fields
|
|
863
|
+
originAmount: prepareSendQuote.originAmount,
|
|
864
|
+
originAmountMin: prepareSendQuote.originAmountMin,
|
|
865
|
+
destinationAmount: prepareSendQuote.destinationAmount,
|
|
866
|
+
destinationAmountMin: prepareSendQuote.destinationAmountMin,
|
|
867
|
+
originAmountUsdDisplay:
|
|
868
|
+
prepareSendQuote.originAmountUsdDisplay ?? "",
|
|
869
|
+
destinationAmountUsdDisplay:
|
|
870
|
+
prepareSendQuote.destinationAmountUsdDisplay ?? "",
|
|
871
|
+
originAmountDisplay: prepareSendQuote.originAmountDisplay ?? "",
|
|
872
|
+
destinationAmountDisplay:
|
|
873
|
+
prepareSendQuote.destinationAmountDisplay ?? "",
|
|
874
|
+
originAmountMinDisplay:
|
|
875
|
+
prepareSendQuote.originAmountMinDisplay ?? "",
|
|
876
|
+
originAmountMinUsdFormatted:
|
|
877
|
+
prepareSendQuote.originAmountMinUsdFormatted ?? "",
|
|
878
|
+
originAmountMinUsdDisplay:
|
|
879
|
+
prepareSendQuote.originAmountMinUsdDisplay ?? "",
|
|
880
|
+
destinationAmountMinDisplay:
|
|
881
|
+
prepareSendQuote.destinationAmountMinDisplay ?? "",
|
|
882
|
+
destinationAmountMinUsdFormatted:
|
|
883
|
+
prepareSendQuote.destinationAmountMinUsdFormatted ?? "",
|
|
884
|
+
destinationAmountMinUsdDisplay:
|
|
885
|
+
prepareSendQuote.destinationAmountMinUsdDisplay ?? "",
|
|
886
|
+
originAmountUsdFormatted:
|
|
887
|
+
prepareSendQuote.originAmountUsdFormatted ?? "",
|
|
888
|
+
destinationAmountUsdFormatted:
|
|
889
|
+
prepareSendQuote.destinationAmountUsdFormatted ?? "",
|
|
890
|
+
// Common fields
|
|
891
|
+
originToken: prepareSendQuote.originToken,
|
|
892
|
+
destinationToken: prepareSendQuote.destinationToken,
|
|
893
|
+
originChain: prepareSendQuote.originChain,
|
|
894
|
+
destinationChain: prepareSendQuote.destinationChain,
|
|
895
|
+
fees: prepareSendQuote.fees,
|
|
896
|
+
priceImpact: prepareSendQuote.priceImpact,
|
|
897
|
+
priceImpactUsd: prepareSendQuote.priceImpactUsd ?? null,
|
|
898
|
+
priceImpactUsdDisplay: prepareSendQuote.priceImpactUsdDisplay ?? "",
|
|
899
|
+
completionEstimateSeconds:
|
|
900
|
+
prepareSendQuote.completionEstimateSeconds,
|
|
901
|
+
completionEstimateDisplay:
|
|
902
|
+
prepareSendQuote.completionEstimateDisplay ?? "",
|
|
903
|
+
slippageTolerance: prepareSendQuote.slippageTolerance,
|
|
904
|
+
transactionStates: prepareSendQuote.transactionStates ?? [],
|
|
905
|
+
originTokenRate: prepareSendQuote.originTokenRate ?? "",
|
|
906
|
+
destinationTokenRate: prepareSendQuote.destinationTokenRate ?? "",
|
|
907
|
+
originTokenPriceUsd: prepareSendQuote.originTokenPriceUsd ?? 0,
|
|
908
|
+
destinationTokenPriceUsd:
|
|
909
|
+
prepareSendQuote.destinationTokenPriceUsd ?? 0,
|
|
910
|
+
routeProviders: prepareSendQuote.routeProviders ?? [],
|
|
911
|
+
gasCostUsd: prepareSendQuote.gasCostUsd ?? null,
|
|
912
|
+
gasCostUsdDisplay: prepareSendQuote.gasCostUsdDisplay ?? "",
|
|
913
|
+
gasCost: prepareSendQuote.gasCost ?? "",
|
|
914
|
+
gasCostFormatted: prepareSendQuote.gasCostFormatted ?? "",
|
|
915
|
+
totalFeesUsd: prepareSendQuote.totalFeesUsd ?? null,
|
|
916
|
+
totalFeesUsdDisplay: prepareSendQuote.totalFeesUsdDisplay ?? "",
|
|
917
|
+
totalGasUsd: prepareSendQuote.totalGasUsd ?? null,
|
|
918
|
+
totalGasUsdDisplay: prepareSendQuote.totalGasUsdDisplay ?? "",
|
|
919
|
+
intentId: prepareSendQuote.intentId ?? null,
|
|
920
|
+
originAmountFormatted: prepareSendQuote.originAmountFormatted ?? "",
|
|
921
|
+
destinationAmountFormatted:
|
|
922
|
+
prepareSendQuote.destinationAmountFormatted ?? "",
|
|
923
|
+
originDepositAddress: prepareSendQuote.originDepositAddress ?? "",
|
|
924
|
+
destinationDepositAddress:
|
|
925
|
+
prepareSendQuote.destinationDepositAddress ?? "",
|
|
926
|
+
destinationAddress: prepareSendQuote.destinationAddress ?? "",
|
|
927
|
+
destinationCalldata: prepareSendQuote.destinationCalldata ?? "",
|
|
928
|
+
// Fee breakdown fields
|
|
929
|
+
trailsFeeBreakdown: prepareSendQuote.trailsFeeBreakdown ?? null,
|
|
930
|
+
originGasUsd: prepareSendQuote.originGasUsd ?? null,
|
|
931
|
+
originGasUsdDisplay: prepareSendQuote.originGasUsdDisplay ?? "",
|
|
932
|
+
destinationGasUsd: prepareSendQuote.destinationGasUsd ?? null,
|
|
933
|
+
destinationGasUsdDisplay:
|
|
934
|
+
prepareSendQuote.destinationGasUsdDisplay ?? "",
|
|
935
|
+
providerFeeUsd: prepareSendQuote.providerFeeUsd ?? null,
|
|
936
|
+
providerFeeUsdDisplay: prepareSendQuote.providerFeeUsdDisplay ?? "",
|
|
937
|
+
trailsFeeUsd: prepareSendQuote.trailsFeeUsd ?? null,
|
|
938
|
+
trailsFeeUsdDisplay: prepareSendQuote.trailsFeeUsdDisplay ?? "",
|
|
939
|
+
totalProviderFeesUsd: prepareSendQuote.totalProviderFeesUsd ?? null,
|
|
940
|
+
totalProviderFeesUsdDisplay:
|
|
941
|
+
prepareSendQuote.totalProviderFeesUsdDisplay ?? "",
|
|
942
|
+
noSufficientBalance: prepareSendQuote.noSufficientBalance ?? false,
|
|
943
|
+
expiresAt: prepareSendQuote.expiresAt ?? null,
|
|
944
|
+
}
|
|
927
945
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
946
|
+
const sendTransaction = async (
|
|
947
|
+
options?: SendOptions,
|
|
948
|
+
): Promise<SwapReturn> => {
|
|
949
|
+
// Use fee option from send() call if provided, otherwise fall back to prop value
|
|
950
|
+
const effectiveFeeOption =
|
|
951
|
+
options?.selectedFeeOption !== undefined
|
|
952
|
+
? options.selectedFeeOption
|
|
953
|
+
: (selectedFeeOption ?? null)
|
|
936
954
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
955
|
+
const {
|
|
956
|
+
depositUserTxnReceipt,
|
|
957
|
+
destinationIntentTransaction,
|
|
958
|
+
totalCompletionSeconds,
|
|
959
|
+
} = await prepareSendSend({
|
|
960
|
+
selectedFeeOption: effectiveFeeOption,
|
|
961
|
+
onOriginSend: options?.onOriginSend,
|
|
962
|
+
depositTransactionHash: options?.depositTransactionHash,
|
|
963
|
+
skipCommit: options?.skipCommit,
|
|
964
|
+
commitOnly: options?.commitOnly,
|
|
965
|
+
})
|
|
948
966
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
+
return {
|
|
968
|
+
originTransaction: {
|
|
969
|
+
transactionHash: depositUserTxnReceipt?.transactionHash,
|
|
970
|
+
explorerUrl: getExplorerUrl({
|
|
971
|
+
txHash: depositUserTxnReceipt?.transactionHash as string,
|
|
972
|
+
chainId: fromChainId,
|
|
973
|
+
}),
|
|
974
|
+
receipt: depositUserTxnReceipt,
|
|
975
|
+
},
|
|
976
|
+
destinationTransaction: {
|
|
977
|
+
transactionHash: destinationIntentTransaction?.txnHash,
|
|
978
|
+
explorerUrl: getExplorerUrl({
|
|
979
|
+
txHash: destinationIntentTransaction?.txnHash as string,
|
|
980
|
+
chainId: toChainId,
|
|
981
|
+
}),
|
|
982
|
+
receipt: destinationIntentTransaction,
|
|
983
|
+
},
|
|
984
|
+
totalCompletionSeconds,
|
|
985
|
+
}
|
|
967
986
|
}
|
|
968
|
-
}
|
|
969
987
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
988
|
+
// Clear the timeout on successful completion
|
|
989
|
+
clearTimeout(timeoutId)
|
|
990
|
+
|
|
991
|
+
return {
|
|
992
|
+
quote,
|
|
993
|
+
send: sendTransaction,
|
|
994
|
+
feeOptions: prepareSendFeeOptions?.feeOptions ?? [],
|
|
995
|
+
}
|
|
996
|
+
} finally {
|
|
997
|
+
// Always clear the timeout
|
|
998
|
+
clearTimeout(timeoutId)
|
|
974
999
|
}
|
|
975
1000
|
} catch (error) {
|
|
1001
|
+
// Check if this was aborted due to timeout
|
|
1002
|
+
if (
|
|
1003
|
+
(error as any)?.name === "AbortError" ||
|
|
1004
|
+
abortControllerRef.current.signal.aborted
|
|
1005
|
+
) {
|
|
1006
|
+
logger.console.error(
|
|
1007
|
+
"[trails-sdk] [useQuote] Quote request timed out:",
|
|
1008
|
+
error,
|
|
1009
|
+
)
|
|
1010
|
+
throw new Error("No route available")
|
|
1011
|
+
}
|
|
1012
|
+
|
|
976
1013
|
logger.console.error(
|
|
977
1014
|
"[trails-sdk] [useQuote] Error getting quote:",
|
|
978
1015
|
error,
|
|
@@ -999,7 +1036,7 @@ export function useQuote({
|
|
|
999
1036
|
refetchOnWindowFocus: false, // Don't refetch when window regains focus
|
|
1000
1037
|
refetchOnMount: "always", // Always refetch on component remount to ensure fresh quote
|
|
1001
1038
|
refetchInterval: false, // Disable automatic polling
|
|
1002
|
-
retry:
|
|
1039
|
+
retry: false, // Disable automatic retries - only make 1 request
|
|
1003
1040
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
1004
1041
|
})
|
|
1005
1042
|
|