mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Wire up network stability slider in new gas modal (#13029)
Use the new `networkCongestion` property available when we fetch gas fee estimates.
This commit is contained in:
parent
ba54a3d83b
commit
a820bce99a
@ -1,7 +1,6 @@
|
|||||||
.status-slider {
|
.status-slider {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
|
|
||||||
@ -17,6 +16,12 @@
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__arrow-container {
|
||||||
|
margin-left: -10px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__arrow-border {
|
&__arrow-border {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useGasFeeContext } from '../../../../../contexts/gasFee';
|
||||||
import I18nValue from '../../../../ui/i18n-value';
|
import I18nValue from '../../../../ui/i18n-value';
|
||||||
import { NetworkStabilityTooltip } from '../tooltips';
|
import { NetworkStabilityTooltip } from '../tooltips';
|
||||||
|
|
||||||
@ -14,57 +15,70 @@ const GRADIENT_COLORS = [
|
|||||||
'#9A4D71',
|
'#9A4D71',
|
||||||
'#B44561',
|
'#B44561',
|
||||||
'#C54055',
|
'#C54055',
|
||||||
|
'#D73A49',
|
||||||
];
|
];
|
||||||
|
|
||||||
const STATUS_INFO = {
|
const determineStatusInfo = (givenNetworkCongestion) => {
|
||||||
low: {
|
const networkCongestion = givenNetworkCongestion ?? 0.5;
|
||||||
statusLabel: 'notBusy',
|
const colorIndex = Math.round(networkCongestion * 10);
|
||||||
tooltipLabel: 'lowLowercase',
|
const color = GRADIENT_COLORS[colorIndex];
|
||||||
color: GRADIENT_COLORS[0],
|
const sliderTickValue = colorIndex * 10;
|
||||||
},
|
|
||||||
stable: {
|
if (networkCongestion <= 0.33) {
|
||||||
|
return {
|
||||||
|
statusLabel: 'notBusy',
|
||||||
|
tooltipLabel: 'lowLowercase',
|
||||||
|
color,
|
||||||
|
sliderTickValue,
|
||||||
|
};
|
||||||
|
} else if (networkCongestion > 0.66) {
|
||||||
|
return {
|
||||||
|
statusLabel: 'busy',
|
||||||
|
tooltipLabel: 'highLowercase',
|
||||||
|
color,
|
||||||
|
sliderTickValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
statusLabel: 'stable',
|
statusLabel: 'stable',
|
||||||
tooltipLabel: 'stableLowercase',
|
tooltipLabel: 'stableLowercase',
|
||||||
color: GRADIENT_COLORS[4],
|
color,
|
||||||
},
|
sliderTickValue,
|
||||||
high: {
|
};
|
||||||
statusLabel: 'busy',
|
|
||||||
tooltipLabel: 'highLowercase',
|
|
||||||
color: GRADIENT_COLORS[9],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStatusInfo = (status) => {
|
|
||||||
if (status <= 0.33) {
|
|
||||||
return STATUS_INFO.low;
|
|
||||||
} else if (status > 0.66) {
|
|
||||||
return STATUS_INFO.high;
|
|
||||||
}
|
|
||||||
return STATUS_INFO.stable;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const StatusSlider = () => {
|
const StatusSlider = () => {
|
||||||
const statusValue = 0.5;
|
const { gasFeeEstimates } = useGasFeeContext();
|
||||||
const sliderValueNumeric = Math.round(statusValue * 10);
|
const statusInfo = determineStatusInfo(gasFeeEstimates.networkCongestion);
|
||||||
|
|
||||||
const statusInfo = getStatusInfo(statusValue);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NetworkStabilityTooltip statusInfo={statusInfo}>
|
<NetworkStabilityTooltip
|
||||||
|
color={statusInfo.color}
|
||||||
|
tooltipLabel={statusInfo.tooltipLabel}
|
||||||
|
>
|
||||||
<div className="status-slider">
|
<div className="status-slider">
|
||||||
<div className="status-slider__arrow-border">
|
<div className="status-slider__arrow-container">
|
||||||
<div
|
<div
|
||||||
className="status-slider__arrow"
|
className="status-slider__arrow-border"
|
||||||
style={{
|
style={{
|
||||||
borderTopColor: GRADIENT_COLORS[sliderValueNumeric],
|
marginLeft: `${statusInfo.sliderTickValue}%`,
|
||||||
marginLeft: `${sliderValueNumeric * 10}%`,
|
|
||||||
}}
|
}}
|
||||||
/>
|
data-testid="status-slider-arrow-border"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="status-slider__arrow"
|
||||||
|
style={{
|
||||||
|
borderTopColor: statusInfo.color,
|
||||||
|
}}
|
||||||
|
data-testid="status-slider-arrow"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="status-slider__line" />
|
<div className="status-slider__line" />
|
||||||
<div
|
<div
|
||||||
className="status-slider__label"
|
className="status-slider__label"
|
||||||
style={{ color: GRADIENT_COLORS[sliderValueNumeric] }}
|
style={{ color: statusInfo.color }}
|
||||||
|
data-testid="status-slider-label"
|
||||||
>
|
>
|
||||||
<I18nValue messageKey={statusInfo.statusLabel} />
|
<I18nValue messageKey={statusInfo.statusLabel} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,51 +1,89 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { screen } from '@testing-library/react';
|
|
||||||
|
|
||||||
import { renderWithProvider } from '../../../../../../test/jest';
|
import { renderWithProvider } from '../../../../../../test/jest';
|
||||||
import { ETH } from '../../../../../helpers/constants/common';
|
import { GasFeeContext } from '../../../../../contexts/gasFee';
|
||||||
import { GasFeeContextProvider } from '../../../../../contexts/gasFee';
|
|
||||||
import configureStore from '../../../../../store/store';
|
import configureStore from '../../../../../store/store';
|
||||||
|
|
||||||
import StatusSlider from './status-slider';
|
import StatusSlider from './status-slider';
|
||||||
|
|
||||||
jest.mock('../../../../../store/actions', () => ({
|
const renderComponent = ({ networkCongestion }) => {
|
||||||
disconnectGasFeeEstimatePoller: jest.fn(),
|
const component = (
|
||||||
getGasFeeEstimatesAndStartPolling: jest
|
<GasFeeContext.Provider value={{ gasFeeEstimates: { networkCongestion } }}>
|
||||||
.fn()
|
|
||||||
.mockImplementation(() => Promise.resolve()),
|
|
||||||
addPollingTokenToAppState: jest.fn(),
|
|
||||||
getGasFeeTimeEstimate: jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementation(() => Promise.resolve('unknown')),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const renderComponent = () => {
|
|
||||||
const store = configureStore({
|
|
||||||
metamask: {
|
|
||||||
nativeCurrency: ETH,
|
|
||||||
provider: {},
|
|
||||||
cachedBalances: {},
|
|
||||||
accounts: {
|
|
||||||
'0xAddress': {
|
|
||||||
address: '0xAddress',
|
|
||||||
balance: '0x176e5b6f173ebe66',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
selectedAddress: '0xAddress',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return renderWithProvider(
|
|
||||||
<GasFeeContextProvider>
|
|
||||||
<StatusSlider />
|
<StatusSlider />
|
||||||
</GasFeeContextProvider>,
|
</GasFeeContext.Provider>
|
||||||
store,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const store = configureStore();
|
||||||
|
|
||||||
|
return renderWithProvider(component, store);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('NetworkStatus', () => {
|
describe('StatusSlider', () => {
|
||||||
it('should renders stable for statusValue > 0.33 and <= 0.66', () => {
|
it('should show "Not busy" when networkCongestion is less than 0.33', () => {
|
||||||
renderComponent();
|
const { queryByText } = renderComponent({ networkCongestion: 0.32 });
|
||||||
expect(screen.queryByText('Stable')).toBeInTheDocument();
|
expect(queryByText('Not busy')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show "Not busy" when networkCongestion is 0.33', () => {
|
||||||
|
const { queryByText } = renderComponent({ networkCongestion: 0.33 });
|
||||||
|
expect(queryByText('Not busy')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show "Stable" when networkCongestion is between 0.33 and 0.66', () => {
|
||||||
|
const { queryByText } = renderComponent({ networkCongestion: 0.5 });
|
||||||
|
expect(queryByText('Stable')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show "Stable" when networkCongestion is 0.66', () => {
|
||||||
|
const { queryByText } = renderComponent({ networkCongestion: 0.66 });
|
||||||
|
expect(queryByText('Stable')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show "Busy" when networkCongestion is greater than 0.66', () => {
|
||||||
|
const { queryByText } = renderComponent({ networkCongestion: 0.67 });
|
||||||
|
expect(queryByText('Busy')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show "Stable" if networkCongestion has not been set yet', () => {
|
||||||
|
const { getByText } = renderComponent({});
|
||||||
|
expect(getByText('Stable')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should position the arrow based on converting networkCongestion to a percentage rounded to the nearest 10', () => {
|
||||||
|
const { getByTestId } = renderComponent({ networkCongestion: 0.23 });
|
||||||
|
expect(getByTestId('status-slider-arrow-border')).toHaveStyle(
|
||||||
|
'margin-left: 20%',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should position the arrow in the middle if networkCongestion has not been set yet', () => {
|
||||||
|
const { getByTestId } = renderComponent({});
|
||||||
|
expect(getByTestId('status-slider-arrow-border')).toHaveStyle(
|
||||||
|
'margin-left: 50%',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should color the arrow and label based on converting networkCongestion to a percentage rounded to the nearest 10', () => {
|
||||||
|
const { getByTestId } = renderComponent({ networkCongestion: 0.23 });
|
||||||
|
expect(getByTestId('status-slider-arrow')).toHaveStyle(
|
||||||
|
'border-top-color: #2D70BA',
|
||||||
|
);
|
||||||
|
expect(getByTestId('status-slider-label')).toHaveStyle('color: #2D70BA');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should color the arrow and label for the end position if networkCongestion rounds to 100%', () => {
|
||||||
|
const { getByTestId } = renderComponent({ networkCongestion: 0.95 });
|
||||||
|
expect(getByTestId('status-slider-arrow')).toHaveStyle(
|
||||||
|
'border-top-color: #D73A49',
|
||||||
|
);
|
||||||
|
expect(getByTestId('status-slider-label')).toHaveStyle('color: #D73A49');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should color the arrow and label for the middle position if networkCongestion has not been set yet', () => {
|
||||||
|
const { getByTestId } = renderComponent({});
|
||||||
|
expect(getByTestId('status-slider-arrow')).toHaveStyle(
|
||||||
|
'border-top-color: #6A5D92',
|
||||||
|
);
|
||||||
|
expect(getByTestId('status-slider-label')).toHaveStyle('color: #6A5D92');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -57,7 +57,7 @@ PriorityFeeTooltip.propTypes = {
|
|||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NetworkStabilityTooltip = ({ children, statusInfo }) => {
|
export const NetworkStabilityTooltip = ({ children, color, tooltipLabel }) => {
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -66,9 +66,9 @@ export const NetworkStabilityTooltip = ({ children, statusInfo }) => {
|
|||||||
<strong
|
<strong
|
||||||
key="network-status__tooltip"
|
key="network-status__tooltip"
|
||||||
className="network-status__tooltip-label"
|
className="network-status__tooltip-label"
|
||||||
style={{ color: statusInfo.color }}
|
style={{ color }}
|
||||||
>
|
>
|
||||||
{t(statusInfo.tooltipLabel)}
|
{t(tooltipLabel)}
|
||||||
</strong>,
|
</strong>,
|
||||||
])}
|
])}
|
||||||
>
|
>
|
||||||
@ -79,5 +79,6 @@ export const NetworkStabilityTooltip = ({ children, statusInfo }) => {
|
|||||||
|
|
||||||
NetworkStabilityTooltip.propTypes = {
|
NetworkStabilityTooltip.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
statusInfo: PropTypes.object,
|
color: PropTypes.string.isRequired,
|
||||||
|
tooltipLabel: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user