@@ -15,7 +15,11 @@ import { formatDisplayKeyPrice } from '@/utils/keyPriceDisplay.utils';
1515import PercentageBadge from '@/components/common/PercentageBadge' ;
1616import NetworkFeeHint from '@/components/common/NetworkFeeHint' ;
1717import { TRADE_FEE_ESTIMATE } from '@/constants/fees' ;
18- import { formatTransactionFeeDisplay } from '@/utils/transactionFee.utils' ;
18+ import {
19+ fetchTradeNetworkFeeEstimate ,
20+ formatTransactionFeeDisplay ,
21+ type NetworkFeeDataProvider ,
22+ } from '@/utils/transactionFee.utils' ;
1923import { normalizeCreatorDisplayName } from '@/utils/creatorDisplayName.utils' ;
2024
2125export type TradeSide = 'buy' | 'sell' ;
@@ -30,8 +34,13 @@ export interface TradeDialogProps {
3034 onOpenChange : ( open : boolean ) => void ;
3135 onConfirm : ( amount : number ) => Promise < void > | void ;
3236 isSubmitting ?: boolean ;
37+ networkFeeEstimateProvider ?: NetworkFeeDataProvider ;
3338}
3439
40+ type NetworkFeeEstimateState =
41+ | { status : 'idle' | 'loading' | 'error' ; fee : null }
42+ | { status : 'success' ; fee : number } ;
43+
3544const TradeDialog : React . FC < TradeDialogProps > = ( {
3645 open,
3746 side,
@@ -41,8 +50,11 @@ const TradeDialog: React.FC<TradeDialogProps> = ({
4150 onOpenChange,
4251 onConfirm,
4352 isSubmitting = false ,
53+ networkFeeEstimateProvider,
4454} ) => {
4555 const [ amountText , setAmountText ] = useState ( '1' ) ;
56+ const [ networkFeeEstimate , setNetworkFeeEstimate ] =
57+ useState < NetworkFeeEstimateState > ( { status : 'idle' , fee : null } ) ;
4658 const amountInputRef = useRef < HTMLInputElement | null > ( null ) ;
4759
4860 useEffect ( ( ) => {
@@ -65,9 +77,60 @@ const TradeDialog: React.FC<TradeDialogProps> = ({
6577 const title = side === 'buy' ? 'Buy keys' : 'Sell keys' ;
6678 const confirmLabel = side === 'buy' ? 'Confirm buy' : 'Confirm sell' ;
6779 const estimatedNetworkFee = formatTransactionFeeDisplay (
68- TRADE_FEE_ESTIMATE . DEFAULT_NETWORK_FEE ,
80+ networkFeeEstimate . status === 'success'
81+ ? networkFeeEstimate . fee
82+ : TRADE_FEE_ESTIMATE . DEFAULT_NETWORK_FEE ,
6983 { unit : TRADE_FEE_ESTIMATE . UNIT }
7084 ) ;
85+ const networkFeeCopy =
86+ networkFeeEstimate . status === 'loading'
87+ ? 'Estimating...'
88+ : networkFeeEstimate . status === 'error'
89+ ? 'Cannot estimate network fee'
90+ : estimatedNetworkFee ;
91+
92+ useEffect ( ( ) => {
93+ if ( ! open ) {
94+ setNetworkFeeEstimate ( { status : 'idle' , fee : null } ) ;
95+ return ;
96+ }
97+
98+ if ( ! amountValid || ! networkFeeEstimateProvider ) {
99+ setNetworkFeeEstimate ( { status : 'error' , fee : null } ) ;
100+ return ;
101+ }
102+
103+ let cancelled = false ;
104+ setNetworkFeeEstimate ( { status : 'loading' , fee : null } ) ;
105+
106+ fetchTradeNetworkFeeEstimate ( networkFeeEstimateProvider , {
107+ side,
108+ amount : parsedAmount ,
109+ } )
110+ . then ( fee => {
111+ if ( cancelled ) return ;
112+ setNetworkFeeEstimate (
113+ fee == null
114+ ? { status : 'error' , fee : null }
115+ : { status : 'success' , fee }
116+ ) ;
117+ } )
118+ . catch ( ( ) => {
119+ if ( ! cancelled ) {
120+ setNetworkFeeEstimate ( { status : 'error' , fee : null } ) ;
121+ }
122+ } ) ;
123+
124+ return ( ) => {
125+ cancelled = true ;
126+ } ;
127+ } , [
128+ amountValid ,
129+ networkFeeEstimateProvider ,
130+ open ,
131+ parsedAmount ,
132+ side ,
133+ ] ) ;
71134
72135 return (
73136 < Dialog
@@ -147,13 +210,12 @@ const TradeDialog: React.FC<TradeDialogProps> = ({
147210 />
148211 ) }
149212 </ div >
150- { side === 'buy' && (
151- < NetworkFeeHint
152- variant = "text"
153- fee = { estimatedNetworkFee }
154- className = "text-white/45"
155- />
156- ) }
213+ < NetworkFeeHint
214+ variant = "text"
215+ label = "Approx. network fee"
216+ fee = { networkFeeCopy }
217+ className = "text-white/45"
218+ />
157219 { side === 'sell' && parsedAmount > availableHoldings && (
158220 < div className = "text-xs text-red-300" >
159221 You can’t sell more than your current holdings.
0 commit comments