Skip to content

Commit 9e4adf7

Browse files
[WALL] Farhan/WALL-3309/Multiple p2p order calls causing rate limit (#12917)
* fix: 🔧 multiple subscriptions for p2p order notification * fix: 🔧 failing tests * fix: 🔧logout issue * chore: empty commit
1 parent e5fa94e commit 9e4adf7

File tree

6 files changed

+80
-26
lines changed

6 files changed

+80
-26
lines changed

packages/core/src/App/Components/Layout/Header/toggle-notifications.jsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import classNames from 'classnames';
22
import React from 'react';
33
import { Counter, DesktopWrapper, Icon, MobileWrapper, Popover } from '@deriv/components';
4-
import { useP2PCompletedOrdersNotification } from '@deriv/hooks';
54
import NotificationsDialog from 'App/Containers/NotificationsDialog';
65
import 'Sass/app/modules/notifications-dialog.scss';
76

@@ -12,8 +11,6 @@ const ToggleNotificationsDrawer = ({
1211
tooltip_message,
1312
should_disable_pointer_events = false,
1413
}) => {
15-
useP2PCompletedOrdersNotification();
16-
1714
const notifications_toggler_el = (
1815
<div
1916
className={classNames('notifications-toggle__icon-wrapper', {

packages/core/src/App/Containers/Routes/routes.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from 'react';
33
import { withRouter } from 'react-router';
44
import Loadable from 'react-loadable';
55
import { UILoader } from '@deriv/components';
6+
import { useP2PCompletedOrdersNotification } from '@deriv/hooks';
67
import { urlForLanguage } from '@deriv/shared';
78
import { getLanguage } from '@deriv/translations';
89
import BinaryRoutes from 'App/Components/Routes';
@@ -24,6 +25,8 @@ const Routes = observer(({ history, location, passthrough }) => {
2425
const initial_route = React.useRef(null);
2526
const unlisten_to_change = React.useRef(null);
2627

28+
useP2PCompletedOrdersNotification();
29+
2730
React.useEffect(() => {
2831
if (!unlisten_to_change.current && !initial_route.current) {
2932
initial_route.current = location.pathname;

packages/hooks/src/__tests__/useP2PCompletedOrdersNotification.spec.tsx

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,62 @@
11
import * as React from 'react';
2-
import { useFetch, useSubscription } from '@deriv/api';
2+
import { useSubscription } from '@deriv/api';
33
import { mockStore, StoreProvider } from '@deriv/stores';
44
import { renderHook } from '@testing-library/react-hooks';
55
import useP2PCompletedOrdersNotification from '../useP2PCompletedOrdersNotification';
66

77
jest.mock('@deriv/api', () => ({
88
...jest.requireActual('@deriv/api'),
9-
useFetch: jest.fn(),
109
useSubscription: jest.fn(),
1110
}));
1211

13-
const mockUseFetch = useFetch as jest.MockedFunction<typeof useFetch<'website_status'>>;
1412
const mockUseSubscription = useSubscription as jest.MockedFunction<typeof useSubscription<'p2p_order_list'>>;
1513

1614
describe('useP2PCompletedOrdersNotification', () => {
17-
test('should unsubscribe from p2p_order_list if user is not authorized', () => {
15+
test('should not subscribe to p2p_order_list if user is not logged in', () => {
1816
const mock = mockStore({
1917
client: {
2018
is_authorize: false,
19+
is_p2p_enabled: true,
2120
currency: 'USD',
2221
},
2322
notifications: {
2423
p2p_completed_orders: [],
2524
},
2625
});
2726

28-
// @ts-expect-error need to come up with a way to mock the return type of useFetch
29-
mockUseFetch.mockReturnValue({ data: { website_status: { p2p_config: { supported_currencies: ['usd'] } } } });
27+
// @ts-expect-error need to come up with a way to mock the return type of useSubscription
28+
mockUseSubscription.mockReturnValue({
29+
subscribe: jest.fn(),
30+
unsubscribe: jest.fn(),
31+
isSubscribed: false,
32+
});
33+
34+
const wrapper = ({ children }: { children: JSX.Element }) => (
35+
<StoreProvider store={mock}>{children}</StoreProvider>
36+
);
37+
38+
renderHook(() => useP2PCompletedOrdersNotification(), { wrapper });
39+
expect(mockUseSubscription('p2p_order_list').subscribe).not.toBeCalled();
40+
expect(mock.notifications.p2p_completed_orders).toEqual([]);
41+
});
42+
43+
test('should not subscribe to p2p_order_list if user p2p is disabled', () => {
44+
const mock = mockStore({
45+
client: {
46+
is_authorize: true,
47+
is_p2p_enabled: false,
48+
currency: 'EUR',
49+
},
50+
notifications: {
51+
p2p_completed_orders: [],
52+
},
53+
});
3054

3155
// @ts-expect-error need to come up with a way to mock the return type of useSubscription
3256
mockUseSubscription.mockReturnValue({
3357
subscribe: jest.fn(),
3458
unsubscribe: jest.fn(),
59+
isSubscribed: false,
3560
});
3661

3762
const wrapper = ({ children }: { children: JSX.Element }) => (
@@ -40,36 +65,66 @@ describe('useP2PCompletedOrdersNotification', () => {
4065

4166
renderHook(() => useP2PCompletedOrdersNotification(), { wrapper });
4267

43-
expect(mockUseSubscription('p2p_order_list').unsubscribe).toBeCalled();
68+
expect(mockUseSubscription('p2p_order_list').subscribe).not.toBeCalled();
4469
expect(mock.notifications.p2p_completed_orders).toEqual([]);
4570
});
4671

47-
test('should unsubscribe from p2p_order_list if user p2p is disabled', () => {
72+
test('should not call unsubscribe from p2p_order_list if user is logged in and p2p is enabled but list is not subscribed', () => {
4873
const mock = mockStore({
4974
client: {
50-
is_authorize: false,
51-
currency: 'EUR',
75+
is_authorize: true,
76+
is_p2p_enabled: true,
77+
currency: 'USD',
5278
},
5379
notifications: {
5480
p2p_completed_orders: [],
5581
},
5682
});
5783

58-
// @ts-expect-error need to come up with a way to mock the return type of useFetch
59-
mockUseFetch.mockReturnValue({ data: { website_status: { p2p_config: { supported_currencies: ['usd'] } } } });
84+
// @ts-expect-error need to come up with a way to mock the return type of useSubscription
85+
mockUseSubscription.mockReturnValue({
86+
subscribe: jest.fn(),
87+
unsubscribe: jest.fn(),
88+
isSubscribed: false,
89+
});
90+
91+
const wrapper = ({ children }: { children: JSX.Element }) => (
92+
<StoreProvider store={mock}>{children}</StoreProvider>
93+
);
94+
95+
const { unmount } = renderHook(() => useP2PCompletedOrdersNotification(), { wrapper });
96+
97+
unmount();
98+
expect(mockUseSubscription('p2p_order_list').unsubscribe).not.toBeCalled();
99+
expect(mock.notifications.p2p_completed_orders).toEqual([]);
100+
});
101+
102+
test('should unsubscribe from p2p_order_list if user is logged in and p2p is enabled and list is subscribed', () => {
103+
const mock = mockStore({
104+
client: {
105+
is_authorize: true,
106+
is_p2p_enabled: true,
107+
currency: 'USD',
108+
},
109+
notifications: {
110+
p2p_completed_orders: [],
111+
},
112+
});
60113

61114
// @ts-expect-error need to come up with a way to mock the return type of useSubscription
62115
mockUseSubscription.mockReturnValue({
63116
subscribe: jest.fn(),
64117
unsubscribe: jest.fn(),
118+
isSubscribed: true,
65119
});
66120

67121
const wrapper = ({ children }: { children: JSX.Element }) => (
68122
<StoreProvider store={mock}>{children}</StoreProvider>
69123
);
70124

71-
renderHook(() => useP2PCompletedOrdersNotification(), { wrapper });
125+
const { unmount } = renderHook(() => useP2PCompletedOrdersNotification(), { wrapper });
72126

127+
unmount();
73128
expect(mockUseSubscription('p2p_order_list').unsubscribe).toBeCalled();
74129
expect(mock.notifications.p2p_completed_orders).toEqual([]);
75130
});
@@ -78,16 +133,14 @@ describe('useP2PCompletedOrdersNotification', () => {
78133
const mock = mockStore({
79134
client: {
80135
is_authorize: true,
136+
is_p2p_enabled: true,
81137
currency: 'USD',
82138
},
83139
notifications: {
84140
p2p_completed_orders: [],
85141
},
86142
});
87143

88-
// @ts-expect-error need to come up with a way to mock the return type of useFetch
89-
mockUseFetch.mockReturnValue({ data: { website_status: { p2p_config: { supported_currencies: ['usd'] } } } });
90-
91144
const mock_p2p_order_list = [
92145
{
93146
account_currency: 'USD',

packages/hooks/src/useP2PCompletedOrdersNotification.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import React from 'react';
22
import { useStore } from '@deriv/stores';
3-
import useIsP2PEnabled from './useIsP2PEnabled';
43
import useP2POrderList from './useP2POrderList';
54

65
const useP2PCompletedOrdersNotification = () => {
7-
const { data: is_p2p_enabled } = useIsP2PEnabled();
8-
const { subscribe, data, unsubscribe } = useP2POrderList();
6+
const { subscribe, data, unsubscribe, isSubscribed } = useP2POrderList();
97
const { client, notifications } = useStore();
10-
const { is_authorize } = client;
8+
const { is_authorize, is_p2p_enabled } = client;
119

1210
React.useEffect(() => {
1311
if (is_authorize && is_p2p_enabled) {
@@ -16,10 +14,11 @@ const useP2PCompletedOrdersNotification = () => {
1614
active: 0,
1715
},
1816
});
19-
} else {
20-
unsubscribe();
2117
}
22-
}, [is_authorize, is_p2p_enabled, subscribe, unsubscribe]);
18+
return () => {
19+
isSubscribed && unsubscribe();
20+
};
21+
}, [isSubscribed, is_authorize, is_p2p_enabled, subscribe, unsubscribe]);
2322

2423
React.useEffect(() => {
2524
if (data?.p2p_order_list?.list.length && data?.p2p_order_list?.list !== notifications.p2p_completed_orders) {

packages/stores/src/mockStore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ const mock = (): TStores & { is_mock: boolean } => {
153153
is_logging_in: false,
154154
is_mt5_password_not_set: false,
155155
is_mt5_account_list_updated: false,
156+
is_p2p_enabled: false,
156157
is_proof_of_ownership_enabled: false,
157158
is_poa_expired: false,
158159
is_populating_dxtrade_account_list: false,

packages/stores/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ type TClientStore = {
468468
is_low_risk: boolean;
469469
is_mt5_password_not_set: boolean;
470470
is_mt5_account_list_updated: boolean;
471+
is_p2p_enabled: boolean;
471472
is_proof_of_ownership_enabled: boolean;
472473
is_poa_expired: boolean;
473474
is_populating_dxtrade_account_list: boolean;

0 commit comments

Comments
 (0)