Enable network switching from header

This commit is contained in:
HenryNguyen5 2018-02-12 18:54:43 -05:00
parent a9e6528a06
commit d904706f51
19 changed files with 389 additions and 157 deletions

View File

@ -33,6 +33,16 @@ export function changeNode(
};
}
export type TChangeNetwork = typeof changeNetwork;
export function changeNetwork(
payload: interfaces.ChangeNetworkAction['payload']
): interfaces.ChangeNetworkAction {
return {
type: TypeKeys.CONFIG_NETWORK_CHANGE,
payload
};
}
export type TPollOfflineStatus = typeof pollOfflineStatus;
export function pollOfflineStatus(): interfaces.PollOfflineStatus {
return {

View File

@ -26,6 +26,13 @@ export interface ChangeNodeAction {
};
}
export interface ChangeNetworkAction {
type: TypeKeys.CONFIG_NETWORK_CHANGE;
payload: {
networkId: string;
};
}
/*** Poll offline status ***/
export interface PollOfflineStatus {
type: TypeKeys.CONFIG_POLL_OFFLINE_STATUS;
@ -82,6 +89,8 @@ export type CustomNetworkAction = AddCustomNetworkAction | RemoveCustomNetworkAc
export type CustomNodeAction = AddCustomNodeAction | RemoveCustomNodeAction;
export type NetworkAction = ChangeNetworkAction;
export type NodeAction =
| ChangeNodeAction
| ChangeNodeIntentAction

View File

@ -14,6 +14,7 @@ export enum TypeKeys {
CONFIG_ADD_CUSTOM_NODE = 'CONFIG_ADD_CUSTOM_NODE',
CONFIG_REMOVE_CUSTOM_NODE = 'CONFIG_REMOVE_CUSTOM_NODE',
CONFIG_NETWORK_CHANGE = 'CONFIG_NETWORK_CHANGE',
CONFIG_ADD_CUSTOM_NETWORK = 'CONFIG_ADD_CUSTOM_NETWORK',
CONFIG_REMOVE_CUSTOM_NETWORK = 'CONFIG_REMOVE_CUSTOM_NETWORK'
}

View File

@ -12,7 +12,7 @@ import {
NodeOnlineAction,
NodeRemovedAction,
TypeKeys,
NetworkSwitchRequestedAction,
BalancerNetworkSwitchRequestedAction,
NetworkSwitchSucceededAction
} from 'actions/nodeBalancer';
@ -83,10 +83,10 @@ export const nodeCallSucceeded = (
payload
});
export const networkSwitchRequested = (): NetworkSwitchRequestedAction => ({
type: TypeKeys.NETWORK_SWTICH_REQUESTED
export const balancerNetworkSwitchRequested = (): BalancerNetworkSwitchRequestedAction => ({
type: TypeKeys.BALANCER_NETWORK_SWTICH_REQUESTED
});
export const networkSwitchSucceeded = (
payload: NetworkSwitchSucceededAction['payload']
): NetworkSwitchSucceededAction => ({ type: TypeKeys.NETWORK_SWITCH_SUCCEEDED, payload });
): NetworkSwitchSucceededAction => ({ type: TypeKeys.BALANCER_NETWORK_SWITCH_SUCCEEDED, payload });

View File

@ -62,12 +62,12 @@ export interface WorkerProcessingAction {
};
}
export interface NetworkSwitchRequestedAction {
type: TypeKeys.NETWORK_SWTICH_REQUESTED;
export interface BalancerNetworkSwitchRequestedAction {
type: TypeKeys.BALANCER_NETWORK_SWTICH_REQUESTED;
}
export interface NetworkSwitchSucceededAction {
type: TypeKeys.NETWORK_SWITCH_SUCCEEDED;
type: TypeKeys.BALANCER_NETWORK_SWITCH_SUCCEEDED;
payload: {
nodeStats: NodeBalancerState['nodes'];
workers: NodeBalancerState['workers'];
@ -103,9 +103,20 @@ export interface NodeCallSucceededAction {
payload: { result: string; nodeCall: NodeCall };
}
export interface BalancerAutoAction {
type: TypeKeys.BALANCER_AUTO;
}
export interface BalancerManualAction {
type: TypeKeys.BALANCER_MANUAL;
payload: { nodeId: string };
}
export type BalancerAction =
| BalancerFlushAction
| NetworkSwitchRequestedAction
| BalancerAutoAction
| BalancerManualAction
| BalancerNetworkSwitchRequestedAction
| NetworkSwitchSucceededAction;
export type NodeAction = NodeOnlineAction | NodeOfflineAction | NodeAddedAction | NodeRemovedAction;

View File

@ -9,12 +9,14 @@ export enum TypeKeys {
WORKER_KILLED = 'WORKER_KILLED',
BALANCER_FLUSH = 'BALANCER_FLUSH',
BALANCER_AUTO = 'BALANCER_AUTO',
BALANCER_MANUAL = 'BALANCER_MANUAL',
NODE_CALL_REQUESTED = 'NODE_CALL_REQUESTED',
NODE_CALL_TIMEOUT = 'NODE_CALL_TIMEOUT',
NODE_CALL_SUCCEEDED = 'NODE_CALL_SUCCEEDED',
NODE_CALL_FAILED = 'NODE_CALL_FAILED',
NETWORK_SWTICH_REQUESTED = 'NETWORK_SWTICH_REQUESTED',
NETWORK_SWITCH_SUCCEEDED = 'NETWORK_SWITCH_SUCCEEDED'
BALANCER_NETWORK_SWTICH_REQUESTED = 'BALANCER_NETWORK_SWTICH_REQUESTED',
BALANCER_NETWORK_SWITCH_SUCCEEDED = 'BALANCER_NETWORK_SWITCH_SUCCEEDED'
}

View File

@ -0,0 +1,217 @@
import {
TChangeNodeIntent,
TAddCustomNode,
TRemoveCustomNode,
TAddCustomNetwork,
AddCustomNodeAction,
changeNodeIntent,
addCustomNode,
removeCustomNode,
addCustomNetwork,
changeNetwork,
TChangeNetwork
} from 'actions/config';
import { ColorDropdown } from 'components/ui';
import React, { Component } from 'react';
import classnames from 'classnames';
import CustomNodeModal from './CustomNodeModal';
import { NodeConfig } from 'types/node';
import { AppState } from 'reducers';
import {
isNodeChanging,
getNodeId,
getNodeConfig,
CustomNodeOption,
NodeOption,
getNodeOptions,
getNetworkOptions,
NetworkOptions,
getSelectedNetwork
} from 'selectors/config';
import { connect } from 'react-redux';
import { isManual } from 'selectors/nodeBalancer';
interface DispatchProps {
changeNetwork: TChangeNetwork;
changeNodeIntent: TChangeNodeIntent;
addCustomNode: TAddCustomNode;
removeCustomNode: TRemoveCustomNode;
addCustomNetwork: TAddCustomNetwork;
}
interface StateProps {
networkOptions: NetworkOptions;
isBalancerOnManual: boolean;
currentNetworkId: string;
node: NodeConfig;
nodeSelection: AppState['config']['nodes']['selectedNode']['nodeId'];
isChangingNode: AppState['config']['nodes']['selectedNode']['pending'];
nodeOptions: (CustomNodeOption | NodeOption)[];
}
const mapStateToProps = (state: AppState): StateProps => ({
isBalancerOnManual: isManual(state),
networkOptions: getNetworkOptions(state),
isChangingNode: isNodeChanging(state),
nodeSelection: getNodeId(state),
node: getNodeConfig(state),
nodeOptions: getNodeOptions(state),
currentNetworkId: getSelectedNetwork(state)
});
const mapDispatchToProps: DispatchProps = {
changeNetwork,
changeNodeIntent,
addCustomNode,
removeCustomNode,
addCustomNetwork
};
interface State {
isAddingCustomNode: boolean;
}
type Props = StateProps & DispatchProps;
class DropDown extends Component<Props, State> {
public state: State = {
isAddingCustomNode: false
};
public render() {
const {
node,
nodeSelection,
isChangingNode,
nodeOptions,
currentNetworkId,
networkOptions,
isBalancerOnManual
} = this.props;
const { isAddingCustomNode } = this.state;
const nodeOpts = nodeOptions.map(n => {
if (n.isCustom) {
const { name: { networkId, nodeId }, isCustom, id, ...rest } = n;
return {
...rest,
name: (
<span>
{networkId} - {nodeId} <small>(custom)</small>
</span>
),
onRemove: () => this.props.removeCustomNode({ id })
};
} else {
const { name: { networkId, service }, isCustom, ...rest } = n;
return {
...rest,
name: (
<span>
{networkId} <small>({service})</small>
</span>
)
};
}
});
const networkOpts = networkOptions.map(n => {
const { networkId } = n;
return {
value: n.networkId,
name: (
<span>
{networkId} <small>{n.isCustom ? '(custom)' : ''}</small>
</span>
)
// onRemove: () => this.props.removeCustomNode({ id })
};
});
const addCustomNodeItem = (
<li>
<a onClick={this.openCustomNodeModal}>Add Custom Node</a>
</li>
);
const nodeDropDown = (
<ColorDropdown
ariaLabel={`
change node. current node is on the ${node.network} network
provided by ${node.service}
`}
options={nodeOpts}
value={nodeSelection}
extra={
<>
{addCustomNodeItem}
<li>
<a onClick={() => {}}> Switch to auto network mode </a>
</li>
</>
}
disabled={nodeSelection === 'web3'}
onChange={this.props.changeNodeIntent}
size="smr"
color="white"
menuAlign="right"
/>
);
const networkDropDown = (
<ColorDropdown
ariaLabel={``}
options={networkOpts}
value={currentNetworkId}
extra={
<>
{addCustomNodeItem}
<li>
<a onClick={() => {}}> Switch to manual node selection </a>
</li>>
</>
}
disabled={nodeSelection === 'web3'}
onChange={(networkId: string) => {
this.props.changeNetwork({ networkId });
}}
size="smr"
color="white"
menuAlign="right"
/>
);
return (
<>
<div
className={classnames({
'Header-branding-right-dropdown': true,
'is-flashing': isChangingNode
})}
>
{isBalancerOnManual ? nodeDropDown : networkDropDown}
</div>
{isAddingCustomNode && (
<CustomNodeModal
addCustomNode={this.addCustomNode}
handleClose={this.closeCustomNodeModal}
/>
)}
</>
);
}
private openCustomNodeModal = () => {
this.setState({ isAddingCustomNode: true });
};
private closeCustomNodeModal = () => {
this.setState({ isAddingCustomNode: false });
};
private addCustomNode = (payload: AddCustomNodeAction['payload']) => {
this.setState({ isAddingCustomNode: false });
this.props.addCustomNode(payload);
};
}
export default connect(mapStateToProps, mapDispatchToProps)(DropDown);

View File

@ -1,130 +1,60 @@
import {
TChangeLanguage,
TChangeNodeIntent,
TAddCustomNode,
TRemoveCustomNode,
TAddCustomNetwork,
AddCustomNodeAction,
changeLanguage,
changeNodeIntent,
addCustomNode,
removeCustomNode,
addCustomNetwork
} from 'actions/config';
import { TChangeLanguage, changeLanguage } from 'actions/config';
import logo from 'assets/images/logo-mycrypto.svg';
import { Dropdown, ColorDropdown } from 'components/ui';
import { Dropdown } from 'components/ui';
import React, { Component } from 'react';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
import { TSetGasPriceField, setGasPriceField } from 'actions/transaction';
import { ANNOUNCEMENT_MESSAGE, ANNOUNCEMENT_TYPE, languages } from 'config';
import Navigation from './components/Navigation';
import CustomNodeModal from './components/CustomNodeModal';
import OnlineStatus from './components/OnlineStatus';
import { getKeyByValue } from 'utils/helpers';
import { NodeConfig } from 'types/node';
import './index.scss';
import { AppState } from 'reducers';
import {
getOffline,
isNodeChanging,
getLanguageSelection,
getNodeId,
getNodeConfig,
CustomNodeOption,
NodeOption,
getNodeOptions,
getNetworkConfig
} from 'selectors/config';
import { NetworkConfig } from 'types/network';
import { connect } from 'react-redux';
import NetworksAndNodesDropdown from 'components/Header/components/NetworksAndNodesDropdown';
interface DispatchProps {
changeLanguage: TChangeLanguage;
changeNodeIntent: TChangeNodeIntent;
setGasPriceField: TSetGasPriceField;
addCustomNode: TAddCustomNode;
removeCustomNode: TRemoveCustomNode;
addCustomNetwork: TAddCustomNetwork;
}
interface StateProps {
network: NetworkConfig;
languageSelection: AppState['config']['meta']['languageSelection'];
node: NodeConfig;
nodeSelection: AppState['config']['nodes']['selectedNode']['nodeId'];
isChangingNode: AppState['config']['nodes']['selectedNode']['pending'];
isOffline: AppState['config']['meta']['offline'];
nodeOptions: (CustomNodeOption | NodeOption)[];
}
const mapStateToProps = (state: AppState): StateProps => ({
isOffline: getOffline(state),
isChangingNode: isNodeChanging(state),
languageSelection: getLanguageSelection(state),
nodeSelection: getNodeId(state),
node: getNodeConfig(state),
nodeOptions: getNodeOptions(state),
network: getNetworkConfig(state)
});
const mapDispatchToProps: DispatchProps = {
setGasPriceField,
changeLanguage,
changeNodeIntent,
addCustomNode,
removeCustomNode,
addCustomNetwork
changeLanguage
};
interface State {
isAddingCustomNode: boolean;
}
type Props = StateProps & DispatchProps;
class Header extends Component<Props, State> {
public state = {
isAddingCustomNode: false
};
class Header extends Component<Props> {
public render() {
const {
languageSelection,
node,
nodeSelection,
isChangingNode,
isOffline,
nodeOptions,
network
} = this.props;
const { isAddingCustomNode } = this.state;
const { languageSelection, isChangingNode, isOffline, network } = this.props;
const selectedLanguage = languageSelection;
const LanguageDropDown = Dropdown as new () => Dropdown<typeof selectedLanguage>;
const options = nodeOptions.map(n => {
if (n.isCustom) {
const { name: { networkId, nodeId }, isCustom, id, ...rest } = n;
return {
...rest,
name: (
<span>
{networkId} - {nodeId} <small>(custom)</small>
</span>
),
onRemove: () => this.props.removeCustomNode({ id })
};
} else {
const { name: { networkId, service }, isCustom, ...rest } = n;
return {
...rest,
name: (
<span>
{networkId} <small>({service})</small>
</span>
)
};
}
});
return (
<div className="Header">
@ -174,37 +104,13 @@ class Header extends Component<Props, State> {
'is-flashing': isChangingNode
})}
>
<ColorDropdown
ariaLabel={`
change node. current node is on the ${node.network} network
provided by ${node.service}
`}
options={options}
value={nodeSelection || ''}
extra={
<li>
<a onClick={this.openCustomNodeModal}>Add Custom Node</a>
</li>
}
disabled={nodeSelection === 'web3'}
onChange={this.props.changeNodeIntent}
size="smr"
color="white"
menuAlign="right"
/>
<NetworksAndNodesDropdown />
</div>
</div>
</section>
</section>
<Navigation color={!network.isCustom && network.color} />
{isAddingCustomNode && (
<CustomNodeModal
addCustomNode={this.addCustomNode}
handleClose={this.closeCustomNodeModal}
/>
)}
</div>
);
}
@ -215,19 +121,6 @@ class Header extends Component<Props, State> {
this.props.changeLanguage(key);
}
};
private openCustomNodeModal = () => {
this.setState({ isAddingCustomNode: true });
};
private closeCustomNodeModal = () => {
this.setState({ isAddingCustomNode: false });
};
private addCustomNode = (payload: AddCustomNodeAction['payload']) => {
this.setState({ isAddingCustomNode: false });
this.props.addCustomNode(payload);
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);

View File

@ -1,7 +1,7 @@
import { ChangeLanguageAction, SetLatestBlockAction, MetaAction } from 'actions/config';
import { TypeKeys } from 'actions/config/constants';
import {
NetworkSwitchRequestedAction,
BalancerNetworkSwitchRequestedAction,
TypeKeys as NodeBalancerTypeKeys,
NodeBalancerAction
} from 'actions/nodeBalancer';
@ -20,7 +20,7 @@ const INITIAL_STATE: State = {
latestBlock: '???'
};
function handleNetworkSwitchRequested(state: State, _: NetworkSwitchRequestedAction) {
function handleNetworkSwitchRequested(state: State, _: BalancerNetworkSwitchRequestedAction) {
return {
...state,
offline: true
@ -69,7 +69,7 @@ export function meta(state: State = INITIAL_STATE, action: MetaAction | NodeBala
case TypeKeys.CONFIG_SET_LATEST_BLOCK:
return setLatestBlock(state, action);
case NodeBalancerTypeKeys.NETWORK_SWTICH_REQUESTED:
case NodeBalancerTypeKeys.BALANCER_NETWORK_SWTICH_REQUESTED:
return handleNetworkSwitchRequested(state, action);
default:
return state;

View File

@ -1,15 +1,18 @@
import { customNetworks, State as CustomNetworksState } from './customNetworks';
import { staticNetworks, State as StaticNetworksState } from './staticNetworks';
import { selectedNetwork, State as SelectedNetworkState } from './selectedNetwork';
import { combineReducers } from 'redux';
interface State {
customNetworks: CustomNetworksState;
staticNetworks: StaticNetworksState;
selectedNetwork: SelectedNetworkState;
}
const networks = combineReducers<State>({
customNetworks,
staticNetworks
staticNetworks,
selectedNetwork
});
export { State, networks, StaticNetworksState, CustomNetworksState };
export { State, networks, StaticNetworksState, CustomNetworksState, SelectedNetworkState };

View File

@ -0,0 +1,17 @@
import { TypeKeys, ChangeNetworkAction, NetworkAction } from 'actions/config';
import { StaticNetworkIds } from 'types/network';
export type State = StaticNetworkIds;
const INITIAL_STATE: State = 'ETH';
const handleNetworkChange = (_: State, { payload }: ChangeNetworkAction) => payload.networkId;
export const selectedNetwork = (state: State = INITIAL_STATE, action: NetworkAction) => {
switch (action.type) {
case TypeKeys.CONFIG_NETWORK_CHANGE:
return handleNetworkChange(state, action);
default:
return state;
}
};

View File

@ -33,57 +33,68 @@ export const INITIAL_STATE: State = {
pLib: new PInfuraNode('https://mainnet.infura.io/mew'),
estimateGas: false
}
/*
},
rop_infura: {
network: 'Ropsten',
isCustom: false,
service: 'infura.io',
lib: new InfuraNode('https://ropsten.infura.io/mew'),
lib: InfuraNode('https://ropsten.infura.io/mew'),
pLib: new PInfuraNode('https://ropsten.infura.io/mew'),
estimateGas: false
},
kov_ethscan: {
network: 'Kovan',
isCustom: false,
service: 'Etherscan.io',
lib: new EtherscanNode('https://kovan.etherscan.io/api'),
pLib: new PEtherscanNode('https://kovan.etherscan.io/api'),
lib: EtherscanNode('https://kovan.etherscan.io/api'),
estimateGas: false
},
rin_ethscan: {
network: 'Rinkeby',
isCustom: false,
service: 'Etherscan.io',
lib: new EtherscanNode('https://rinkeby.etherscan.io/api'),
lib: EtherscanNode('https://rinkeby.etherscan.io/api'),
pLib: new PEtherscanNode('https://rinkeby.etherscan.io/api'),
estimateGas: false
},
rin_infura: {
network: 'Rinkeby',
isCustom: false,
service: 'infura.io',
lib: new InfuraNode('https://rinkeby.infura.io/mew'),
lib: InfuraNode('https://rinkeby.infura.io/mew'),
pLib: new PInfuraNode('https://rinkeby.infura.io/mew'),
estimateGas: false
},
etc_epool: {
network: 'ETC',
isCustom: false,
service: 'Epool.io',
lib: new RPCNode('https://mewapi.epool.io'),
lib: RPCNode('https://mewapi.epool.io'),
pLib: new PRPCNode('https://mewapi.epool.io'),
estimateGas: false
},
ubq: {
network: 'UBQ',
isCustom: false,
service: 'ubiqscan.io',
lib: new RPCNode('https://pyrus2.ubiqscan.io'),
lib: RPCNode('https://pyrus2.ubiqscan.io'),
pLib: new PRPCNode('https://pyrus2.ubiqscan.io'),
estimateGas: true
},
exp_tech: {
network: 'EXP',
isCustom: false,
service: 'Expanse.tech',
lib: new RPCNode('https://node.expanse.tech/'),
lib: RPCNode('https://node.expanse.tech/'),
pLib: new PRPCNode('https://node.expanse.tech/'),
estimateGas: true
}*/
}
};
export const staticNodes = (state: State = INITIAL_STATE, action: NodeAction) => {

View File

@ -0,0 +1,36 @@
import { TypeKeys } from 'actions/nodeBalancer/constants';
import { Reducer } from 'redux';
import { BalancerAction, BalancerAutoAction } from 'actions/nodeBalancer';
export interface State {
manual: boolean;
offline: boolean;
}
const INITIAL_STATE: State = {
manual: false,
offline: false
};
const handleBalancerAuto: Reducer<State> = (state: State, _: BalancerAutoAction) => ({
...state,
manual: false
});
const handleBalancerManual: Reducer<State> = (state: State, _: BalancerAutoAction) => ({
...state,
manual: true
});
export const balancerConfig: Reducer<State> = (
state: State = INITIAL_STATE,
action: BalancerAction
): State => {
switch (action.type) {
case TypeKeys.BALANCER_AUTO:
return handleBalancerAuto(state, action);
case TypeKeys.BALANCER_MANUAL:
return handleBalancerManual(state, action);
default:
return state;
}
};

View File

@ -1,10 +1,16 @@
import { nodes, State as NodeState } from './nodes';
import { State as WorkerState, workers } from './workers';
import { State as BalancerConfigState, balancerConfig } from './balancerConfig';
import { combineReducers } from 'redux';
export interface State {
nodes: NodeState;
workers: WorkerState;
balancerConfig: BalancerConfigState;
}
export const nodeBalancer = combineReducers({ nodes, workers });
export const nodeBalancer = combineReducers({
nodes,
workers,
balancerConfig
});

View File

@ -13,12 +13,9 @@ import {
BalancerFlushAction,
BalancerAction,
NodeRemovedAction,
NetworkSwitchRequestedAction,
NetworkSwitchSucceededAction
} from 'actions/nodeBalancer';
import { TypeKeys } from 'actions/nodeBalancer/constants';
import { configuredStore } from 'store';
import { getNodeConfig } from 'selectors/config';
export interface INodeStats {
isCustom: boolean;
@ -141,7 +138,7 @@ export const nodes: Reducer<State> = (
case TypeKeys.BALANCER_FLUSH:
return handleBalancerFlush(state, action);
case TypeKeys.NETWORK_SWITCH_SUCCEEDED:
case TypeKeys.BALANCER_NETWORK_SWITCH_SUCCEEDED:
return handleNetworkSwitch(state, action);
default:
return state;

View File

@ -89,7 +89,7 @@ export const workers: Reducer<State> = (
action: WorkerAction | NodeCallAction | BalancerAction
): State => {
switch (action.type) {
case TypeKeys.NETWORK_SWITCH_SUCCEEDED:
case TypeKeys.BALANCER_NETWORK_SWITCH_SUCCEEDED:
return handleNetworkSwitch(state, action);
case TypeKeys.WORKER_SPAWNED:
return handleWorkerSpawned(state, action);

View File

@ -15,7 +15,6 @@ import {
import {
nodeCallRequested,
NodeCall,
workerSpawned,
NodeCallRequestedAction,
nodeCallSucceeded,
workerProcessing,
@ -30,7 +29,7 @@ import {
nodeOnline,
BalancerFlushAction,
balancerFlush,
networkSwitchRequested,
balancerNetworkSwitchRequested,
NetworkSwitchSucceededAction,
networkSwitchSucceeded
} from 'actions/nodeBalancer';
@ -43,10 +42,9 @@ import {
getOffline,
getNodeById,
getAllNodesOfNetworkId,
getNetworkConfig,
getSelectedNetwork
} from 'selectors/config';
import { toggleOffline } from 'actions/config';
import { toggleOffline, ChangeNetworkAction, TypeKeys as ConfigTypeKeys } from 'actions/config';
import { StaticNodeConfig, CustomNodeConfig, NodeConfig } from '../../../shared/types/node';
import { INodeStats } from 'reducers/nodeBalancer/nodes';
import { IWorker } from 'reducers/nodeBalancer/workers';
@ -72,7 +70,7 @@ interface IChannels {
const channels: IChannels = {};
function* networkSwitch(): SagaIterator {
yield put(networkSwitchRequested());
yield put(balancerNetworkSwitchRequested());
//flush all existing requests
yield put(balancerFlush());
@ -154,7 +152,7 @@ function* networkSwitch(): SagaIterator {
nodeStats: { ...accu.nodeStats, [currNode.nodeId]: currNode.stats },
workers: { ...accu.workers, ...currNode.workers }
}),
{} as NetworkSwitchSucceededAction['payload']
{ nodeStats: {}, workers: {} } as NetworkSwitchSucceededAction['payload']
);
yield put(networkSwitchSucceeded(networkSwitchPayload));
@ -367,6 +365,7 @@ function* flushHandler(_: BalancerFlushAction): SagaIterator {
export function* nodeBalancer() {
yield all([
call(networkSwitch),
takeEvery(ConfigTypeKeys.CONFIG_NETWORK_CHANGE, networkSwitch),
takeEvery(TypeKeys.NODE_OFFLINE, watchOfflineNode),
fork(handleNodeCallRequests),
takeEvery(TypeKeys.NODE_CALL_TIMEOUT, handleCallTimeouts),

View File

@ -3,7 +3,8 @@ import {
CustomNetworkConfig,
StaticNetworkConfig,
StaticNetworkIds,
NetworkContract
NetworkContract,
NetworkConfig
} from 'types/network';
import { getNodeConfig } from 'selectors/config';
const getConfig = (state: AppState) => state.config;
@ -44,7 +45,7 @@ export const getStaticNetworkConfig = (state: AppState): StaticNetworkConfig | u
return defaultNetwork;
};
export const getSelectedNetwork = (state: AppState) => getNodeConfig(state).network;
export const getSelectedNetwork = (state: AppState) => getNetworks(state).selectedNetwork;
export const getCustomNetworkConfig = (state: AppState): CustomNetworkConfig | undefined => {
const selectedNetwork = getSelectedNetwork(state);
@ -74,3 +75,18 @@ export const getNetworkContracts = (state: AppState): NetworkContract[] | null =
export const getCustomNetworkConfigs = (state: AppState) => getNetworks(state).customNetworks;
export const getStaticNetworkConfigs = (state: AppState) => getNetworks(state).staticNetworks;
export type NetworkOptions = (NetworkConfig & { networkId: string })[];
export const getNetworkOptions = (state: AppState): NetworkOptions => {
const customNetworks = getCustomNetworkConfigs(state);
const staticNetworks = getStaticNetworkConfigs(state);
const allNetworks: { [networkId: string]: NetworkConfig } = {
...customNetworks,
...staticNetworks
};
return Object.entries(allNetworks).map(([networkId, network]) => ({
...network,
networkId
}));
};

View File

@ -2,7 +2,6 @@ import { AppState } from 'reducers';
import { State as NodeBalancerState, INodeStats } from 'reducers/nodeBalancer/nodes';
import { Omit } from 'react-redux';
import { NodeCall } from 'actions/nodeBalancer';
import { getNodeById } from 'selectors/config';
const allMethods = [
'client',
@ -19,6 +18,11 @@ const allMethods = [
];
export const getNodeBalancer = (state: AppState) => state.nodeBalancer;
export const getBalancerConfig = (state: AppState) => getNodeBalancer(state).balancerConfig;
export const isManual = (state: AppState) => getBalancerConfig(state).manual;
export const getNodesState = (state: AppState) => getNodeBalancer(state).nodes;
export type AvailableNodes = {