0xtrails 0.8.2 → 0.8.3

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.
Files changed (68) hide show
  1. package/dist/aave.d.ts.map +1 -1
  2. package/dist/{ccip-ru_Yzdas.js → ccip-Bs-QcZXm.js} +13 -13
  3. package/dist/constants.d.ts +2 -0
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/fees.d.ts +11 -17
  6. package/dist/fees.d.ts.map +1 -1
  7. package/dist/{index-Si7cO9V7.js → index-C_EsqqSn.js} +20320 -20063
  8. package/dist/index.js +425 -847
  9. package/dist/intents.d.ts +1 -2
  10. package/dist/intents.d.ts.map +1 -1
  11. package/dist/prepareSend.d.ts.map +1 -1
  12. package/dist/recover.d.ts +8 -9
  13. package/dist/recover.d.ts.map +1 -1
  14. package/dist/tokenBalances.d.ts +51 -0
  15. package/dist/tokenBalances.d.ts.map +1 -1
  16. package/dist/trailsRouter.d.ts +15 -0
  17. package/dist/trailsRouter.d.ts.map +1 -1
  18. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +1 -3
  19. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  20. package/dist/transactionIntent/deposits/standardDeposit.d.ts +1 -3
  21. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  22. package/dist/transactionIntent/handlers/crossChain.d.ts +2 -4
  23. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
  24. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +5 -4
  25. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
  26. package/dist/transactionIntent/quote/normalizeQuote.d.ts +1 -1
  27. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  28. package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
  29. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
  30. package/dist/transactionIntent/types.d.ts +11 -18
  31. package/dist/transactionIntent/types.d.ts.map +1 -1
  32. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  33. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  34. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  35. package/dist/widget/components/SlippageToleranceSettings.d.ts +2 -1
  36. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  37. package/dist/widget/css/compiled.css +1 -1
  38. package/dist/widget/hooks/useQuote.d.ts +94 -35
  39. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  40. package/dist/widget/hooks/useSendForm.d.ts +2 -2
  41. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  42. package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -1
  43. package/dist/widget/index.js +1 -1
  44. package/package.json +2 -2
  45. package/src/aave.ts +4 -0
  46. package/src/constants.ts +4 -0
  47. package/src/fees.ts +47 -72
  48. package/src/intents.ts +1 -3
  49. package/src/morpho.ts +1 -1
  50. package/src/prepareSend.ts +42 -6
  51. package/src/recover.ts +116 -172
  52. package/src/tokenBalances.ts +301 -1
  53. package/src/trailsRouter.ts +77 -0
  54. package/src/transactionIntent/deposits/depositOrchestrator.ts +0 -6
  55. package/src/transactionIntent/deposits/standardDeposit.ts +167 -184
  56. package/src/transactionIntent/handlers/crossChain.ts +8 -11
  57. package/src/transactionIntent/handlers/sameChainSameToken.ts +619 -608
  58. package/src/transactionIntent/quote/normalizeQuote.ts +32 -46
  59. package/src/transactionIntent/quote/quoteHelpers.ts +4 -2
  60. package/src/transactionIntent/types.ts +11 -18
  61. package/src/widget/compiled.css +1 -1
  62. package/src/widget/components/AccountIntentTransactionHistory.tsx +50 -18
  63. package/src/widget/components/ClassicSwap.tsx +25 -30
  64. package/src/widget/components/QuoteDetails.tsx +18 -27
  65. package/src/widget/components/SlippageToleranceSettings.tsx +55 -25
  66. package/src/widget/hooks/useQuote.ts +317 -79
  67. package/src/widget/hooks/useSendForm.ts +123 -764
  68. package/src/widget/hooks/useTrailsSendTransaction.ts +0 -2
package/src/recover.ts CHANGED
@@ -17,13 +17,14 @@ import { splitSignature } from "./gasless.js"
17
17
  import { useMemo, useCallback } from "react"
18
18
  import { useGetIntent } from "./widget/hooks/useGetIntent.js"
19
19
  import {
20
- useTokenBalances,
20
+ useTokenBalancesForMultipleAccounts,
21
21
  getTokenBalanceUsd,
22
22
  type Price,
23
23
  } from "./tokenBalances.js"
24
24
  import { getERC20TransferData } from "./encoders.js"
25
25
  import { zeroAddress } from "viem"
26
26
  import { useTokenPrices } from "./prices.js"
27
+ import type { Token } from "./tokens.js"
27
28
  import type { Payload as WalletPayload } from "@0xsequence/wallet-primitives"
28
29
  import { attemptSwitchChain } from "./chainSwitch.js"
29
30
  import { decodeGuestModuleEvents } from "./decoders.js"
@@ -440,15 +441,17 @@ export async function buildRefundTransaction(
440
441
 
441
442
  /**
442
443
  * Determines the refund call based on token balances at the intent address
444
+ * Uses Token type which has symbol, name, decimals, chainId directly (no contractInfo)
443
445
  */
444
446
  export function determineRefundCall(
445
447
  tokenBalancesData:
446
448
  | {
447
- nativeBalances?: Array<{ balance?: string; chainId?: number }>
448
- balances?: Array<{
449
+ tokens?: Array<{
449
450
  balance?: string
450
451
  contractAddress?: string
451
- contractInfo?: { decimals?: number; chainId?: number }
452
+ decimals?: number
453
+ chainId?: number
454
+ isNativeToken?: boolean
452
455
  }>
453
456
  }
454
457
  | undefined,
@@ -467,34 +470,18 @@ export function determineRefundCall(
467
470
  chainId?: number
468
471
  } | null = null
469
472
 
470
- // Check native token balances
471
- if (tokenBalancesData?.nativeBalances) {
472
- for (const nativeBalance of tokenBalancesData.nativeBalances) {
473
- const balance = BigInt(nativeBalance.balance || "0")
473
+ // Check all tokens (both native and ERC20)
474
+ if (tokenBalancesData?.tokens) {
475
+ for (const token of tokenBalancesData.tokens) {
476
+ const balance = BigInt(token.balance || "0")
474
477
  if (balance > 0n) {
475
478
  if (!highestBalanceToken || balance > highestBalanceToken.balance) {
476
479
  highestBalanceToken = {
477
- type: "native",
480
+ type: token.isNativeToken ? "native" : "erc20",
478
481
  balance,
479
- chainId: nativeBalance.chainId,
480
- }
481
- }
482
- }
483
- }
484
- }
485
-
486
- // Check ERC20 token balances
487
- if (tokenBalancesData?.balances) {
488
- for (const tokenBalance of tokenBalancesData.balances) {
489
- const balance = BigInt(tokenBalance.balance || "0")
490
- if (balance > 0n) {
491
- if (!highestBalanceToken || balance > highestBalanceToken.balance) {
492
- highestBalanceToken = {
493
- type: "erc20",
494
- balance,
495
- tokenAddress: tokenBalance.contractAddress,
496
- decimals: tokenBalance.contractInfo?.decimals,
497
- chainId: tokenBalance.contractInfo?.chainId,
482
+ tokenAddress: token.contractAddress,
483
+ decimals: token.decimals,
484
+ chainId: token.chainId,
498
485
  }
499
486
  }
500
487
  }
@@ -581,6 +568,8 @@ export interface UseIntentRecoverReturn {
581
568
  intentError: Error | null
582
569
  balancesError: Error | null
583
570
  hasIntentBalance: boolean
571
+ /** Token that will be recovered (the one with highest balance) */
572
+ recoverToken: Token | null
584
573
  refetchIntent: () => void
585
574
  signPayload: () => Promise<{
586
575
  signature: string
@@ -655,49 +644,41 @@ export function useIntentRecover({
655
644
  return Address.from(intentData.destinationIntentAddress)
656
645
  }, [intentData?.destinationIntentAddress])
657
646
 
647
+ // Fetch balances for both origin and destination in a single API call
658
648
  const {
659
- tokenBalancesData: originTokenBalancesData,
660
- isLoadingBalances: isLoadingOriginBalances,
661
- balanceError: originBalanceError,
662
- } = useTokenBalances(originIntentAddressForBalances)
649
+ balancesByAccount,
650
+ isLoading: isLoadingBalances,
651
+ error: balanceError,
652
+ } = useTokenBalancesForMultipleAccounts([
653
+ originIntentAddressForBalances,
654
+ destinationIntentAddressForBalances,
655
+ ])
663
656
 
664
- const {
665
- tokenBalancesData: destinationTokenBalancesData,
666
- isLoadingBalances: isLoadingDestinationBalances,
667
- balanceError: destinationBalanceError,
668
- } = useTokenBalances(destinationIntentAddressForBalances)
657
+ // Extract individual account balances
658
+ const originTokenBalancesData = originIntentAddressForBalances
659
+ ? balancesByAccount[originIntentAddressForBalances.toLowerCase()]
660
+ ?.tokenBalancesData
661
+ : undefined
662
+ const destinationTokenBalancesData = destinationIntentAddressForBalances
663
+ ? balancesByAccount[destinationIntentAddressForBalances.toLowerCase()]
664
+ ?.tokenBalancesData
665
+ : undefined
666
+
667
+ // balancesError alias for backward compatibility in component return
668
+ const balancesError = balanceError
669
669
 
670
670
  // Get token prices for origin balances
671
+ // Note: Token type already has balance/price fields populated, but we fetch prices
672
+ // separately for more accurate/up-to-date pricing
671
673
  const originTokensForPricing = useMemo(() => {
672
- if (!originTokenBalancesData) return []
673
- const tokens: Array<{
674
- tokenSymbol: string
675
- tokenAddress: string
676
- chainId: number
677
- }> = []
678
- if (originTokenBalancesData.nativeBalances) {
679
- for (const nativeBalance of originTokenBalancesData.nativeBalances) {
680
- if (nativeBalance.chainId) {
681
- tokens.push({
682
- tokenSymbol: (nativeBalance as any).symbol || "ETH",
683
- tokenAddress: zeroAddress,
684
- chainId: nativeBalance.chainId,
685
- })
686
- }
687
- }
688
- }
689
- if (originTokenBalancesData.balances) {
690
- for (const tokenBalance of originTokenBalancesData.balances) {
691
- if (tokenBalance.contractInfo?.chainId) {
692
- tokens.push({
693
- tokenSymbol: tokenBalance.contractInfo?.symbol || "",
694
- tokenAddress: tokenBalance.contractAddress || zeroAddress,
695
- chainId: tokenBalance.contractInfo.chainId,
696
- })
697
- }
698
- }
699
- }
700
- return tokens
674
+ if (!originTokenBalancesData?.tokens) return []
675
+ return originTokenBalancesData.tokens
676
+ .filter((token) => token.chainId !== undefined)
677
+ .map((token) => ({
678
+ tokenSymbol: token.symbol,
679
+ tokenAddress: token.contractAddress || zeroAddress,
680
+ chainId: token.chainId!,
681
+ }))
701
682
  }, [originTokenBalancesData])
702
683
 
703
684
  const { tokenPrices: originTokenPrices } = useTokenPrices(
@@ -706,35 +687,14 @@ export function useIntentRecover({
706
687
 
707
688
  // Get token prices for destination balances
708
689
  const destinationTokensForPricing = useMemo(() => {
709
- if (!destinationTokenBalancesData) return []
710
- const tokens: Array<{
711
- tokenSymbol: string
712
- tokenAddress: string
713
- chainId: number
714
- }> = []
715
- if (destinationTokenBalancesData.nativeBalances) {
716
- for (const nativeBalance of destinationTokenBalancesData.nativeBalances) {
717
- if (nativeBalance.chainId) {
718
- tokens.push({
719
- tokenSymbol: (nativeBalance as any).symbol || "ETH",
720
- tokenAddress: zeroAddress,
721
- chainId: nativeBalance.chainId,
722
- })
723
- }
724
- }
725
- }
726
- if (destinationTokenBalancesData.balances) {
727
- for (const tokenBalance of destinationTokenBalancesData.balances) {
728
- if (tokenBalance.contractInfo?.chainId) {
729
- tokens.push({
730
- tokenSymbol: tokenBalance.contractInfo?.symbol || "",
731
- tokenAddress: tokenBalance.contractAddress || zeroAddress,
732
- chainId: tokenBalance.contractInfo.chainId,
733
- })
734
- }
735
- }
736
- }
737
- return tokens
690
+ if (!destinationTokenBalancesData?.tokens) return []
691
+ return destinationTokenBalancesData.tokens
692
+ .filter((token) => token.chainId !== undefined)
693
+ .map((token) => ({
694
+ tokenSymbol: token.symbol,
695
+ tokenAddress: token.contractAddress || zeroAddress,
696
+ chainId: token.chainId!,
697
+ }))
738
698
  }, [destinationTokenBalancesData])
739
699
 
740
700
  const { tokenPrices: destinationTokenPrices } = useTokenPrices(
@@ -746,19 +706,13 @@ export function useIntentRecover({
746
706
  (
747
707
  balancesData:
748
708
  | {
749
- nativeBalances?: Array<{
709
+ tokens?: Array<{
750
710
  balance?: string
751
711
  chainId?: number
752
- symbol?: string
753
- }>
754
- balances?: Array<{
755
- balance?: string
756
712
  contractAddress?: string
757
- contractInfo?: {
758
- decimals?: number
759
- chainId?: number
760
- symbol?: string
761
- }
713
+ decimals?: number
714
+ isNativeToken?: boolean
715
+ balanceUsd?: number
762
716
  }>
763
717
  }
764
718
  | undefined,
@@ -773,56 +727,44 @@ export function useIntentRecover({
773
727
 
774
728
  let totalUsd = 0
775
729
 
776
- // Sum native token USD values
777
- if (balancesData.nativeBalances) {
778
- for (const nativeBalance of balancesData.nativeBalances) {
779
- const priceData = tokenPrices.find(
780
- (p) =>
781
- p.token.tokenAddress === zeroAddress &&
782
- p.token.chainId === nativeBalance.chainId &&
783
- p.priceUsd !== undefined,
784
- )
785
- if (priceData?.priceUsd && nativeBalance.balance) {
786
- const price: Price = {
787
- value: priceData.priceUsd,
788
- currency: "USD",
789
- }
790
- const usdValue = getTokenBalanceUsd(
791
- {
792
- balance: nativeBalance.balance,
793
- chainId: nativeBalance.chainId,
794
- } as any,
795
- price,
796
- )
797
- totalUsd += usdValue
798
- }
799
- }
800
- }
730
+ // Sum all token USD values (both native and ERC20)
731
+ if (balancesData.tokens) {
732
+ for (const token of balancesData.tokens) {
733
+ const tokenAddress = token.isNativeToken
734
+ ? zeroAddress
735
+ : token.contractAddress || zeroAddress
801
736
 
802
- // Sum ERC20 token USD values
803
- if (balancesData.balances) {
804
- for (const tokenBalance of balancesData.balances) {
805
737
  const priceData = tokenPrices.find(
806
738
  (p) =>
807
739
  p.token.tokenAddress?.toLowerCase() ===
808
- (tokenBalance.contractAddress || zeroAddress).toLowerCase() &&
809
- p.token.chainId === tokenBalance.contractInfo?.chainId &&
740
+ tokenAddress.toLowerCase() &&
741
+ p.token.chainId === token.chainId &&
810
742
  p.priceUsd !== undefined,
811
743
  )
812
- if (priceData?.priceUsd && tokenBalance.balance) {
744
+
745
+ if (priceData?.priceUsd && token.balance) {
813
746
  const price: Price = {
814
747
  value: priceData.priceUsd,
815
748
  currency: "USD",
816
749
  }
817
- const usdValue = getTokenBalanceUsd(
818
- {
819
- balance: tokenBalance.balance,
820
- contractAddress: tokenBalance.contractAddress,
821
- contractInfo: tokenBalance.contractInfo,
822
- } as any,
823
- price,
824
- )
825
- totalUsd += usdValue
750
+
751
+ // Use balanceUsd if already calculated, otherwise calculate
752
+ if (token.balanceUsd !== undefined) {
753
+ totalUsd += token.balanceUsd
754
+ } else {
755
+ // Create a compatible object for getTokenBalanceUsd
756
+ const balanceObj = token.isNativeToken
757
+ ? { balance: token.balance, chainId: token.chainId }
758
+ : {
759
+ balance: token.balance,
760
+ contractInfo: {
761
+ decimals: token.decimals,
762
+ chainId: token.chainId,
763
+ },
764
+ }
765
+ const usdValue = getTokenBalanceUsd(balanceObj as any, price)
766
+ totalUsd += usdValue
767
+ }
826
768
  }
827
769
  }
828
770
  }
@@ -919,9 +861,7 @@ export function useIntentRecover({
919
861
  calculateTotalUsdBalance,
920
862
  ])
921
863
 
922
- const isLoadingBalances =
923
- isLoadingOriginBalances || isLoadingDestinationBalances
924
- const balancesError = originBalanceError || destinationBalanceError
864
+ // isLoadingBalances and balancesError are already defined above from useTokenBalancesForMultipleAccounts
925
865
 
926
866
  // Check if ANY intent address (origin or destination) has any balance (native or ERC20)
927
867
  // This ensures we show the recover button if there are balances in either address
@@ -930,34 +870,17 @@ export function useIntentRecover({
930
870
  const checkBalances = (
931
871
  balancesData:
932
872
  | {
933
- nativeBalances?: Array<{ balance?: string; chainId?: number }>
934
- balances?: Array<{
935
- balance?: string
936
- contractAddress?: string
937
- contractInfo?: { decimals?: number; chainId?: number }
938
- }>
873
+ tokens?: Array<{ balance?: string }>
939
874
  }
940
875
  | undefined,
941
876
  ): boolean => {
942
- if (!balancesData) return false
943
-
944
- // Check native token balances
945
- if (balancesData.nativeBalances) {
946
- for (const nativeBalance of balancesData.nativeBalances) {
947
- const balance = BigInt(nativeBalance.balance || "0")
948
- if (balance > 0n) {
949
- return true
950
- }
951
- }
952
- }
877
+ if (!balancesData?.tokens) return false
953
878
 
954
- // Check ERC20 token balances
955
- if (balancesData.balances) {
956
- for (const tokenBalance of balancesData.balances) {
957
- const balance = BigInt(tokenBalance.balance || "0")
958
- if (balance > 0n) {
959
- return true
960
- }
879
+ // Check all tokens (both native and ERC20)
880
+ for (const token of balancesData.tokens) {
881
+ const balance = BigInt(token.balance || "0")
882
+ if (balance > 0n) {
883
+ return true
961
884
  }
962
885
  }
963
886
 
@@ -971,6 +894,26 @@ export function useIntentRecover({
971
894
  return originHasBalance || destinationHasBalance
972
895
  }, [originTokenBalancesData, destinationTokenBalancesData])
973
896
 
897
+ // Get the token that will be recovered (highest balance from selected intent address)
898
+ // Get the token that will be recovered (highest balance from selected intent address)
899
+ const recoverToken = useMemo<Token | null>(() => {
900
+ if (!selectedIntentAddress?.tokenBalancesData?.tokens) return null
901
+
902
+ // Find the token with the highest balance
903
+ let highestBalanceToken: Token | null = null
904
+ let highestBalance = 0n
905
+
906
+ for (const token of selectedIntentAddress.tokenBalancesData.tokens) {
907
+ const balance = BigInt(token.balance || "0")
908
+ if (balance > 0n && balance > highestBalance) {
909
+ highestBalance = balance
910
+ highestBalanceToken = token
911
+ }
912
+ }
913
+
914
+ return highestBalanceToken
915
+ }, [selectedIntentAddress?.tokenBalancesData?.tokens])
916
+
974
917
  // Get refund address (use walletClient account or provided address)
975
918
  // Don't throw during render - validate when methods are called
976
919
  const effectiveRefundAddress = useMemo<`0x${string}` | null>(() => {
@@ -1411,6 +1354,7 @@ export function useIntentRecover({
1411
1354
  intentError: intentError as Error | null,
1412
1355
  balancesError: balancesError as Error | null,
1413
1356
  hasIntentBalance,
1357
+ recoverToken,
1414
1358
  refetchIntent,
1415
1359
  signPayload,
1416
1360
  getRecoverTx,