0xtrails 0.9.3 → 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-CDO_EkNr.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-CybzMCeP.js → index-D5AG6huo.js} +22141 -21641
- 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/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.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/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 +387 -355
- package/src/widget/providers/TrailsProvider.tsx +5 -0
- package/src/widget/widget.tsx +2 -0
|
@@ -587,397 +587,429 @@ export function useQuote({
|
|
|
587
587
|
return null
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
-
//
|
|
591
|
-
|
|
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
|
+
|
|
592
598
|
try {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
balanceErrorMessage
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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")
|
|
608
617
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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
|
+
}
|
|
621
631
|
}
|
|
622
|
-
}
|
|
623
632
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
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
|
+
)
|
|
633
640
|
|
|
634
|
-
|
|
635
|
-
// if (originTokenBalanceAmount === "0") {
|
|
636
|
-
// return null
|
|
637
|
-
// }
|
|
641
|
+
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
638
642
|
|
|
639
|
-
|
|
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
|
+
// }
|
|
640
647
|
|
|
641
|
-
|
|
642
|
-
let originNativeTokenPriceUsd = 0
|
|
643
|
-
try {
|
|
644
|
-
const originChain = getChainInfo(fromChainId)
|
|
645
|
-
const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
|
|
646
|
-
if (nativeTokenSymbol) {
|
|
647
|
-
const nativePrice = await getTokenPrice(trailsClient, {
|
|
648
|
-
tokenSymbol: nativeTokenSymbol,
|
|
649
|
-
tokenAddress: zeroAddress,
|
|
650
|
-
chainId: fromChainId,
|
|
651
|
-
})
|
|
652
|
-
originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
|
|
653
|
-
logger.console.log(
|
|
654
|
-
"[trails-sdk] [useQuote] Origin native token price:",
|
|
655
|
-
{
|
|
656
|
-
chainId: fromChainId,
|
|
657
|
-
symbol: nativeTokenSymbol,
|
|
658
|
-
priceUsd: originNativeTokenPriceUsd,
|
|
659
|
-
},
|
|
660
|
-
)
|
|
661
|
-
}
|
|
662
|
-
} catch (error) {
|
|
663
|
-
logger.console.error(
|
|
664
|
-
"[trails-sdk] [useQuote] Error getting origin native token price:",
|
|
665
|
-
error,
|
|
666
|
-
)
|
|
667
|
-
}
|
|
648
|
+
// logger.console.log("supportedTokens", supportedTokens)
|
|
668
649
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
tokenAddress: string,
|
|
672
|
-
chainId: number,
|
|
673
|
-
): Promise<number | null> => {
|
|
650
|
+
// Get native token price for origin chain (for gas cost calculation)
|
|
651
|
+
let originNativeTokenPriceUsd = 0
|
|
674
652
|
try {
|
|
675
|
-
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
:
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
logger.console.
|
|
685
|
-
|
|
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
|
+
},
|
|
686
669
|
)
|
|
687
|
-
return null
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// For native tokens, return 18 decimals
|
|
691
|
-
if (tokenAddress.toLowerCase() === zeroAddress.toLowerCase()) {
|
|
692
|
-
const chainInfo = getChainInfo(chainId)
|
|
693
|
-
return chainInfo?.nativeCurrency.decimals ?? 18
|
|
694
670
|
}
|
|
695
|
-
|
|
696
|
-
const decimals = await publicClient.readContract({
|
|
697
|
-
address: tokenAddress as `0x${string}`,
|
|
698
|
-
abi: erc20Abi,
|
|
699
|
-
functionName: "decimals",
|
|
700
|
-
})
|
|
701
|
-
|
|
702
|
-
logger.console.log(
|
|
703
|
-
`[trails-sdk] Fetched decimals on-chain for token ${tokenAddress} on chain ${chainId}: ${decimals}`,
|
|
704
|
-
)
|
|
705
|
-
return decimals
|
|
706
671
|
} catch (error) {
|
|
707
672
|
logger.console.error(
|
|
708
|
-
|
|
673
|
+
"[trails-sdk] [useQuote] Error getting origin native token price:",
|
|
709
674
|
error,
|
|
710
675
|
)
|
|
711
|
-
return null
|
|
712
676
|
}
|
|
713
|
-
}
|
|
714
677
|
|
|
715
|
-
|
|
716
|
-
(
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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
|
|
725
691
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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,
|
|
735
729
|
)
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
730
|
+
const destinationToken = supportedTokens?.find(
|
|
731
|
+
(token) =>
|
|
732
|
+
token.contractAddress?.toLowerCase() ===
|
|
733
|
+
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
739
734
|
)
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
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(
|
|
749
747
|
fromTokenAddress,
|
|
750
748
|
fromChainId,
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
let destinationTokenDecimals = destinationToken?.decimals
|
|
756
|
-
if (!destinationTokenDecimals && toTokenAddress && toChainId) {
|
|
757
|
-
logger.console.warn(
|
|
758
|
-
"[trails-sdk] Destination token decimals not found in token list, fetching on-chain:",
|
|
759
|
-
{
|
|
760
|
-
destinationToken,
|
|
761
|
-
toTokenAddress,
|
|
762
|
-
toChainId,
|
|
763
|
-
},
|
|
764
|
-
)
|
|
765
|
-
const onChainDecimals = await fetchDecimalsOnChain(
|
|
766
|
-
toTokenAddress,
|
|
767
|
-
toChainId,
|
|
768
|
-
)
|
|
769
|
-
if (onChainDecimals !== null) {
|
|
770
|
-
destinationTokenDecimals = onChainDecimals
|
|
749
|
+
)
|
|
750
|
+
if (onChainDecimals !== null) {
|
|
751
|
+
sourceTokenDecimals = onChainDecimals
|
|
752
|
+
}
|
|
771
753
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
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(
|
|
778
776
|
toTokenAddress,
|
|
779
777
|
toChainId,
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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 ?? ""
|
|
786
796
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
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
|
|
793
803
|
|
|
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
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
+
}
|
|
832
842
|
|
|
833
|
-
|
|
843
|
+
logger.console.log("[trails-sdk] options", options)
|
|
834
844
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
845
|
+
const {
|
|
846
|
+
quote: prepareSendQuote,
|
|
847
|
+
send: prepareSendSend,
|
|
848
|
+
feeOptions: prepareSendFeeOptions,
|
|
849
|
+
} = await prepareSend(options)
|
|
840
850
|
|
|
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
|
-
prepareSendQuote.
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
prepareSendQuote.
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
prepareSendQuote.
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
prepareSendQuote.
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
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
|
+
}
|
|
932
945
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
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)
|
|
941
954
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
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
|
+
})
|
|
953
966
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
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
|
+
}
|
|
972
986
|
}
|
|
973
|
-
}
|
|
974
987
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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)
|
|
979
999
|
}
|
|
980
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
|
+
|
|
981
1013
|
logger.console.error(
|
|
982
1014
|
"[trails-sdk] [useQuote] Error getting quote:",
|
|
983
1015
|
error,
|
|
@@ -1004,7 +1036,7 @@ export function useQuote({
|
|
|
1004
1036
|
refetchOnWindowFocus: false, // Don't refetch when window regains focus
|
|
1005
1037
|
refetchOnMount: "always", // Always refetch on component remount to ensure fresh quote
|
|
1006
1038
|
refetchInterval: false, // Disable automatic polling
|
|
1007
|
-
retry:
|
|
1039
|
+
retry: false, // Disable automatic retries - only make 1 request
|
|
1008
1040
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
1009
1041
|
})
|
|
1010
1042
|
|