diff --git a/packages/status-js/src/client/client.ts b/packages/status-js/src/client/client.ts index 3caa9ac4..d9cbaff5 100644 --- a/packages/status-js/src/client/client.ts +++ b/packages/status-js/src/client/client.ts @@ -87,52 +87,65 @@ class Client { } } - static async start(options: ClientOptions) { - // Waku + static async start(options: ClientOptions): Promise { const { environment = 'production' } = options - const waku = await createLightNode({ - defaultBootstrap: false, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - emitSelf: true, - pingKeepAlive: 15, - relayKeepAlive: 0, - libp2p: { - peerDiscovery: [ - /** - * >only connects to 1 remote node because of the limited number of nodes - * >run by Status and the limited number of connections provided by these nodes - * > - * >@see https://forum.vac.dev/t/waku-v2-scalability-studies/142/2 - */ - new PeerDiscoveryStaticPeers(peers[environment], { maxPeers: 1 }), - ], - }, - }) - await waku.start() - await waitForRemotePeer( - waku, - [Protocols.Store, Protocols.Filter, Protocols.LightPush], - 10 * 1000 - ) - const wakuDisconnectionTimer = setInterval(async () => { - const connectionsToClose: Promise[] = [] + let waku: WakuLight | undefined + let client: Client | undefined - for (const connection of waku.libp2p.connectionManager.getConnections()) { - if (!connection.streams.length) { - connectionsToClose.push(connection.close()) + try { + // Waku + waku = await createLightNode({ + defaultBootstrap: false, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + emitSelf: true, + pingKeepAlive: 15, + relayKeepAlive: 0, + libp2p: { + peerDiscovery: [ + /** + * >only connects to 1 remote node because of the limited number of nodes + * >run by Status and the limited number of connections provided by these nodes + * > + * >@see https://forum.vac.dev/t/waku-v2-scalability-studies/142/2 + */ + new PeerDiscoveryStaticPeers(peers[environment], { maxPeers: 1 }), + ], + }, + }) + await waku.start() + await waitForRemotePeer( + waku, + [Protocols.Store, Protocols.Filter, Protocols.LightPush], + 10 * 1000 + ) + const wakuDisconnectionTimer = setInterval(async () => { + const connectionsToClose: Promise[] = [] + + for (const connection of waku!.libp2p.connectionManager.getConnections()) { + if (!connection.streams.length) { + connectionsToClose.push(connection.close()) + } } + + await Promise.allSettled(connectionsToClose) + }, 10 * 1000) + + // Client + client = new Client(waku, wakuDisconnectionTimer, options) + + // Community + await client.community.start() + } catch (error) { + if (client) { + await client.stop() + } else if (waku) { + await waku.stop() } - await Promise.allSettled(connectionsToClose) - }, 10 * 1000) - - // Client - const client = new Client(waku, wakuDisconnectionTimer, options) - - // Community - await client.community.start() + throw error + } return client } diff --git a/packages/status-react/src/components/failed/index.tsx b/packages/status-react/src/components/failed/index.tsx new file mode 100644 index 00000000..6892cef2 --- /dev/null +++ b/packages/status-react/src/components/failed/index.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +import { Text } from '../../system' + +export const Failed = () => { + return ( + + Failed to connect. Try reloading. + + ) +} diff --git a/packages/status-react/src/protocol/provider.tsx b/packages/status-react/src/protocol/provider.tsx index a7517513..59b62055 100644 --- a/packages/status-react/src/protocol/provider.tsx +++ b/packages/status-react/src/protocol/provider.tsx @@ -2,6 +2,7 @@ import React, { createContext, useEffect, useReducer } from 'react' import { createClient } from '@status-im/js' +import { Failed } from '../components/failed' import { Loading } from '../components/loading' import type { Account, Client, ClientOptions, Community } from '@status-im/js' @@ -10,6 +11,7 @@ export const Context = createContext(undefined) export type State = { loading: boolean + failed: boolean client: Client | undefined community: Community['description'] | undefined account: Account | undefined @@ -20,6 +22,7 @@ export type Action = | { type: 'INIT'; client: Client } | { type: 'UPDATE_COMMUNITY'; community: Community['description'] } | { type: 'SET_ACCOUNT'; account: Account | undefined } + | { type: 'FAIL' } interface Props { options: ClientOptions @@ -44,6 +47,9 @@ const reducer = (state: State, action: Action): State => { case 'SET_ACCOUNT': { return { ...state, account: action.account } } + case 'FAIL': { + return { ...state, failed: true, loading: false } + } } } @@ -56,15 +62,22 @@ export const ProtocolProvider = (props: Props) => { community: undefined, account: undefined, dispatch: undefined, + failed: false, }) - const { client, loading } = state + const { client, loading, failed } = state useEffect(() => { const loadClient = async () => { - const client = await createClient(options) + try { + const client = await createClient(options) - dispatch({ type: 'INIT', client }) + dispatch({ type: 'INIT', client }) + } catch (error) { + console.error(error) + + dispatch({ type: 'FAIL' }) + } } loadClient() @@ -89,6 +102,10 @@ export const ProtocolProvider = (props: Props) => { } }, [client]) + if (failed) { + return + } + if (loading) { return }