1- import React , { useEffect , useState } from 'react' ;
2- import * as S from './TieredFees.styles' ;
3- import { useResponsive } from '@app/hooks/useResponsive' ;
4- import { tiers } from '../../SendForm' ;
5- import { set } from 'date-fns' ;
1+ import React , { useState , useEffect } from "react" ;
2+ import * as S from "./TieredFees.styles" ;
3+ import { useResponsive } from "@app/hooks/useResponsive" ;
64
75interface FeeRecommendation {
86 fastestFee : number ;
@@ -11,107 +9,140 @@ interface FeeRecommendation {
119 economyFee : number ;
1210 minimumFee : number ;
1311}
14- type Fees = {
15- [ key in tiers ] : number ;
16- } ;
12+
13+ type Tier = "low" | "med" | "high" ;
14+
15+ interface Fees {
16+ low : number ;
17+ med : number ;
18+ high : number ;
19+ }
20+
21+
22+ // interface Fees {
23+ // [key in Tier]: number;
24+ // }
25+
1726interface TieredFeesProps {
1827 handleFeeChange : ( fee : number ) => void ;
19- inValidAmount : boolean ;
20- txSize : number | null ; // Transaction size passed down from SendForm
28+ invalidAmount : boolean ;
29+ transactionSize : number | null ; // Transaction size passed down from parent
30+ originalFeeRate ?: number ; // Optional original fee rate (used for replacements)
2131}
2232
23- const TieredFees : React . FC < TieredFeesProps > = ( { inValidAmount, handleFeeChange, txSize } ) => {
33+ const DEFAULT_FEES : Fees = { low : 3 , med : 4 , high : 5 } ;
34+
35+ const TieredFees : React . FC < TieredFeesProps > = ( {
36+ handleFeeChange,
37+ invalidAmount,
38+ transactionSize,
39+ originalFeeRate = 0 ,
40+ } ) => {
2441 const { isDesktop, isTablet } = useResponsive ( ) ;
42+ const [ selectedTier , setSelectedTier ] = useState < Tier > ( "low" ) ;
43+ const [ fees , setFees ] = useState < Fees > ( DEFAULT_FEES ) ;
44+ const [ estimatedFee , setEstimatedFee ] = useState < Fees > ( { low : 0 , med : 0 , high : 0 } ) ;
2545 const [ loadingRecommendation , setLoadingRecommendation ] = useState ( false ) ;
26- const [ fetchedrecommendation , setFetchedRecommendation ] = useState ( false ) ;
27- const [ fees , setFees ] = useState < Fees > ( { low : 0 , med : 0 , high : 0 } ) ;
28- const [ selectedTier , setSelectedTier ] = useState < tiers | null > ( 'low' ) ;
29- const [ estimatedFee , setEstimatedFee ] = useState ( { low : 0 , med : 0 , high : 0 } ) ;
46+ const [ fetchedRecommendation , setFetchedRecommendation ] = useState ( false ) ;
47+
48+ // Adjust fees for replacement transactions if originalFeeRate > 0
49+ const adjustFees = ( fetchedFees : Fees ) => {
50+ if ( originalFeeRate > 0 ) {
51+ const adjustedFees = { ...fetchedFees } ;
52+ adjustedFees . low = Math . max ( originalFeeRate + 1 , fetchedFees . low ) ;
53+ adjustedFees . med = Math . max ( adjustedFees . low + 1 , fetchedFees . med ) ;
54+ adjustedFees . high = Math . max ( adjustedFees . med + 1 , fetchedFees . high ) ;
55+ return adjustedFees ;
56+ }
57+ return fetchedFees ;
58+ } ;
3059
3160 useEffect ( ( ) => {
32- if ( loadingRecommendation || fetchedrecommendation ) return ;
61+ if ( loadingRecommendation || fetchedRecommendation ) return ;
3362 const fetchFees = async ( ) => {
3463 setLoadingRecommendation ( true ) ;
3564 try {
36- const response = await fetch ( ' https://mempool.space/api/v1/fees/recommended' ) ;
65+ const response = await fetch ( " https://mempool.space/api/v1/fees/recommended" ) ;
3766 const data : FeeRecommendation = await response . json ( ) ;
38- setFees ( {
67+ const fetchedFees : Fees = {
3968 low : data . economyFee ,
4069 med : data . halfHourFee ,
4170 high : data . fastestFee ,
42- } ) ;
71+ } ;
72+ const adjustedFees = adjustFees ( fetchedFees ) ;
73+ setFees ( adjustedFees ) ;
4374 setFetchedRecommendation ( true ) ;
4475 } catch ( error ) {
45- console . error ( 'Failed to fetch fees:' , error ) ;
76+ console . error ( "Failed to fetch fees:" , error ) ;
77+ setFees ( adjustFees ( DEFAULT_FEES ) ) ;
4678 }
4779 setLoadingRecommendation ( false ) ;
4880 } ;
49-
5081 fetchFees ( ) ;
51- } , [ ] ) ;
82+ } , [ originalFeeRate ] ) ;
5283
5384 // Update estimated fees whenever the fees or transaction size change
5485 useEffect ( ( ) => {
55- if ( txSize ) {
86+ if ( transactionSize ) {
5687 setEstimatedFee ( {
57- low : txSize * fees . low ,
58- med : txSize * fees . med ,
59- high : txSize * fees . high ,
88+ low : Math . ceil ( transactionSize * fees . low ) ,
89+ med : Math . ceil ( transactionSize * fees . med ) ,
90+ high : Math . ceil ( transactionSize * fees . high ) ,
6091 } ) ;
6192 }
62- } , [ fees , txSize ] ) ;
93+ } , [ fees , transactionSize ] ) ;
6394
64- const handleTierChange = ( tier : any ) => {
65- setSelectedTier ( tier . id ) ;
95+ const handleTierChange = ( tier : Tier ) => {
96+ setSelectedTier ( tier ) ;
6697 } ;
6798
6899 useEffect ( ( ) => {
69- handleFeeChange ( fees [ selectedTier as tiers ] ) ;
70- } , [ selectedTier , fees ] ) ;
100+ handleFeeChange ( fees [ selectedTier ] ) ;
101+ } , [ selectedTier , fees , handleFeeChange ] ) ;
71102
72103 return (
73104 < S . TiersWrapper $isMobile = { ! isDesktop && ! isTablet } >
74105 < S . TierCard
75106 $isMobile = { ! isDesktop }
76- onClick = { ( ) => handleTierChange ( { id : ' low' } ) }
77- className = { `tier-hover ${ selectedTier === ' low' ? ' selected' : '' } ${
78- selectedTier === ' low' && inValidAmount ? ' invalidAmount' : ''
107+ onClick = { ( ) => handleTierChange ( " low" ) }
108+ className = { `tier-hover ${ selectedTier === " low" ? " selected" : "" } ${
109+ selectedTier === " low" && invalidAmount ? " invalidAmount" : ""
79110 } `}
80111 >
81112 < S . TierCardContent >
82113 { `Low` }
83114 < br />
84115 { `Priority` }
85116 < S . RateValueWrapper >
86- { `${ fees . low } ` } < br /> { `sat/vB` }
117+ { `${ fees . low } ` } < br /> { `sat/vB` }
87118 < S . RateValue > { `${ estimatedFee . low } Sats` } </ S . RateValue > { /* Show estimated fee */ }
88119 </ S . RateValueWrapper >
89120 </ S . TierCardContent >
90121 </ S . TierCard >
91122
92123 < S . TierCard
93124 $isMobile = { ! isDesktop }
94- onClick = { ( ) => handleTierChange ( { id : ' med' } ) }
95- className = { `tier-hover ${ selectedTier === ' med' ? ' selected' : '' } ${
96- selectedTier === ' med' && inValidAmount ? ' invalidAmount' : ''
125+ onClick = { ( ) => handleTierChange ( " med" ) }
126+ className = { `tier-hover ${ selectedTier === " med" ? " selected" : "" } ${
127+ selectedTier === " med" && invalidAmount ? " invalidAmount" : ""
97128 } `}
98129 >
99130 < S . TierCardContent >
100131 { `Medium` }
101132 < br />
102133 { `Priority` }
103134 < S . RateValueWrapper >
104- { `${ fees . med } ` } < br /> { `sat/vB` }
135+ { `${ fees . med } ` } < br /> { `sat/vB` }
105136 < S . RateValue > { `${ estimatedFee . med } Sats` } </ S . RateValue > { /* Show estimated fee */ }
106137 </ S . RateValueWrapper >
107138 </ S . TierCardContent >
108139 </ S . TierCard >
109140
110141 < S . TierCard
111142 $isMobile = { ! isDesktop }
112- onClick = { ( ) => handleTierChange ( { id : ' high' } ) }
113- className = { `tier-hover ${ selectedTier === ' high' ? ' selected' : '' } ${
114- selectedTier === ' high' && inValidAmount ? ' invalidAmount' : ''
143+ onClick = { ( ) => handleTierChange ( " high" ) }
144+ className = { `tier-hover ${ selectedTier === " high" ? " selected" : "" } ${
145+ selectedTier === " high" && invalidAmount ? " invalidAmount" : ""
115146 } `}
116147 >
117148 < S . TierCardContent >
@@ -130,119 +161,4 @@ const TieredFees: React.FC<TieredFeesProps> = ({ inValidAmount, handleFeeChange,
130161 ) ;
131162} ;
132163
133- export default TieredFees ;
134-
135- // import React, { useEffect, useState } from 'react';
136- // import * as S from './TieredFees.styles';
137- // import { useResponsive } from '@app/hooks/useResponsive';
138- // import { tiers } from '../../SendForm';
139-
140- // interface FeeRecommendation {
141- // fastestFee: number;
142- // halfHourFee: number;
143- // hourFee: number;
144- // economyFee: number;
145- // minimumFee: number;
146- // }
147- // type Fees = {
148- // [key in tiers]: number;
149- // };
150- // interface TieredFeesProps {
151- // // Define the props for your component here
152- // handleFeeChange: (fee: number) => void;
153- // inValidAmount: boolean;
154- // }
155-
156- // const TieredFees: React.FC<TieredFeesProps> = ({ inValidAmount, handleFeeChange }) => {
157- // const { isDesktop, isTablet } = useResponsive();
158- // const [fees, setFees] = useState<Fees>({ low: 0, med: 0, high: 0 });
159- // const [selectedTier, setSelectedTier] = useState<tiers | null>('low');
160-
161- // useEffect(() => {
162- // const fetchFees = async () => {
163- // try {
164- // const response = await fetch('https://mempool.space/api/v1/fees/recommended');
165- // const data: FeeRecommendation = await response.json();
166- // setFees({
167- // low: data.economyFee,
168- // med: data.halfHourFee,
169- // high: data.fastestFee,
170- // });
171- // } catch (error) {
172- // console.error('Failed to fetch fees:', error);
173- // }
174- // };
175-
176- // fetchFees();
177- // }, []);
178- // const handleTierChange = (tier: any) => {
179- // console.log(tier);
180- // setSelectedTier(tier.id);
181- // };
182-
183- // useEffect(() => {
184- // handleFeeChange(fees[selectedTier as tiers]);
185- // }, [selectedTier]);
186- // return (
187- // <S.TiersWrapper $isMobile={!isDesktop || !isTablet }>
188- // <S.TierCard
189- // $isMobile={!isDesktop}
190- // onClick={() => handleTierChange({ id: 'low', rate: fees.med })}
191- // className={`tier-hover ${selectedTier === 'low' ? 'selected' : ''} ${
192- // selectedTier === 'low' && inValidAmount ? 'invalidAmount' : ''
193- // } ` }
194- // >
195- // <S.TierCardContent>
196- // {`Low`}
197- // <br />
198- // {`Priority`}
199- // <S.RateValueWrapper>
200- // <span>{`${fees.low} sat/vB`}</span>
201- // <S.RateValue>{`${fees.low} Sats`}</S.RateValue>
202- // </S.RateValueWrapper>
203- // </S.TierCardContent>
204- // </S.TierCard>
205-
206- // <S.TierCard
207- // $isMobile={!isDesktop}
208- // onClick={() => handleTierChange({ id: 'med', rate: fees.med })}
209- // className={`tier-hover ${selectedTier === 'med' ? 'selected' : ''} ${
210- // selectedTier === 'med' && inValidAmount ? 'invalidAmount' : ''
211- // } ` }
212- // >
213- // <S.TierCardContent>
214- // {`Medium`}
215- // <br />
216- // {`Priority`}
217- // <S.RateValueWrapper>
218- // <span>{`${fees.med} sat/vB`}</span>
219- // <S.RateValue>{`${fees.med} Sats`}</S.RateValue>
220- // </S.RateValueWrapper>
221- // </S.TierCardContent>
222- // </S.TierCard>
223-
224- // <S.TierCard
225- // $isMobile={!isDesktop}
226- // onClick={() => handleTierChange({ id: 'high', rate: fees.high })}
227- // className={`tier-hover ${selectedTier === 'high' ? 'selected' : ''} ${
228- // selectedTier === 'high' && inValidAmount ? 'invalidAmount' : ''
229- // } ` }
230- // >
231- // <S.TierCardContent>
232- // <S.TierCardAmount>
233- // {' '}
234- // {`High`}
235- // <br />
236- // {`Priority`}
237- // </S.TierCardAmount>
238- // <S.RateValueWrapper>
239- // <span>{`${fees.high} sat/vB`}</span>
240- // <S.RateValue>{`${fees.high} Sats`}</S.RateValue>
241- // </S.RateValueWrapper>
242- // </S.TierCardContent>
243- // </S.TierCard>
244- // </S.TiersWrapper>
245- // );
246- // };
247-
248- // export default TieredFees;
164+ export default TieredFees ;
0 commit comments