Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions app/components/UI/Bridge/Views/BridgeView/BridgeView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { RequestStatus, type QuoteResponse } from '@metamask/bridge-controller';
import { SolScope } from '@metamask/keyring-api';
import { mockUseBridgeQuoteData } from '../../_mocks_/useBridgeQuoteData.mock';
import { useBridgeQuoteData } from '../../hooks/useBridgeQuoteData';
import { useRWAToken } from '../../hooks/useRWAToken';
import { strings } from '../../../../../../locales/i18n';
import { isHardwareAccount } from '../../../../../util/address';
import { MOCK_ENTROPY_SOURCE as mockEntropySource } from '../../../../../util/test/keyringControllerTestUtils';
Expand Down Expand Up @@ -266,6 +267,12 @@ jest.mock('../../hooks/useBridgeQuoteData', () => ({
.mockImplementation(() => mockUseBridgeQuoteData),
}));

jest.mock('../../hooks/useRWAToken', () => ({
useRWAToken: jest.fn().mockImplementation(() => ({
isStockToken: jest.fn().mockReturnValue(false),
})),
}));

jest.mock('../../../../../util/address', () => ({
...jest.requireActual('../../../../../util/address'),
isHardwareAccount: jest.fn(),
Expand Down Expand Up @@ -1173,6 +1180,72 @@ describe('BridgeView', () => {
});
});

// TODO: This test suite is temporary and will be replaced by another behavior once geolocation detection will be implemented.
describe('Error Banner for RWA tokens', () => {
beforeEach(() => {
// Mock quote data to show an error
jest
.mocked(useBridgeQuoteData as unknown as jest.Mock)
.mockImplementation(() => ({
...mockUseBridgeQuoteData,
quoteFetchError: 'Error fetching quote',
isNoQuotesAvailable: true,
isLoading: false,
}));
});
it('should show regular error banner when no quotes and no RWA token selected', async () => {
Comment thread
Akaryatrh marked this conversation as resolved.
const testState = createBridgeTestState({
bridgeControllerOverrides: {
quotesLoadingStatus: RequestStatus.FETCHED,
quotes: [],
quotesLastFetched: 12,
},
});

const { getByText } = renderScreen(
BridgeView,
{
name: Routes.BRIDGE.ROOT,
},
{ state: testState },
);

const expected = strings('bridge.error_banner_description');

await waitFor(() => {
expect(getByText(expected)).toBeTruthy();
});
});

it('should show error banner about geolocation restriction when no quotes and RWA token selected', async () => {
jest.mocked(useRWAToken as jest.Mock).mockImplementation(() => ({
isStockToken: jest.fn().mockReturnValue(true),
}));
Comment thread
Akaryatrh marked this conversation as resolved.

const testState = createBridgeTestState({
bridgeControllerOverrides: {
quotesLoadingStatus: RequestStatus.FETCHED,
quotes: [],
quotesLastFetched: 12,
},
});

const { getByText } = renderScreen(
BridgeView,
{
name: Routes.BRIDGE.ROOT,
},
{ state: testState },
);

const expected = strings('bridge.stock_token_error_banner_description');

await waitFor(() => {
expect(getByText(expected)).toBeTruthy();
});
});
});

describe('Error Banner Visibility', () => {
it('should hide error banner when input is focused', async () => {
// Setup state with error condition
Expand Down
13 changes: 12 additions & 1 deletion app/components/UI/Bridge/Views/BridgeView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import { useIsGasIncludedSTXSendBundleSupported } from '../../hooks/useIsGasIncl
import { useIsGasIncluded7702Supported } from '../../hooks/useIsGasIncluded7702Supported/index.ts';
import { useRefreshSmartTransactionsLiveness } from '../../../../hooks/useRefreshSmartTransactionsLiveness';
import { BridgeViewSelectorsIDs } from './BridgeView.testIds';
import { useRWAToken } from '../../hooks/useRWAToken.ts';

export interface BridgeRouteParams {
sourcePage: string;
Expand Down Expand Up @@ -125,6 +126,7 @@ const BridgeView = () => {
const bridgeViewMode = useSelector(selectBridgeViewMode);
const { quotesLastFetched } = useSelector(selectBridgeControllerState);
const { handleSwitchTokens } = useSwitchTokens();
const { isStockToken } = useRWAToken();
const selectedAddress = useSelector(
selectSelectedInternalAccountFormattedAddress,
);
Expand Down Expand Up @@ -416,6 +418,15 @@ const BridgeView = () => {
isSelectingToken,
isSubmittingTx,
]);
const isRWATokenSelected = useMemo(
() =>
(sourceToken && isStockToken(sourceToken as BridgeToken)) ||
(destToken && isStockToken(destToken as BridgeToken)),
[isStockToken, sourceToken, destToken],
);
const genericErrorMessage = isRWATokenSelected
? strings('bridge.stock_token_error_banner_description')
: strings('bridge.error_banner_description');

const renderBottomContent = (submitDisabled: boolean) => {
if (shouldDisplayKeypad && !isLoading) {
Expand Down Expand Up @@ -443,7 +454,7 @@ const BridgeView = () => {
<Box style={styles.buttonContainer}>
<BannerAlert
severity={BannerAlertSeverity.Error}
description={strings('bridge.error_banner_description')}
description={genericErrorMessage}
onClose={() => {
setIsErrorBannerVisible(false);
setIsInputFocused(true);
Expand Down
1 change: 1 addition & 0 deletions locales/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6319,6 +6319,7 @@
"select_recipient": "Select recipient",
"external_account": "External account",
"error_banner_description": "This trade route isn't available right now. Try changing the amount, network, or token and we'll find the best option.",
"stock_token_error_banner_description": "This trade route isn't available right now. Try changing the amount, network, or token and we'll find the best option.\n\nPlease note if you are attempting to trade Ondo Tokenised Stocks you may be geo-restricted e.g. via US, EU, UK and BR.",
"insufficient_funds": "Insufficient funds",
"insufficient_gas": "Insufficient gas",
"select_amount": "Select amount",
Expand Down
Loading