diff --git a/src/configs/websocket/index.ts b/src/configs/websocket/index.ts index fd1aa630..fd8b0deb 100644 --- a/src/configs/websocket/index.ts +++ b/src/configs/websocket/index.ts @@ -15,12 +15,17 @@ export type TDerivApi = { authorize: (requestData: AuthorizeRequest) => Promise; }; +let attempts = 10; +const RECONNECT_INTERVAL = attempts * 10000; const PING_INTERVAL = 12000; export class ApiManager { private socket: WebSocket; private derivApi: TDerivApi; private pingInterval: NodeJS.Timer; + private reconnectInterval: NodeJS.Timer; + private is_websocket_connected: (connection_value) => boolean; + private is_websocket_authorized: (connection_value) => boolean; public static instance: ApiManager; public static getInstance() { @@ -51,7 +56,9 @@ export class ApiManager { return this.derivApi.subscribe(request) as Observable>; } - public authorize(token: string) { + public authorize(token: string, setIsConnected, setIsAuthorized) { + this.is_websocket_connected = setIsConnected; + this.is_websocket_authorized = setIsAuthorized; return this.derivApi.authorize({ authorize: token }); } public logout() { @@ -62,14 +69,30 @@ export class ApiManager { if (this.pingInterval) { clearInterval(this.pingInterval); } + if (this.reconnectInterval) { + clearInterval(this.reconnectInterval); + } this.socket.addEventListener('open', () => { + this.is_websocket_connected?.(true); this.pingInterval = setInterval(() => { this.socket.send(JSON.stringify({ ping: 1 })); }, PING_INTERVAL); }); this.socket.addEventListener('close', () => { + this.is_websocket_connected?.(false); + this.is_websocket_authorized?.(false); clearInterval(this.pingInterval); + this.socket = null; + if (attempts > 0) { + this.reconnectInterval = setTimeout(this.init.bind(this), RECONNECT_INTERVAL); + attempts -= 1; + } else { + window.alert( + 'Sorry, the server is currently down. Please refresh the page or try again later', + ); + clearInterval(this.reconnectInterval); + } }); this.socket.addEventListener('error', () => { diff --git a/src/contexts/auth/auth.provider.tsx b/src/contexts/auth/auth.provider.tsx index d36d091e..d458b284 100644 --- a/src/contexts/auth/auth.provider.tsx +++ b/src/contexts/auth/auth.provider.tsx @@ -23,6 +23,7 @@ const AuthProvider = ({ children }: TAuthProviderProps) => { const [is_logged_in, setIsLoggedIn] = useState(false); const [is_authorized, setIsAuthorized] = useState(false); const [is_switching_account, setisSwitchingAccount] = useState(false); + const [is_connected, setIsConnected] = useState(true); const [loginAccounts, setLoginAccounts] = useSessionStorage( LOGIN_ACCOUNTS_SESSION_STORAGE_KEY, @@ -45,7 +46,11 @@ const AuthProvider = ({ children }: TAuthProviderProps) => { const updateAuthorize = useCallback(async () => { if (currentLoginAccount.token) { - const { authorize } = await apiManager.authorize(currentLoginAccount.token); + const { authorize } = await apiManager.authorize( + currentLoginAccount.token, + setIsConnected, + setIsAuthorized, + ); setIsAuthorized(true); setisSwitchingAccount(false); const { account_list, ...user } = authorize; @@ -55,10 +60,10 @@ const AuthProvider = ({ children }: TAuthProviderProps) => { }, [currentLoginAccount.token, setUser, setUserAccounts]); useEffect(() => { - if (!is_authorized) { + if (!is_authorized && is_connected) { updateAuthorize(); } - }, [is_authorized, updateAuthorize]); + }, [is_authorized, is_connected, updateAuthorize]); const updateLoginAccounts = useCallback( (loginAccounts: IUserLoginAccount[]) => { diff --git a/src/contexts/playground/playground.provider.tsx b/src/contexts/playground/playground.provider.tsx index 8141d988..b1b64965 100644 --- a/src/contexts/playground/playground.provider.tsx +++ b/src/contexts/playground/playground.provider.tsx @@ -1,6 +1,4 @@ import React, { ReactNode, useEffect, useMemo, useState } from 'react'; -import apiManager from '@site/src/configs/websocket'; -import { getIsBrowser } from '@site/src/utils'; import { PlaygroundContext } from './playground.context'; import { TSocketResponseData } from '@site/src/configs/websocket/types'; import { TSocketEndpointNames } from '@site/src/configs/websocket/types'; @@ -9,10 +7,6 @@ type TPlaygroundProviderProps = { children: ReactNode; }; -if (getIsBrowser()) { - apiManager.init(); -} - const PlaygroundProvider = ({ children, }: TPlaygroundProviderProps) => {