0xtrails 0.2.4 → 0.2.6

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 (212) hide show
  1. package/dist/aave.d.ts +8 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/abortController.d.ts +8 -0
  4. package/dist/abortController.d.ts.map +1 -0
  5. package/dist/{ccip-BlV1Mry3.js → ccip-Xjh9d1gb.js} +7 -7
  6. package/dist/config.d.ts +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/constants.d.ts +3 -0
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/error.d.ts +1 -0
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/estimate.d.ts +52 -0
  13. package/dist/estimate.d.ts.map +1 -1
  14. package/dist/fees.d.ts +19 -0
  15. package/dist/fees.d.ts.map +1 -0
  16. package/dist/{index-BNWCIGfQ.js → index-BnhdZ8Ho.js} +76406 -75798
  17. package/dist/index.js +726 -520
  18. package/dist/intents.d.ts +40 -0
  19. package/dist/intents.d.ts.map +1 -1
  20. package/dist/metaTxnMonitor.d.ts +3 -3
  21. package/dist/metaTxnMonitor.d.ts.map +1 -1
  22. package/dist/metaTxns.d.ts +3 -3
  23. package/dist/metaTxns.d.ts.map +1 -1
  24. package/dist/morpho.d.ts +8 -0
  25. package/dist/morpho.d.ts.map +1 -1
  26. package/dist/prepareSend.d.ts +19 -75
  27. package/dist/prepareSend.d.ts.map +1 -1
  28. package/dist/queryParams.d.ts.map +1 -1
  29. package/dist/relayer.d.ts +6 -6
  30. package/dist/relayer.d.ts.map +1 -1
  31. package/dist/sequenceWallet.d.ts +2 -2
  32. package/dist/sequenceWallet.d.ts.map +1 -1
  33. package/dist/tokens.d.ts.map +1 -1
  34. package/dist/transactions.d.ts +4 -2
  35. package/dist/transactions.d.ts.map +1 -1
  36. package/dist/wallets.d.ts.map +1 -1
  37. package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
  38. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
  39. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
  40. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  41. package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
  42. package/dist/widget/components/ClassicSwap.d.ts +4 -2
  43. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  44. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  45. package/dist/widget/components/ConnectedWallets.d.ts +4 -0
  46. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  47. package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
  48. package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
  49. package/dist/widget/components/Earn.d.ts +2 -2
  50. package/dist/widget/components/Earn.d.ts.map +1 -1
  51. package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
  52. package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
  53. package/dist/widget/components/FeeBreakdown.d.ts +9 -0
  54. package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
  55. package/dist/widget/components/Fund.d.ts +2 -2
  56. package/dist/widget/components/Fund.d.ts.map +1 -1
  57. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  58. package/dist/widget/components/{FundSendForm.d.ts → FundSwap.d.ts} +13 -7
  59. package/dist/widget/components/FundSwap.d.ts.map +1 -0
  60. package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
  61. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
  62. package/dist/widget/components/Identicon.d.ts.map +1 -1
  63. package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
  64. package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
  65. package/dist/widget/components/Modal.d.ts.map +1 -1
  66. package/dist/widget/components/Pay.d.ts +2 -2
  67. package/dist/widget/components/Pay.d.ts.map +1 -1
  68. package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
  69. package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
  70. package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +14 -36
  71. package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
  72. package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +19 -10
  73. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
  74. package/dist/widget/components/QuoteDetails.d.ts +1 -0
  75. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  76. package/dist/widget/components/Receipt.d.ts.map +1 -1
  77. package/dist/widget/components/Receive.d.ts.map +1 -1
  78. package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
  79. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
  80. package/dist/widget/components/Recipients.d.ts.map +1 -1
  81. package/dist/widget/components/RequiredPropsError.d.ts +8 -0
  82. package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
  83. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  84. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  85. package/dist/widget/components/Swap.d.ts +3 -2
  86. package/dist/widget/components/Swap.d.ts.map +1 -1
  87. package/dist/widget/components/SwapSettings.d.ts.map +1 -1
  88. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  89. package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
  90. package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
  91. package/dist/widget/components/TokenImage.d.ts +1 -0
  92. package/dist/widget/components/TokenImage.d.ts.map +1 -1
  93. package/dist/widget/components/TokenList.d.ts.map +1 -1
  94. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  95. package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
  96. package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
  97. package/dist/widget/components/Tooltip.d.ts +9 -0
  98. package/dist/widget/components/Tooltip.d.ts.map +1 -0
  99. package/dist/widget/components/UserPreferences.d.ts.map +1 -1
  100. package/dist/widget/components/WaasFeeOptions.d.ts +9 -0
  101. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
  102. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  103. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  104. package/dist/widget/components/WalletList.d.ts.map +1 -1
  105. package/dist/widget/css/compiled.css +2 -0
  106. package/dist/widget/css/index.css +554 -0
  107. package/dist/widget/hooks/useBack.d.ts +1 -0
  108. package/dist/widget/hooks/useBack.d.ts.map +1 -1
  109. package/dist/widget/hooks/useCheckout.d.ts +1 -1
  110. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  111. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  112. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  113. package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -3
  114. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  115. package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
  116. package/dist/widget/hooks/useQuote.d.ts +83 -0
  117. package/dist/widget/hooks/useQuote.d.ts.map +1 -0
  118. package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
  119. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
  120. package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
  121. package/dist/widget/hooks/useSendForm.d.ts +2 -2
  122. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  123. package/dist/widget/index.js +2 -2
  124. package/dist/widget/widget.d.ts +9 -4
  125. package/dist/widget/widget.d.ts.map +1 -1
  126. package/package.json +18 -12
  127. package/src/aave.ts +32 -0
  128. package/src/abortController.ts +35 -0
  129. package/src/config.ts +12 -4
  130. package/src/constants.ts +5 -0
  131. package/src/error.ts +19 -1
  132. package/src/estimate.ts +416 -5
  133. package/src/fees.ts +199 -0
  134. package/src/intents.ts +161 -11
  135. package/src/metaTxnMonitor.ts +3 -3
  136. package/src/metaTxns.ts +3 -5
  137. package/src/morpho.ts +32 -0
  138. package/src/prepareSend.ts +714 -550
  139. package/src/queryParams.ts +2 -1
  140. package/src/relayer.ts +11 -11
  141. package/src/sequenceWallet.ts +2 -2
  142. package/src/tokens.ts +7 -1
  143. package/src/trails.ts +3 -3
  144. package/src/transactions.ts +62 -18
  145. package/src/wallets.ts +8 -0
  146. package/src/widget/compiled.css +2 -2
  147. package/src/widget/components/AccountActionsDropdown.tsx +3 -13
  148. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
  149. package/src/widget/components/AccountSettings.tsx +48 -54
  150. package/src/widget/components/ChainFilterDropdown.tsx +24 -3
  151. package/src/widget/components/ClassicSwap.tsx +131 -213
  152. package/src/widget/components/ConnectWallet.tsx +8 -38
  153. package/src/widget/components/ConnectedWallets.tsx +132 -77
  154. package/src/widget/components/DynamicInputStyles.tsx +76 -0
  155. package/src/widget/components/Earn.tsx +82 -593
  156. package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
  157. package/src/widget/components/FeeBreakdown.tsx +155 -0
  158. package/src/widget/components/Fund.tsx +41 -108
  159. package/src/widget/components/FundMethods.tsx +82 -159
  160. package/src/widget/components/FundSwap.tsx +52 -0
  161. package/src/widget/components/FundingMethodSelectorButton.tsx +70 -0
  162. package/src/widget/components/Identicon.tsx +164 -95
  163. package/src/widget/components/MeshConnectExchanges.tsx +2 -15
  164. package/src/widget/components/Modal.tsx +0 -8
  165. package/src/widget/components/Pay.tsx +214 -237
  166. package/src/widget/components/PercentageMaxButtons.tsx +77 -0
  167. package/src/widget/components/PoolDeposit.tsx +569 -0
  168. package/src/widget/components/PoolWithdraw.tsx +884 -0
  169. package/src/widget/components/PriceImpactWarning.tsx +1 -1
  170. package/src/widget/components/QuoteDetails.tsx +43 -12
  171. package/src/widget/components/Receipt.tsx +16 -2
  172. package/src/widget/components/Receive.tsx +0 -2
  173. package/src/widget/components/RecipientSelectorButton.tsx +44 -0
  174. package/src/widget/components/Recipients.tsx +63 -157
  175. package/src/widget/components/RequiredPropsError.tsx +33 -0
  176. package/src/widget/components/ScreenHeader.tsx +62 -34
  177. package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
  178. package/src/widget/components/Swap.tsx +4 -45
  179. package/src/widget/components/SwapSettings.tsx +2 -14
  180. package/src/widget/components/ThemeProvider.tsx +2 -1
  181. package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
  182. package/src/widget/components/TokenImage.tsx +22 -5
  183. package/src/widget/components/TokenList.tsx +0 -1
  184. package/src/widget/components/TokenSelector.tsx +63 -53
  185. package/src/widget/components/TokenSelectorButton.tsx +98 -0
  186. package/src/widget/components/Tooltip.tsx +51 -0
  187. package/src/widget/components/TransferPendingVertical.tsx +1 -1
  188. package/src/widget/components/UserPreferences.tsx +6 -24
  189. package/src/widget/components/WaasFeeOptions.tsx +450 -0
  190. package/src/widget/components/WalletConfirmation.tsx +76 -14
  191. package/src/widget/components/WalletConnect.tsx +93 -29
  192. package/src/widget/components/WalletList.tsx +4 -2
  193. package/src/widget/hooks/useBack.tsx +2 -0
  194. package/src/widget/hooks/useCheckout.ts +36 -20
  195. package/src/widget/hooks/useCurrentScreen.tsx +1 -0
  196. package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
  197. package/src/widget/hooks/usePayMessage.tsx +86 -11
  198. package/src/widget/hooks/useQuote.ts +413 -0
  199. package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
  200. package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
  201. package/src/widget/hooks/useSendForm.ts +32 -6
  202. package/src/widget/index.css +27 -0
  203. package/src/widget/widget.tsx +326 -283
  204. package/dist/widget/components/FundSendForm.d.ts.map +0 -1
  205. package/dist/widget/components/PaySendForm.d.ts.map +0 -1
  206. package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
  207. package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
  208. package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
  209. package/src/widget/components/FundSendForm.tsx +0 -903
  210. package/src/widget/components/PaySendForm.tsx +0 -869
  211. package/src/widget/components/SimpleSwap.tsx +0 -983
  212. package/src/widget/hooks/useSwapSettings.tsx +0 -100
@@ -0,0 +1,130 @@
1
+ import { type CSSProperties, useEffect, useState } from "react"
2
+
3
+ export function ErrorAnimationIcon() {
4
+ const [animate, setAnimate] = useState(false)
5
+
6
+ useEffect(() => {
7
+ const timer = setTimeout(() => {
8
+ setAnimate(true)
9
+ }, 100)
10
+
11
+ return () => clearTimeout(timer)
12
+ }, [])
13
+
14
+ const styles: Record<string, CSSProperties> = {
15
+ container: {
16
+ width: "80px",
17
+ height: "80px",
18
+ position: "relative" as const,
19
+ },
20
+ circleContainer: {
21
+ position: "relative" as const,
22
+ width: "100%",
23
+ height: "100%",
24
+ },
25
+ circleFill: {
26
+ position: "absolute" as const,
27
+ top: 0,
28
+ left: 0,
29
+ width: "100%",
30
+ height: "100%",
31
+ borderRadius: "50%",
32
+ backgroundColor: "#ef4444",
33
+ transform: animate ? "scale(1)" : "scale(0)",
34
+ opacity: animate ? 1 : 0,
35
+ transition: "transform 0.15s ease-out 0.3s, opacity 0.15s ease-out 0.3s",
36
+ },
37
+ progressRing: {
38
+ position: "absolute" as const,
39
+ top: 0,
40
+ left: 0,
41
+ width: "100%",
42
+ height: "100%",
43
+ transform: "rotate(-90deg)",
44
+ },
45
+ circle: {
46
+ fill: "none",
47
+ stroke: "url(#redGradient)",
48
+ strokeWidth: 4,
49
+ strokeLinecap: "round" as const,
50
+ strokeDasharray: 226,
51
+ strokeDashoffset: animate ? 0 : 226,
52
+ transition: "stroke-dashoffset 0.3s ease-out",
53
+ },
54
+ xContainer: {
55
+ position: "absolute" as const,
56
+ top: "50%",
57
+ left: "50%",
58
+ transform: animate
59
+ ? "translate(-50%, -50%) scale(1)"
60
+ : "translate(-50%, -50%) scale(0)",
61
+ opacity: animate ? 1 : 0,
62
+ zIndex: 10,
63
+ transition: "transform 0.1s ease-out 0.4s, opacity 0.1s ease-out 0.4s",
64
+ },
65
+ xPath: {
66
+ fill: "none",
67
+ stroke: "white",
68
+ strokeWidth: 3,
69
+ strokeLinecap: "round" as const,
70
+ strokeLinejoin: "round" as const,
71
+ strokeDasharray: 15,
72
+ strokeDashoffset: animate ? 0 : 15,
73
+ transition: "stroke-dashoffset 0.15s ease-out 0.45s",
74
+ },
75
+ xPathSecond: {
76
+ fill: "none",
77
+ stroke: "white",
78
+ strokeWidth: 3,
79
+ strokeLinecap: "round" as const,
80
+ strokeLinejoin: "round" as const,
81
+ strokeDasharray: 15,
82
+ strokeDashoffset: animate ? 0 : 15,
83
+ transition: "stroke-dashoffset 0.15s ease-out 0.5s",
84
+ },
85
+ }
86
+
87
+ return (
88
+ <div style={styles.container}>
89
+ <div style={styles.circleContainer}>
90
+ {/* Circle fill */}
91
+ <div style={styles.circleFill} />
92
+
93
+ {/* Progress ring */}
94
+ <svg style={styles.progressRing}>
95
+ <defs>
96
+ <radialGradient
97
+ id="redGradient"
98
+ cx="50%"
99
+ cy="50%"
100
+ r="50%"
101
+ gradientUnits="objectBoundingBox"
102
+ >
103
+ <stop
104
+ offset="0%"
105
+ style={{ stopColor: "#ef4444", stopOpacity: 0 }}
106
+ />
107
+ <stop
108
+ offset="70%"
109
+ style={{ stopColor: "#ef4444", stopOpacity: 0.3 }}
110
+ />
111
+ <stop
112
+ offset="100%"
113
+ style={{ stopColor: "#ef4444", stopOpacity: 1 }}
114
+ />
115
+ </radialGradient>
116
+ </defs>
117
+ <circle cx="40" cy="40" r="36" style={styles.circle} />
118
+ </svg>
119
+
120
+ {/* X icon */}
121
+ <div style={styles.xContainer}>
122
+ <svg width="48" height="48" viewBox="0 0 24 24">
123
+ <path d="M6 6L18 18" style={styles.xPath} />
124
+ <path d="M18 6L6 18" style={styles.xPathSecond} />
125
+ </svg>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ )
130
+ }
@@ -0,0 +1,155 @@
1
+ import type React from "react"
2
+ import { useState } from "react"
3
+ import { InfoIcon } from "@0xsequence/design-system"
4
+ import { Tooltip } from "./Tooltip.js"
5
+ import { TokenImage } from "./TokenImage.js"
6
+ import type { TrailsFeeBreakdown, FeeItem } from "../../fees.js"
7
+
8
+ interface FeeBreakdownProps {
9
+ feeBreakdown: TrailsFeeBreakdown
10
+ children?: React.ReactNode
11
+ }
12
+
13
+ interface FeeRowProps {
14
+ label: string
15
+ feeItem: FeeItem
16
+ tooltip?: string
17
+ }
18
+
19
+ const FeeRow: React.FC<FeeRowProps> = ({ label, feeItem, tooltip }) => (
20
+ <div className="flex justify-between items-center py-1 items-start">
21
+ <span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
22
+ {label}
23
+ {tooltip && (
24
+ <Tooltip message={tooltip}>
25
+ <InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
26
+ </Tooltip>
27
+ )}
28
+ </span>
29
+ <div className="text-right">
30
+ <div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
31
+ <TokenImage
32
+ imageUrl=""
33
+ symbol={feeItem.tokenSymbol}
34
+ chainId={feeItem.chainId}
35
+ contractAddress={feeItem.tokenAddress}
36
+ size={16}
37
+ />
38
+ {feeItem.amount} {feeItem.tokenSymbol}
39
+ </div>
40
+ <div className="text-xs text-gray-500 dark:text-gray-400">
41
+ ~{feeItem.usdValue}
42
+ </div>
43
+ </div>
44
+ </div>
45
+ )
46
+
47
+ export const FeeBreakdown: React.FC<FeeBreakdownProps> = ({
48
+ feeBreakdown,
49
+ children,
50
+ }) => {
51
+ const [isExpanded, setIsExpanded] = useState(false)
52
+
53
+ // Don't render at all if there are no fees
54
+ const hasAnyFees =
55
+ feeBreakdown.originRelayFee ||
56
+ feeBreakdown.destinationRelayFee ||
57
+ feeBreakdown.providerFee ||
58
+ feeBreakdown.trailsFee
59
+
60
+ if (!hasAnyFees) {
61
+ return null
62
+ }
63
+
64
+ return (
65
+ <div className="space-y-2">
66
+ {/* Accordion header */}
67
+ <button
68
+ type="button"
69
+ onClick={() => setIsExpanded(!isExpanded)}
70
+ className="w-full flex items-center justify-between py-1 text-xs transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 cursor-pointer"
71
+ aria-label={isExpanded ? "Hide fee breakdown" : "Show fee breakdown"}
72
+ >
73
+ <span className="flex items-center gap-1 w-full">
74
+ {children ? (
75
+ children
76
+ ) : (
77
+ <Tooltip message="Detailed breakdown of the Trails platform fees">
78
+ <InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
79
+ </Tooltip>
80
+ )}
81
+ </span>
82
+ <svg
83
+ className={`w-3 h-3 transition-transform duration-300 ease-out ml-2 ${
84
+ isExpanded ? "rotate-180" : ""
85
+ }`}
86
+ fill="none"
87
+ stroke="currentColor"
88
+ viewBox="0 0 24 24"
89
+ aria-hidden="true"
90
+ >
91
+ <path
92
+ strokeLinecap="round"
93
+ strokeLinejoin="round"
94
+ strokeWidth={2}
95
+ d="M19 9l-7 7-7-7"
96
+ />
97
+ </svg>
98
+ </button>
99
+
100
+ {/* Collapsible content */}
101
+ <div
102
+ className={`overflow-hidden transition-all duration-300 ease-out ${
103
+ isExpanded ? "max-h-96 opacity-100" : "max-h-0 opacity-0"
104
+ }`}
105
+ >
106
+ <div className="space-y-1 pl-2">
107
+ {feeBreakdown.originRelayFee && (
108
+ <FeeRow
109
+ label="Origin Relay Fee"
110
+ feeItem={feeBreakdown.originRelayFee}
111
+ tooltip="Fee for relaying the origin chain transaction"
112
+ />
113
+ )}
114
+ {feeBreakdown.destinationRelayFee && (
115
+ <FeeRow
116
+ label="Destination Relay Fee"
117
+ feeItem={feeBreakdown.destinationRelayFee}
118
+ tooltip="Fee for relaying the destination chain transaction"
119
+ />
120
+ )}
121
+ {feeBreakdown.providerFee && (
122
+ <FeeRow
123
+ label="Provider Fee"
124
+ feeItem={feeBreakdown.providerFee}
125
+ tooltip="Fee charged by the bridge/swap provider for executing the transaction"
126
+ />
127
+ )}
128
+ {feeBreakdown.trailsFee && (
129
+ <FeeRow
130
+ label="Trails Platform Fee"
131
+ feeItem={feeBreakdown.trailsFee}
132
+ tooltip="Platform fee for using the Trails service"
133
+ />
134
+ )}
135
+
136
+ {/* Total line - only show if we have a total value */}
137
+ {/* {feeBreakdown.totalUsdValue && (
138
+ <div className="flex justify-between items-center py-1 pt-2 border-t border-gray-200 dark:border-gray-700">
139
+ <span className="text-xs font-medium text-gray-700 dark:text-gray-300">
140
+ Total Fees
141
+ </span>
142
+ <div className="text-right">
143
+ <div className="font-medium text-xs text-gray-900 dark:text-white">
144
+ ~{feeBreakdown.totalUsdValue}
145
+ </div>
146
+ </div>
147
+ </div>
148
+ )} */}
149
+ </div>
150
+ </div>
151
+ </div>
152
+ )
153
+ }
154
+
155
+ export default FeeBreakdown
@@ -1,13 +1,8 @@
1
- import {
2
- ChevronRight,
3
- Search,
4
- Loader2,
5
- ChevronDown,
6
- ArrowDown,
7
- } from "lucide-react"
1
+ import { ChevronRight, Search, Loader2, ArrowDown } from "lucide-react"
8
2
  import { useEffect, useState, useMemo, useRef, useCallback } from "react"
9
3
  import type React from "react"
10
4
  import type { Account, WalletClient } from "viem"
5
+ import { zeroAddress } from "viem"
11
6
  import type { TransactionState } from "../../transactions.js"
12
7
  import type { OnCompleteProps } from "../hooks/useSendForm.js"
13
8
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
@@ -35,11 +30,14 @@ import type { PrepareSendQuote } from "../../prepareSend.js"
35
30
  import type { SupportedToken } from "../../tokens.js"
36
31
  import { logger } from "../../logger.js"
37
32
  import { RefundWarning } from "./RefundWarning.js"
33
+ import { PercentageMaxButtons } from "./PercentageMaxButtons.js"
34
+ import { TokenSelectorButton } from "./TokenSelectorButton.js"
35
+ import { useDynamicInputStyles } from "./DynamicInputStyles.js"
38
36
 
39
37
  interface FundProps {
40
38
  onBack?: () => void
41
- account: Account
42
- walletClient: WalletClient
39
+ account?: Account
40
+ walletClient?: WalletClient
43
41
  onTransactionStateChange: (transactionStates: TransactionState[]) => void
44
42
  onError: (error: Error | string | null) => void
45
43
  onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
@@ -154,7 +152,7 @@ export const Fund: React.FC<FundProps> = ({
154
152
  } = useSendForm({
155
153
  account,
156
154
  toAmount: undefined, // Don't pass toAmount for fund form - user enters input amount
157
- toRecipient: selectedRecipient || account.address,
155
+ toRecipient: selectedRecipient || account?.address,
158
156
  toChainId,
159
157
  toToken,
160
158
  toCalldata,
@@ -524,27 +522,10 @@ export const Fund: React.FC<FundProps> = ({
524
522
  }, [tokenAmountForBackend, isInputTypeUsd, sourceTokenPrice])
525
523
 
526
524
  // Dynamic font size based on input length - matching Earn.tsx
527
- const inputStyles = useMemo(() => {
528
- const inputLength = displayAmount.length
529
- let fontSize: string
530
-
531
- if (inputLength > 12) {
532
- fontSize = "0.875rem"
533
- } else if (inputLength > 9) {
534
- fontSize = "1rem"
535
- } else if (inputLength > 6) {
536
- fontSize = "1.125rem"
537
- } else if (inputLength > 3) {
538
- fontSize = "1.25rem"
539
- } else {
540
- fontSize = "1.5rem"
541
- }
542
-
543
- return {
544
- fontSize,
545
- transition: "all 0.1s ease-in-out",
546
- }
547
- }, [displayAmount.length])
525
+ const inputStyles = useDynamicInputStyles({
526
+ inputValue: displayAmount,
527
+ variant: "smaller",
528
+ })
548
529
 
549
530
  const handleOriginTokenSelect = useCallback(
550
531
  (token: any) => {
@@ -637,7 +618,6 @@ export const Fund: React.FC<FundProps> = ({
637
618
  onBack={() => setShowOriginTokenSelector(false)}
638
619
  headerContent="Select From Token"
639
620
  headerContentAlign="left"
640
- showAccountActions={true}
641
621
  />
642
622
  <TokenSelector
643
623
  onTokenSelect={handleOriginTokenSelect}
@@ -684,7 +664,6 @@ export const Fund: React.FC<FundProps> = ({
684
664
  onBack={() => setShowDestinationTokenSelector(false)}
685
665
  headerContent="Select To Token"
686
666
  headerContentAlign="left"
687
- showAccountActions={true}
688
667
  />
689
668
  <TokenSelector
690
669
  onTokenSelect={handleDestinationTokenSelect}
@@ -728,7 +707,6 @@ export const Fund: React.FC<FundProps> = ({
728
707
  onBack={onBack}
729
708
  headerContent="Fund"
730
709
  headerContentAlign="left"
731
- showAccountActions={true}
732
710
  />
733
711
 
734
712
  <div className="space-y-2">
@@ -770,7 +748,7 @@ export const Fund: React.FC<FundProps> = ({
770
748
  <div className="space-y-1">
771
749
  {/* Origin Amount Input Section */}
772
750
  <div className="trails-bg-secondary trails-bg-secondary-hover trails-border-radius-container p-3 group transition-all duration-200 border border-transparent focus-within:!bg-white dark:focus-within:!bg-gray-800 focus-within:border-gray-400 dark:focus-within:border-gray-500">
773
- {/* Deposit Label and Percentage Buttons */}
751
+ {/* Deposit Label */}
774
752
  <div className="flex justify-between items-center mb-2">
775
753
  <div className="text-sm font-medium trails-text-secondary text-left">
776
754
  Deposit
@@ -782,40 +760,6 @@ export const Fund: React.FC<FundProps> = ({
782
760
  ""
783
761
  )}
784
762
  </div>
785
-
786
- {/* Percentage Buttons */}
787
- {originToken && (
788
- <div className="flex space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
789
- <button
790
- type="button"
791
- onClick={() => handlePercentageClick(25)}
792
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
793
- >
794
- 25%
795
- </button>
796
- <button
797
- type="button"
798
- onClick={() => handlePercentageClick(50)}
799
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
800
- >
801
- 50%
802
- </button>
803
- <button
804
- type="button"
805
- onClick={() => handlePercentageClick(75)}
806
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
807
- >
808
- 75%
809
- </button>
810
- <button
811
- type="button"
812
- onClick={() => handlePercentageClick(100)}
813
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
814
- >
815
- Max
816
- </button>
817
- </div>
818
- )}
819
763
  </div>
820
764
 
821
765
  <div className="flex items-center space-x-2">
@@ -869,39 +813,17 @@ export const Fund: React.FC<FundProps> = ({
869
813
  </div>
870
814
 
871
815
  {/* Token Selection Button */}
872
- <button
873
- type="button"
874
- onClick={() => setShowOriginTokenSelector(true)}
875
- className="flex items-center space-x-2 trails-bg-card hover:trails-hover-bg trails-border-radius-input px-2.5 py-1.5 border trails-border-primary transition-colors cursor-pointer"
876
- >
877
- {originToken ? (
878
- <>
879
- <TokenImage
880
- symbol={originToken.symbol}
881
- imageUrl={originToken.imageUrl}
882
- chainId={originToken.chainId}
883
- size={20}
884
- />
885
- <span className="font-medium trails-text-primary text-sm">
886
- {originToken.symbol}
887
- </span>
888
- <ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
889
- </>
890
- ) : (
891
- <>
892
- <span className="font-medium trails-text-muted text-sm">
893
- Select Token
894
- </span>
895
- <ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
896
- </>
897
- )}
898
- </button>
816
+ <TokenSelectorButton
817
+ token={originToken}
818
+ chainId={originToken?.chainId}
819
+ onSelect={() => setShowOriginTokenSelector(true)}
820
+ />
899
821
  </div>
900
822
 
901
823
  {/* Bottom Info Row */}
902
824
  <div className="mt-2 flex justify-between items-center">
903
825
  {/* USD Amount */}
904
- <div className="text-xs trails-text-muted">
826
+ <div className="text-xs text-gray-500 dark:text-gray-400">
905
827
  {originToken?.symbol && displayAmount ? (
906
828
  <>≈ {amountUsdDisplay || "$0.00"}</>
907
829
  ) : (
@@ -909,12 +831,12 @@ export const Fund: React.FC<FundProps> = ({
909
831
  )}
910
832
  </div>
911
833
 
912
- {/* Origin Token Balance */}
913
- <div className="text-xs trails-text-muted text-right">
914
- {originToken ? (
834
+ {/* Origin Token Balance and Percentage Buttons */}
835
+ {originToken && balanceFormatted && (
836
+ <div className="flex items-center space-x-2">
915
837
  <button
916
838
  type="button"
917
- className="text-xs trails-text-muted cursor-pointer hover:trails-hover-text transition-colors bg-transparent border-none p-0"
839
+ className="text-xs text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 transition-colors bg-transparent border-none p-0"
918
840
  onClick={() => handlePercentageClick(100)}
919
841
  onKeyDown={(e) => {
920
842
  if (e.key === "Enter" || e.key === " ") {
@@ -925,14 +847,25 @@ export const Fund: React.FC<FundProps> = ({
925
847
  title="Click to use full balance"
926
848
  >
927
849
  Balance:{" "}
928
- {isBalanceVisible
929
- ? `${balanceFormatted || "0.00"} ${originToken.symbol}`
930
- : "••••••"}
850
+ {isBalanceVisible ? balanceFormatted || "0.00" : "••••••"}
931
851
  </button>
932
- ) : (
933
- <span>&nbsp;</span>
934
- )}
935
- </div>
852
+
853
+ {/* Percentage Buttons */}
854
+ <PercentageMaxButtons
855
+ userBalance={balanceFormatted}
856
+ isNativeToken={originToken.contractAddress === zeroAddress}
857
+ gasCostFormatted={prepareSendQuote?.gasCostFormatted}
858
+ chainId={originToken.chainId}
859
+ onAmountSelect={(amount) => {
860
+ setTokenAmountForBackend(amount)
861
+ setSendFormAmount(amount)
862
+ setGlobalAmount(amount)
863
+ setInputDisplayValue(amount)
864
+ }}
865
+ className="opacity-100"
866
+ />
867
+ </div>
868
+ )}
936
869
  </div>
937
870
  </div>
938
871