@@ -91,6 +91,7 @@ import { useBridgeTokens } from '../../../hooks/bridge/useBridgeTokens';
91
91
import { getCurrentKeyring , getLocale } from '../../../selectors' ;
92
92
import { isHardwareKeyring } from '../../../helpers/utils/hardware' ;
93
93
import { SECOND } from '../../../../shared/constants/time' ;
94
+ import { BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE } from '../../../../shared/constants/bridge' ;
94
95
import { BridgeInputGroup } from './bridge-input-group' ;
95
96
import { BridgeCTAButton } from './bridge-cta-button' ;
96
97
@@ -151,10 +152,12 @@ const PrepareBridgePage = () => {
151
152
152
153
const ticker = useSelector ( getNativeCurrency ) ;
153
154
const {
155
+ isEstimatedReturnLow,
154
156
isNoQuotesAvailable,
155
157
isInsufficientGasForQuote,
156
158
isInsufficientBalance,
157
159
} = useSelector ( getValidationErrors ) ;
160
+ const { quotesRefreshCount } = useSelector ( getBridgeQuotes ) ;
158
161
const { openBuyCryptoInPdapp } = useRamps ( ) ;
159
162
160
163
const { balanceAmount : nativeAssetBalance } = useLatestBalance (
@@ -190,6 +193,10 @@ const PrepareBridgePage = () => {
190
193
191
194
const [ rotateSwitchTokens , setRotateSwitchTokens ] = useState ( false ) ;
192
195
196
+ // Resets the banner visibility when the estimated return is low
197
+ const [ isLowReturnBannerOpen , setIsLowReturnBannerOpen ] = useState ( true ) ;
198
+ useEffect ( ( ) => setIsLowReturnBannerOpen ( true ) , [ quotesRefreshCount ] ) ;
199
+
193
200
// Background updates are debounced when the switch button is clicked
194
201
// To prevent putting the frontend in an unexpected state, prevent the user
195
202
// from switching tokens within the debounce period
@@ -211,16 +218,27 @@ const PrepareBridgePage = () => {
211
218
dispatch ( resetBridgeState ( ) ) ;
212
219
} , [ ] ) ;
213
220
214
- const scrollRef = useRef < HTMLDivElement > ( null ) ;
215
-
221
+ // Scroll to bottom of the page when banners are shown
222
+ const insufficientBalanceBannerRef = useRef < HTMLDivElement > ( null ) ;
223
+ const isEstimatedReturnLowRef = useRef < HTMLDivElement > ( null ) ;
216
224
useEffect ( ( ) => {
217
225
if ( isInsufficientGasForQuote ( nativeAssetBalance ) ) {
218
- scrollRef . current ?. scrollIntoView ( {
226
+ insufficientBalanceBannerRef . current ?. scrollIntoView ( {
227
+ behavior : 'smooth' ,
228
+ block : 'start' ,
229
+ } ) ;
230
+ }
231
+ if ( isEstimatedReturnLow ) {
232
+ isEstimatedReturnLowRef . current ?. scrollIntoView ( {
219
233
behavior : 'smooth' ,
220
234
block : 'start' ,
221
235
} ) ;
222
236
}
223
- } , [ isInsufficientGasForQuote ( nativeAssetBalance ) ] ) ;
237
+ } , [
238
+ isEstimatedReturnLow ,
239
+ isInsufficientGasForQuote ( nativeAssetBalance ) ,
240
+ isLowReturnBannerOpen ,
241
+ ] ) ;
224
242
225
243
const quoteParams = useMemo (
226
244
( ) => ( {
@@ -603,12 +621,26 @@ const PrepareBridgePage = () => {
603
621
textAlign = { TextAlign . Left }
604
622
/>
605
623
) }
624
+ { isEstimatedReturnLow && isLowReturnBannerOpen && (
625
+ < BannerAlert
626
+ ref = { insufficientBalanceBannerRef }
627
+ marginInline = { 4 }
628
+ marginBottom = { 3 }
629
+ title = { t ( 'lowEstimatedReturnTooltipTitle' ) }
630
+ severity = { BannerAlertSeverity . Warning }
631
+ description = { t ( 'lowEstimatedReturnTooltipMessage' , [
632
+ BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE * 100 ,
633
+ ] ) }
634
+ textAlign = { TextAlign . Left }
635
+ onClose = { ( ) => setIsLowReturnBannerOpen ( false ) }
636
+ />
637
+ ) }
606
638
{ ! isLoading &&
607
639
activeQuote &&
608
640
! isInsufficientBalance ( srcTokenBalance ) &&
609
641
isInsufficientGasForQuote ( nativeAssetBalance ) && (
610
642
< BannerAlert
611
- ref = { scrollRef }
643
+ ref = { isEstimatedReturnLowRef }
612
644
marginInline = { 4 }
613
645
marginBottom = { 3 }
614
646
title = { t ( 'bridgeValidationInsufficientGasTitle' , [ ticker ] ) }
0 commit comments