100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
import { bindActionCreators } from 'redux';
|
||
|
||
import { shepherdProvider, getShepherdPending, getShepherdOffline } from 'libs/nodes';
|
||
import { setOffline, setOnline, getOffline } from 'features/config';
|
||
import { notificationsActions } from 'features/notifications';
|
||
import handleMetaMaskPolling, { METAMASK_POLLING_INTERVAL } from './handleMetaMaskPolling';
|
||
import configureStore from './configureStore';
|
||
|
||
const store = configureStore();
|
||
|
||
window.addEventListener('load', () => {
|
||
const getShepherdStatus = () => ({
|
||
pending: getShepherdPending(),
|
||
isOnline: !getShepherdOffline()
|
||
});
|
||
|
||
const { online, offline, lostNetworkNotif, offlineNotif, restoreNotif } = bindActionCreators(
|
||
{
|
||
offline: setOffline,
|
||
online: setOnline,
|
||
restoreNotif: () =>
|
||
notificationsActions.showNotification(
|
||
'success',
|
||
'Your connection to the network has been restored!',
|
||
3000
|
||
),
|
||
lostNetworkNotif: () =>
|
||
notificationsActions.showNotification(
|
||
'danger',
|
||
`You’ve lost your connection to the network, check your internet
|
||
connection or try changing networks from the dropdown at the
|
||
top right of the page.`,
|
||
Infinity
|
||
),
|
||
|
||
offlineNotif: () =>
|
||
notificationsActions.showNotification(
|
||
'info',
|
||
'You are currently offline. Some features will be unavailable.',
|
||
5000
|
||
)
|
||
},
|
||
store.dispatch
|
||
);
|
||
|
||
const getAppOnline = () => !getOffline(store.getState());
|
||
|
||
/**
|
||
* @description Repeatedly polls itself to check for online state conflict occurs, implemented in recursive style for flexible polling times
|
||
* as network requests take a variable amount of time.
|
||
*
|
||
* Whenever an app online state conflict occurs, it resolves the conflict with the following priority:
|
||
* * If shepherd is online but app is offline -> do a ping request via shepherd provider, with the result of the ping being the set app state
|
||
* * If shepherd is offline but app is online -> set app to offline as it wont be able to make requests anyway
|
||
*/
|
||
async function detectOnlineStateConflict() {
|
||
const shepherdStatus = getShepherdStatus();
|
||
const appOffline = getAppOnline();
|
||
const onlineStateConflict = shepherdStatus.isOnline !== appOffline;
|
||
|
||
if (shepherdStatus.pending || !onlineStateConflict) {
|
||
return setTimeout(detectOnlineStateConflict, 1000);
|
||
}
|
||
|
||
// if app reports online but shepherd offline, then set app offline
|
||
if (appOffline && !shepherdStatus.isOnline) {
|
||
lostNetworkNotif();
|
||
offline();
|
||
} else if (!appOffline && shepherdStatus.isOnline) {
|
||
// if app reports offline but shepherd reports online
|
||
// send a request to shepherd provider to see if we can still send out requests
|
||
const success = await shepherdProvider.ping().catch(() => false);
|
||
if (success) {
|
||
restoreNotif();
|
||
online();
|
||
}
|
||
}
|
||
detectOnlineStateConflict();
|
||
}
|
||
detectOnlineStateConflict();
|
||
|
||
window.addEventListener('offline', () => {
|
||
const previouslyOnline = getAppOnline();
|
||
|
||
// if browser reports as offline and we were previously online
|
||
// then set offline without checking balancer state
|
||
if (!navigator.onLine && previouslyOnline) {
|
||
offlineNotif();
|
||
offline();
|
||
}
|
||
});
|
||
});
|
||
|
||
/** @desc When MetaMask is loaded as an extension, watch for network changes. */
|
||
if ((window as any).web3) {
|
||
setInterval(handleMetaMaskPolling.bind(null, store), METAMASK_POLLING_INTERVAL);
|
||
}
|
||
|
||
export default store;
|