From b727dc28741552ef3da5b560b37381490b3bc5b9 Mon Sep 17 00:00:00 2001 From: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:39:36 +0800 Subject: [PATCH] Farzin/90439/R&D/Make use of `react-query` in `@deriv/api` package (#7845) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: :arrow_up: update `@deriv/api-types` to `1.0.85` * feat(api): :sparkles: update api types with all the requests from `@deriv/api-types` * feat(api): :sparkles: add `useAPI` hook * feat(api): ✨ add `useAPISubscription` hook * feat(api): ✨ add `useAPISubscription` hook * feat(api): ✨ improve types * feat(api): ✨ rename hooks * feat(api): ✨ rename hooks * refactor(api): :fire: remove `QueryClient` config * refactor(api): :fire: remove unnecessary utils file * refactor(api): :fire: remove unnecessary export types * test(api): :white_check_mark: add test for `useFetch` hook * refactor(api): :fire: improve `useSubscription` hook * feat(api): ✨ use `useMutation` hook inside `useRequest` hook * test(cashier): :white_check_mark: fix the failing test * refactor(api): :recycle: move request props to `payload` object * refactor(api): :memo: resolve PR comments * feat(api): :arrow_up: migrating to React Query 4 * fix(cashier): :bug: fix type errors * feat(api): :sparkles: add `useInvalidateQuery` hook * refactor(api): :memo: resolve PR comments * ci: :green_heart: trigger build * ci: :green_heart: trigger build --------- Co-authored-by: Farzin Mirzaie --- packages/account/package.json | 2 +- packages/api/package.json | 6 +- packages/api/src/APIProvider.tsx | 14 +++ packages/api/src/__tests__/useFetch.spec.tsx | 29 +++++ .../api/src/__tests__/useRequest.spec.tsx | 31 ++++++ .../src/__tests__/useSubscription.spec.tsx | 8 +- packages/api/src/__tests__/useWS.spec.tsx | 105 ------------------ packages/api/src/index.ts | 5 +- packages/api/src/useFetch.ts | 19 ++++ packages/api/src/useInvalidateQuery.ts | 10 ++ packages/api/src/useRequest.ts | 20 ++++ packages/api/src/useSubscription.ts | 84 ++++++++------ packages/api/src/useWS.ts | 35 ------ packages/api/src/utils.ts | 36 ++++++ packages/api/types.ts | 51 +++++++-- packages/appstore/package.json | 2 +- packages/cashier/package.json | 2 +- packages/cashier/src/cashier-providers.tsx | 5 +- .../__tests__/funds-protection.spec.tsx | 5 +- .../funds-protection/funds-protection.tsx | 12 +- packages/cfd/package.json | 2 +- packages/hooks/src/index.ts | 2 +- packages/hooks/src/useVerifyEmail.ts | 15 ++- packages/reports/package.json | 2 +- packages/shared/package.json | 2 +- packages/stores/package.json | 2 +- packages/trader/package.json | 2 +- 27 files changed, 290 insertions(+), 218 deletions(-) create mode 100644 packages/api/src/APIProvider.tsx create mode 100644 packages/api/src/__tests__/useFetch.spec.tsx create mode 100644 packages/api/src/__tests__/useRequest.spec.tsx delete mode 100644 packages/api/src/__tests__/useWS.spec.tsx create mode 100644 packages/api/src/useFetch.ts create mode 100644 packages/api/src/useInvalidateQuery.ts create mode 100644 packages/api/src/useRequest.ts delete mode 100644 packages/api/src/useWS.ts create mode 100644 packages/api/src/utils.ts diff --git a/packages/account/package.json b/packages/account/package.json index 8d5d3d34afb4..d6b8107a4467 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -28,7 +28,7 @@ }, "dependencies": { "@binary-com/binary-document-uploader": "^2.4.7", - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/shared": "^1.0.0", "@deriv/translations": "^1.0.0", diff --git a/packages/api/package.json b/packages/api/package.json index 469cea5c7660..603e827785a0 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -5,10 +5,12 @@ "main": "src/index.ts", "dependencies": { "@deriv/shared": "^1.0.0", - "react": "^17.0.2" + "react": "^17.0.2", + "@tanstack/react-query": "^4.28.0", + "@tanstack/react-query-devtools": "^4.28.0" }, "devDependencies": { - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@testing-library/react": "^12.0.0", "@testing-library/react-hooks": "^7.0.2", "@testing-library/user-event": "^13.5.0", diff --git a/packages/api/src/APIProvider.tsx b/packages/api/src/APIProvider.tsx new file mode 100644 index 000000000000..88228b61a50e --- /dev/null +++ b/packages/api/src/APIProvider.tsx @@ -0,0 +1,14 @@ +import React, { PropsWithChildren } from 'react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; + +const queryClient = new QueryClient(); + +const APIProvider = ({ children }: PropsWithChildren) => ( + + {children} + + +); + +export default APIProvider; diff --git a/packages/api/src/__tests__/useFetch.spec.tsx b/packages/api/src/__tests__/useFetch.spec.tsx new file mode 100644 index 000000000000..8d608eb277ac --- /dev/null +++ b/packages/api/src/__tests__/useFetch.spec.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import useFetch from '../useFetch'; +import APIProvider from '../APIProvider'; +import { TSocketResponse } from '../../types'; + +jest.mock('@deriv/shared', () => ({ + WS: { + send: jest.fn(() => + Promise.resolve>({ + msg_type: 'ping', + ping: 'pong', + echo_req: {}, + }) + ), + }, +})); + +describe('useFetch', () => { + test('should call ping and get pong in response', async () => { + const wrapper = ({ children }: { children: JSX.Element }) => {children}; + + const { result, waitFor } = renderHook(() => useFetch('ping'), { wrapper }); + + await waitFor(() => result.current.isSuccess, { timeout: 10000 }); + + expect(result.current.data).toEqual('pong'); + }); +}); diff --git a/packages/api/src/__tests__/useRequest.spec.tsx b/packages/api/src/__tests__/useRequest.spec.tsx new file mode 100644 index 000000000000..871333a910d8 --- /dev/null +++ b/packages/api/src/__tests__/useRequest.spec.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import useRequest from '../useRequest'; +import APIProvider from '../APIProvider'; +import { TSocketResponse } from '../../types'; + +jest.mock('@deriv/shared', () => ({ + WS: { + send: jest.fn(() => + Promise.resolve>({ + msg_type: 'verify_email', + verify_email: 1, + echo_req: {}, + }) + ), + }, +})); + +describe('useRequest', () => { + test('should call verify_email and get 1 in response', async () => { + const wrapper = ({ children }: { children: JSX.Element }) => {children}; + + const { result, waitFor } = renderHook(() => useRequest('verify_email'), { wrapper }); + + result.current.mutate([{ payload: { verify_email: 'john@example.com', type: 'request_email' } }]); + + await waitFor(() => result.current.isSuccess, { timeout: 10000 }); + + expect(result.current.data).toEqual(1); + }); +}); diff --git a/packages/api/src/__tests__/useSubscription.spec.tsx b/packages/api/src/__tests__/useSubscription.spec.tsx index f3327046eb0f..fe7506e78205 100644 --- a/packages/api/src/__tests__/useSubscription.spec.tsx +++ b/packages/api/src/__tests__/useSubscription.spec.tsx @@ -1,14 +1,14 @@ import { renderHook, act } from '@testing-library/react-hooks'; -import { useWS as useWSShared } from '@deriv/shared'; +import { useWS } from '@deriv/shared'; import useSubscription from '../useSubscription'; jest.mock('@deriv/shared'); -const mockUseWSShared = useWSShared as jest.MockedFunction; +const mockUseWS = useWS as jest.MockedFunction; describe('useSubscription', () => { test('should subscribe to p2p_order_info and get the order updates', async () => { - mockUseWSShared.mockReturnValue({ + mockUseWS.mockReturnValue({ subscribe: jest.fn(() => { return { subscribe: async (onData: (response: unknown) => void, onError: (response: unknown) => void) => { @@ -36,7 +36,7 @@ describe('useSubscription', () => { expect(result.current.data).toBe(undefined); act(() => { - result.current.subscribe({ id: '2' }); + result.current.subscribe({ payload: { id: '2' } }); }); await waitForNextUpdate(); diff --git a/packages/api/src/__tests__/useWS.spec.tsx b/packages/api/src/__tests__/useWS.spec.tsx deleted file mode 100644 index f732a6d85bbd..000000000000 --- a/packages/api/src/__tests__/useWS.spec.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { renderHook, act } from '@testing-library/react-hooks'; -import { useWS as useWSShared } from '@deriv/shared'; -import useWS from '../useWS'; -import { TSocketResponse } from '../../types'; - -jest.mock('@deriv/shared'); - -const mockUseWSShared = useWSShared as jest.MockedFunction; - -describe('useWS', () => { - test('should have initial error and data of undefined and is_loading of false', async () => { - const { result } = renderHook(() => useWS('ping')); - - expect(result.current.is_loading).toBe(false); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); - }); - - test('should call ping and get pong in response', async () => { - mockUseWSShared.mockReturnValue({ - send: jest.fn(() => - Promise.resolve>({ - msg_type: 'ping', - ping: 'pong', - echo_req: {}, - }) - ), - }); - - const { result, waitForNextUpdate } = renderHook(() => useWS('ping')); - - expect(result.current.is_loading).toBe(false); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); - - act(() => { - result.current.send(); - }); - - expect(result.current.is_loading).toBe(true); - await waitForNextUpdate(); - expect(result.current.data).toBe('pong'); - expect(result.current.error).toBe(undefined); - expect(result.current.is_loading).toBe(false); - }); - - test('should call verify_email and get 1 in response', async () => { - mockUseWSShared.mockReturnValue({ - send: jest.fn(() => - Promise.resolve>({ - verify_email: 1, - msg_type: 'verify_email', - echo_req: {}, - }) - ), - }); - - const { result, waitForNextUpdate } = renderHook(() => useWS('verify_email')); - - expect(result.current.is_loading).toBe(false); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); - - act(() => { - result.current.send({ verify_email: 'test@test.com', type: 'reset_password' }); - }); - - expect(result.current.is_loading).toBe(true); - await waitForNextUpdate(); - expect(result.current.data).toBe(1); - expect(result.current.error).toBe(undefined); - expect(result.current.is_loading).toBe(false); - }); - - test('should call cashier and get ASK_TNC_APPROVAL error code in response', async () => { - mockUseWSShared.mockReturnValue({ - send: jest.fn(() => - Promise.resolve>({ - msg_type: 'cashier', - echo_req: {}, - error: { - code: 'ASK_TNC_APPROVAL', - message: 'Error message', - }, - }) - ), - }); - - const { result, waitForNextUpdate } = renderHook(() => useWS('cashier')); - - expect(result.current.is_loading).toBe(false); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); - - act(() => { - result.current.send({ cashier: 'deposit' }); - }); - - expect(result.current.is_loading).toBe(true); - await waitForNextUpdate(); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toStrictEqual({ code: 'ASK_TNC_APPROVAL', message: 'Error message' }); - expect(result.current.is_loading).toBe(false); - }); -}); diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 17daa7cf5c6b..f0ccb910ded4 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,2 +1,5 @@ -export { default as useWS } from './useWS'; +export { default as APIProvider } from './APIProvider'; +export { default as useFetch } from './useFetch'; +export { default as useInvalidateQuery } from './useInvalidateQuery'; +export { default as useRequest } from './useRequest'; export { default as useSubscription } from './useSubscription'; diff --git a/packages/api/src/useFetch.ts b/packages/api/src/useFetch.ts new file mode 100644 index 000000000000..02f65cc211dc --- /dev/null +++ b/packages/api/src/useFetch.ts @@ -0,0 +1,19 @@ +import { useQuery } from '@tanstack/react-query'; +import { getQueryKeys, send } from './utils'; +import type { + TSocketEndpointNames, + TSocketAcceptableProps, + TSocketResponseData, + TSocketRequestCleaned, + TSocketRequestQueryOptions, +} from '../types'; + +const useFetch = (name: T, ...props: TSocketAcceptableProps) => { + const prop = props?.[0]; + const payload = prop && 'payload' in prop ? (prop.payload as TSocketRequestCleaned) : undefined; + const options = prop && 'options' in prop ? (prop.options as TSocketRequestQueryOptions) : undefined; + + return useQuery, unknown>(getQueryKeys(name, payload), () => send(name, payload), options); +}; + +export default useFetch; diff --git a/packages/api/src/useInvalidateQuery.ts b/packages/api/src/useInvalidateQuery.ts new file mode 100644 index 000000000000..55e45c72b5f1 --- /dev/null +++ b/packages/api/src/useInvalidateQuery.ts @@ -0,0 +1,10 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { TSocketEndpointNames } from '../types'; + +const useInvalidateQuery = () => { + const queryClient = useQueryClient(); + + return (name: T) => queryClient.invalidateQueries([name]); +}; + +export default useInvalidateQuery; diff --git a/packages/api/src/useRequest.ts b/packages/api/src/useRequest.ts new file mode 100644 index 000000000000..8efe56eece98 --- /dev/null +++ b/packages/api/src/useRequest.ts @@ -0,0 +1,20 @@ +import { useMutation } from '@tanstack/react-query'; +import { send } from './utils'; +import type { + TSocketEndpointNames, + TSocketAcceptableProps, + TSocketResponseData, + TSocketRequestCleaned, + TSocketRequestMutationOptions, +} from '../types'; + +// Todo: Get rid of redundant array wrapper for the props argument. +const useRequest = (name: T, options?: TSocketRequestMutationOptions) => + useMutation, unknown, TSocketAcceptableProps>(props => { + const prop = props?.[0]; + const payload = prop && 'payload' in prop ? (prop.payload as TSocketRequestCleaned) : undefined; + + return send(name, payload); + }, options); + +export default useRequest; diff --git a/packages/api/src/useSubscription.ts b/packages/api/src/useSubscription.ts index baa623d3d8cc..4c4f942ee6aa 100644 --- a/packages/api/src/useSubscription.ts +++ b/packages/api/src/useSubscription.ts @@ -1,42 +1,62 @@ -import { useState } from 'react'; -import { useWS as useWSShared } from '@deriv/shared'; -import { TSocketSubscribableEndpointNames, TSocketAcceptableProps, TSocketResponseData } from '../types'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { useWS } from '@deriv/shared'; +import type { + TSocketSubscribableEndpointNames, + TSocketAcceptableProps, + TSocketResponseData, + TSocketRequestCleaned, +} from '../types'; const useSubscription = (name: T) => { const [is_loading, setIsLoading] = useState(false); const [is_subscribed, setSubscribed] = useState(false); const [error, setError] = useState(); const [data, setData] = useState>(); - const [subscriber, setSubscriber] = useState<{ unsubscribe?: VoidFunction }>(); - const WS = useWSShared(); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const onData = (response: any) => { - setData(response[name === 'ticks' ? 'tick' : name]); - setIsLoading(false); - }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const onError = (response: any) => { - setError(response.error); - setIsLoading(false); - }; - - const subscribe = (...props: TSocketAcceptableProps) => { - setIsLoading(true); - setSubscribed(true); - - try { - setSubscriber(WS.subscribe({ [name]: 1, subscribe: 1, ...(props[0] || {}) }).subscribe(onData, onError)); - } catch (e) { - setError(e); - } - }; - - const unsubscribe = () => { - subscriber?.unsubscribe?.(); + const subscriber = useRef<{ unsubscribe?: VoidFunction }>(); + const WS = useWS(); + + const subscribe = useCallback( + (...props: TSocketAcceptableProps) => { + const prop = props?.[0]; + const payload = prop && 'payload' in prop ? (prop.payload as TSocketRequestCleaned) : undefined; + + setIsLoading(true); + setSubscribed(true); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onData = (response: any) => { + setData(response[name === 'ticks' ? 'tick' : name]); + setIsLoading(false); + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onError = (response: any) => { + setError(response.error); + setIsLoading(false); + }; + + try { + subscriber.current = WS.subscribe({ [name]: 1, subscribe: 1, ...(payload || {}) }).subscribe( + onData, + onError + ); + } catch (e) { + setError(e); + } + }, + [WS, name] + ); + + const unsubscribe = useCallback(() => { + subscriber.current?.unsubscribe?.(); setSubscribed(false); - }; + }, []); + + useEffect(() => { + return () => { + unsubscribe(); + }; + }, [unsubscribe]); return { subscribe, unsubscribe, is_loading, is_subscribed, error, data }; }; diff --git a/packages/api/src/useWS.ts b/packages/api/src/useWS.ts deleted file mode 100644 index 59ff72d6342d..000000000000 --- a/packages/api/src/useWS.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useCallback, useState } from 'react'; -import { useWS as useWSShared } from '@deriv/shared'; -import { TSocketEndpointNames, TSocketAcceptableProps, TSocketResponseData } from '../types'; - -const useWS = (name: T) => { - const [is_loading, setIsLoading] = useState(false); - const [error, setError] = useState(); - const [data, setData] = useState>(); - const WS = useWSShared(); - - const send = useCallback( - async (...props: TSocketAcceptableProps) => { - setIsLoading(true); - - try { - const response = await WS.send({ [name]: 1, ...(props[0] || {}) }); - - if (response.error) { - setError(response.error); - } else { - setData(response[name]); - } - } catch (e) { - setError(e); - } finally { - setIsLoading(false); - } - }, - [WS, name] - ); - - return { send, is_loading, error, data }; -}; - -export default useWS; diff --git a/packages/api/src/utils.ts b/packages/api/src/utils.ts new file mode 100644 index 000000000000..62599914b24a --- /dev/null +++ b/packages/api/src/utils.ts @@ -0,0 +1,36 @@ +import { WS } from '@deriv/shared'; +import { TSocketEndpointNames, TSocketRequestCleaned, TSocketResponseData } from '../types'; + +export const send = async ( + name: T, + payload?: TSocketRequestCleaned +): Promise> => { + const response = await WS.send({ [name]: 1, ...(payload || {}) }); + + if (response.error) { + throw response.error; + } + + return response[name]; +}; + +export const getQueryKeys = (name: string, props?: Record) => { + if (!props) return [name]; + + delete props.req_id; + if (name && props[name] === 1) delete props[name]; + + if (Object.keys(props).length === 0) return [name]; + + const ordered_props = Object.keys(props) + .sort() + .reduce((obj, key) => { + obj[key] = props[key]; + + return obj; + }, {} as { [k: string]: unknown }); + + const query_props = JSON.stringify(ordered_props); + + return [name, query_props]; +}; diff --git a/packages/api/types.ts b/packages/api/types.ts index 36e24f6c5204..032a6b326e38 100644 --- a/packages/api/types.ts +++ b/packages/api/types.ts @@ -1,3 +1,4 @@ +import type { useMutation, useQuery } from '@tanstack/react-query'; import type { ActiveSymbolsResponse, ActiveSymbolsRequest, @@ -155,6 +156,8 @@ import type { PaymentAgentTransferResponse, PaymentAgentWithdrawRequest, PaymentAgentWithdrawResponse, + PaymentAgentWithdrawJustificationRequest, + PaymentAgentWithdrawJustificationResponse, PayoutCurrenciesRequest, PayoutCurrenciesResponse, PingRequest, @@ -225,7 +228,7 @@ import type { ServerStatusRequest, } from '@deriv/api-types'; -export type TSocketEndpoints = { +type TSocketEndpoints = { active_symbols: { request: ActiveSymbolsRequest; response: ActiveSymbolsResponse; @@ -538,6 +541,10 @@ export type TSocketEndpoints = { request: PaymentAgentWithdrawRequest; response: PaymentAgentWithdrawResponse; }; + paymentagent_withdraw_justification: { + request: PaymentAgentWithdrawJustificationRequest; + response: PaymentAgentWithdrawJustificationResponse; + }; payout_currencies: { request: PayoutCurrenciesRequest; response: PayoutCurrenciesResponse; @@ -686,19 +693,39 @@ export type TSocketResponse = TSocketEndpoints[T export type TSocketResponseData = TSocketResponse[T extends 'ticks' ? 'tick' : T]; -export type TSocketRequest = TSocketEndpoints[T]['request']; +type TSocketRequest = TSocketEndpoints[T]['request']; + +type TRemovableEndpointName = T extends KeysMatching, 1> ? T : never; + +export type TSocketRequestCleaned = { + payload: Omit, TRemovableEndpointName | 'passthrough' | 'req_id' | 'subscribe'>; +}; + +export type TSocketRequestQueryOptions = Parameters< + typeof useQuery, unknown> +>[2]; + +export type TSocketRequestMutationOptions = Parameters< + typeof useMutation, unknown, TSocketAcceptableProps> +>[2]; -type TSocketRequestCleaned = Omit< - TSocketRequest, - (T extends KeysMatching, 1> ? T : never) | 'passthrough' | 'req_id' | 'subscribe' +type TSocketRequestWithOptions = Omit< + TSocketRequestCleaned & { options?: TSocketRequestQueryOptions }, + | (TSocketRequestCleaned['payload'] extends Record ? 'payload' : never) + | (O extends true ? never : 'options') >; -type TSocketRequestProps = TSocketRequestCleaned extends Record - ? never - : TSocketRequestCleaned; +type TNever = T extends Record ? never : T; + +type TSocketRequestProps = TNever< + TSocketRequestWithOptions +>; -export type TSocketAcceptableProps = TSocketRequestProps extends never +export type TSocketAcceptableProps = TSocketRequestProps< + T, + O +> extends never ? [undefined?] - : Partial> extends TSocketRequestProps - ? [TSocketRequestProps?] - : [TSocketRequestProps]; + : Partial> extends TSocketRequestProps + ? [TSocketRequestProps?] + : [TSocketRequestProps]; diff --git a/packages/appstore/package.json b/packages/appstore/package.json index ee529eb90634..f7b6dae2ee7b 100644 --- a/packages/appstore/package.json +++ b/packages/appstore/package.json @@ -25,7 +25,7 @@ "license": "Apache-2.0", "dependencies": { "@deriv/account": "^1.0.0", - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/cashier": "^1.0.0", "@deriv/components": "^1.0.0", "@deriv/cfd": "^1.0.0", diff --git a/packages/cashier/package.json b/packages/cashier/package.json index 826a3383f240..02163fd4c667 100644 --- a/packages/cashier/package.json +++ b/packages/cashier/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@deriv/api": "^1.0.0", - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.11", "@deriv/hooks": "^1.0.0", diff --git a/packages/cashier/src/cashier-providers.tsx b/packages/cashier/src/cashier-providers.tsx index 01f2b459d1bf..b1f4b9c7265d 100644 --- a/packages/cashier/src/cashier-providers.tsx +++ b/packages/cashier/src/cashier-providers.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { APIProvider } from '@deriv/api'; import { StoreProvider } from '@deriv/stores'; import { ThemeProvider } from '@deriv/ui'; import { CashierStoreProvider } from './stores/useCashierStores'; @@ -8,7 +9,9 @@ const CashierProviders = ({ children, store }: React.PropsWithChildren<{ store: return ( - {children} + + {children} + ); diff --git a/packages/cashier/src/components/funds-protection/__tests__/funds-protection.spec.tsx b/packages/cashier/src/components/funds-protection/__tests__/funds-protection.spec.tsx index 4d4126eb9cc8..819951b88b25 100644 --- a/packages/cashier/src/components/funds-protection/__tests__/funds-protection.spec.tsx +++ b/packages/cashier/src/components/funds-protection/__tests__/funds-protection.spec.tsx @@ -1,10 +1,13 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; +import { APIProvider } from '@deriv/api'; import FundsProtection from '../funds-protection'; describe('FundsProtection component tests', () => { it('should render the component', () => { - render(); + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('Funds protection level')).toBeInTheDocument(); expect(screen.getByText('Deposit now')).toBeInTheDocument(); diff --git a/packages/cashier/src/components/funds-protection/funds-protection.tsx b/packages/cashier/src/components/funds-protection/funds-protection.tsx index b60cafb1fe62..d864c5c49aa2 100644 --- a/packages/cashier/src/components/funds-protection/funds-protection.tsx +++ b/packages/cashier/src/components/funds-protection/funds-protection.tsx @@ -1,15 +1,11 @@ -import React, { useEffect } from 'react'; -import { useWS } from '@deriv/api'; +import React from 'react'; +import { useRequest } from '@deriv/api'; import { Icon, Button, Text } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; import './funds-protection.scss'; const FundsProtection = () => { - const { data, send } = useWS('tnc_approval'); - - useEffect(() => { - if (data) location.reload(); - }, [data]); + const { mutate } = useRequest('tnc_approval', { onSuccess: () => location.reload() }); return (
@@ -34,7 +30,7 @@ const FundsProtection = () => { /> }

-
diff --git a/packages/cfd/package.json b/packages/cfd/package.json index 855ba86257e9..58ec009a9c9b 100644 --- a/packages/cfd/package.json +++ b/packages/cfd/package.json @@ -79,7 +79,7 @@ }, "dependencies": { "@deriv/account": "^1.0.0", - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.11", "@deriv/shared": "^1.0.0", diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 9681785ade8d..318262fbd150 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -1,5 +1,5 @@ export { default as useCountdown } from './useCountdown'; -export { default as useVerifyEmail, type TEmailVerificationType } from './useVerifyEmail'; +export { default as useVerifyEmail } from './useVerifyEmail'; export { default as useNeedAuthentication } from './useNeedAuthentication'; export { default as useNeedFinancialAssessment } from './useNeedFinancialAssessment'; export { default as useRealSTPAccount } from './useRealSTPAccount'; diff --git a/packages/hooks/src/useVerifyEmail.ts b/packages/hooks/src/useVerifyEmail.ts index 2116418a4089..49dd50798e36 100644 --- a/packages/hooks/src/useVerifyEmail.ts +++ b/packages/hooks/src/useVerifyEmail.ts @@ -1,15 +1,14 @@ import { useState } from 'react'; -import { useWS } from '@deriv/api'; +import { useRequest } from '@deriv/api'; import { useStore } from '@deriv/stores'; -import type { TSocketEndpoints } from '@deriv/api/types'; import useCountdown from './useCountdown'; const RESEND_COUNTDOWN = 60; -export type TEmailVerificationType = TSocketEndpoints['verify_email']['request']['type']; - -const useVerifyEmail = (type: TEmailVerificationType) => { - const WS = useWS('verify_email'); +const useVerifyEmail = ( + type: Parameters>['mutate']>[0][0]['payload']['type'] +) => { + const WS = useRequest('verify_email'); const counter = useCountdown({ from: RESEND_COUNTDOWN }); const { client } = useStore(); const [sent_count, setSentCount] = useState(0); @@ -23,11 +22,11 @@ const useVerifyEmail = (type: TEmailVerificationType) => { setSentCount(old => old + 1); - WS.send({ verify_email: client.email, type }); + WS.mutate([{ payload: { verify_email: client.email, type } }]); }; return { - is_loading: WS.is_loading, + is_loading: WS.isLoading, error: WS.error, data: WS.data, counter: counter.count, diff --git a/packages/reports/package.json b/packages/reports/package.json index b073d6e2ee0d..ebd6169c1ca0 100644 --- a/packages/reports/package.json +++ b/packages/reports/package.json @@ -75,7 +75,7 @@ "webpack-node-externals": "^2.5.2" }, "dependencies": { - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.11", "@deriv/shared": "^1.0.0", diff --git a/packages/shared/package.json b/packages/shared/package.json index 06b2b36f1103..6e5da757327c 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -40,7 +40,7 @@ "typescript": "^4.6.3" }, "dependencies": { - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/translations": "^1.0.0", "@types/js-cookie": "^3.0.1", "@types/react-loadable": "^5.5.6", diff --git a/packages/stores/package.json b/packages/stores/package.json index 0e98034bf1e2..fa5d3c0b4b02 100644 --- a/packages/stores/package.json +++ b/packages/stores/package.json @@ -11,7 +11,7 @@ "react": "^17.0.2" }, "devDependencies": { - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@testing-library/react": "^12.0.0", "@testing-library/react-hooks": "^7.0.2", "@types/lodash.merge": "^4.6.7", diff --git a/packages/trader/package.json b/packages/trader/package.json index 9748f72772f2..3820b4c1c5e6 100644 --- a/packages/trader/package.json +++ b/packages/trader/package.json @@ -79,7 +79,7 @@ "webpack-node-externals": "^2.5.2" }, "dependencies": { - "@deriv/api-types": "^1.0.85", + "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.11", "@deriv/deriv-charts": "1.1.8",