From 139cf405e7a1a3bcc0640bb47f55ede0d198916e Mon Sep 17 00:00:00 2001 From: HenryNguyen5 Date: Mon, 29 Jan 2018 20:41:59 -0500 Subject: [PATCH] re-type repo --- common/actions/config/actionCreators.ts | 23 ++--- common/actions/config/actionTypes.ts | 4 +- common/actions/customTokens/actionCreators.ts | 2 +- common/actions/customTokens/actionTypes.ts | 3 +- .../components/BalanceSidebar/AccountInfo.tsx | 11 ++- .../BalanceSidebar/EquivalentValues.tsx | 12 +-- .../TokenBalances/AddCustomTokenForm.tsx | 2 +- .../BalanceSidebar/TokenBalances/Balances.tsx | 2 +- .../BalanceSidebar/TokenBalances/index.tsx | 8 +- .../ConfirmationModal/components/Amount.tsx | 3 +- .../components/TransactionFee.tsx | 9 +- .../components/Details/Node.tsx | 4 +- .../TransactionSucceeded.tsx | 2 +- .../SendButtonFactory/OfflineBroadcast.tsx | 2 +- .../TXMetaDataPanel/TXMetaDataPanel.tsx | 5 +- .../components/AdvancedGas.tsx | 2 +- .../TXMetaDataPanel/components/FeeSummary.tsx | 9 +- .../components/UnitDropDown/UnitDropDown.tsx | 3 +- .../WalletDecrypt/WalletDecrypt.tsx | 5 +- .../components/DeterministicWalletsModal.tsx | 5 +- .../WalletDecrypt/components/LedgerNano.tsx | 1 - .../WalletDecrypt/components/Mnemonic.tsx | 1 - .../WalletDecrypt/components/Trezor.tsx | 1 - common/components/ui/UnitDisplay.tsx | 2 +- common/config/dpaths.ts | 5 -- common/config/index.ts | 1 - common/containers/TabSection/index.tsx | 87 +++++-------------- .../components/InteractExplorer/index.tsx | 5 +- .../components/InteractForm/index.tsx | 2 +- .../components/RequestPayment.tsx | 4 +- .../containers/Tabs/SendTransaction/index.tsx | 3 +- .../Swap/components/LiteSend/LiteSend.tsx | 2 +- common/containers/Tabs/Swap/index.tsx | 3 +- common/libs/nodes/INode.ts | 2 +- common/libs/nodes/custom/index.ts | 2 +- common/libs/nodes/etherscan/requests.ts | 2 +- common/libs/nodes/rpc/index.ts | 2 +- common/libs/nodes/rpc/requests.ts | 3 +- common/libs/values.ts | 4 +- common/libs/wallet/non-deterministic/web3.ts | 5 +- .../config/networks/customNetworks.ts | 2 +- common/reducers/config/networks/index.ts | 12 +-- .../config/networks/selectedNetwork.ts | 10 +-- .../{defaultNetworks.ts => staticNetworks.ts} | 17 ++-- common/reducers/config/nodes/customNodes.ts | 2 +- common/reducers/config/nodes/index.ts | 14 +-- .../nodes/{defaultNodes.ts => staticNodes.ts} | 28 +++--- common/reducers/config/nodes/typings.ts | 49 +---------- common/reducers/customTokens.ts | 2 +- common/sagas/config.ts | 18 ++-- common/sagas/deterministicWallets.ts | 2 +- common/sagas/transaction/signing/helpers.ts | 4 +- common/sagas/wallet/helpers.ts | 2 +- common/sagas/wallet/wallet.ts | 2 +- common/selectors/config/networks.ts | 45 ++++++---- common/selectors/config/nodes.ts | 81 ++++++++++++----- common/selectors/config/tokens.ts | 6 +- common/selectors/wallet.ts | 6 +- common/utils/network.ts | 27 +++--- common/utils/node.ts | 8 +- common/utils/tokens.ts | 2 +- shared/types/hardware-wallets.d.ts | 4 + .../typings.ts => shared/types/network.d.ts | 25 +++--- shared/types/node.d.ts | 45 ++++++++++ spec/config/networks.spec.ts | 4 +- spec/integration/data.int.ts | 4 +- spec/pages/SendTransaction.spec.tsx | 1 - spec/reducers/config.spec.ts | 3 +- spec/reducers/customTokens.spec.ts | 2 +- spec/sagas/config.spec.ts | 6 +- spec/sagas/deterministicWallets.spec.ts | 2 +- spec/sagas/wallet.spec.tsx | 4 +- tsconfig.json | 9 +- 73 files changed, 358 insertions(+), 343 deletions(-) rename common/reducers/config/networks/{defaultNetworks.ts => staticNetworks.ts} (90%) rename common/reducers/config/nodes/{defaultNodes.ts => staticNodes.ts} (79%) create mode 100644 shared/types/hardware-wallets.d.ts rename common/reducers/config/networks/typings.ts => shared/types/network.d.ts (54%) create mode 100644 shared/types/node.d.ts diff --git a/common/actions/config/actionCreators.ts b/common/actions/config/actionCreators.ts index 2f067e70..6a1eb961 100644 --- a/common/actions/config/actionCreators.ts +++ b/common/actions/config/actionCreators.ts @@ -1,6 +1,5 @@ import * as interfaces from './actionTypes'; import { TypeKeys } from './constants'; -import { NodeConfig, CustomNodeConfig, NetworkConfig, CustomNetworkConfig } from 'config'; export type TToggleOfflineConfig = typeof toggleOfflineConfig; export function toggleOfflineConfig(): interfaces.ToggleOfflineAction { @@ -25,14 +24,10 @@ export function changeLanguage(sign: string): interfaces.ChangeLanguageAction { } export type TChangeNode = typeof changeNode; -export function changeNode( - nodeSelection: string, - node: NodeConfig, - network: NetworkConfig -): interfaces.ChangeNodeAction { +export function changeNode(networkName: string, nodeName: string): interfaces.ChangeNodeAction { return { type: TypeKeys.CONFIG_NODE_CHANGE, - payload: { nodeSelection, nodeName, networkName } + payload: { networkName, nodeName } }; } @@ -52,7 +47,9 @@ export function changeNodeIntent(payload: string): interfaces.ChangeNodeIntentAc } export type TAddCustomNode = typeof addCustomNode; -export function addCustomNode(payload: CustomNodeConfig): interfaces.AddCustomNodeAction { +export function addCustomNode( + payload: interfaces.AddCustomNodeAction['payload'] +): interfaces.AddCustomNodeAction { return { type: TypeKeys.CONFIG_ADD_CUSTOM_NODE, payload @@ -60,7 +57,9 @@ export function addCustomNode(payload: CustomNodeConfig): interfaces.AddCustomNo } export type TRemoveCustomNode = typeof removeCustomNode; -export function removeCustomNode(payload: CustomNodeConfig): interfaces.RemoveCustomNodeAction { +export function removeCustomNode( + payload: interfaces.RemoveCustomNodeAction['payload'] +): interfaces.RemoveCustomNodeAction { return { type: TypeKeys.CONFIG_REMOVE_CUSTOM_NODE, payload @@ -68,7 +67,9 @@ export function removeCustomNode(payload: CustomNodeConfig): interfaces.RemoveCu } export type TAddCustomNetwork = typeof addCustomNetwork; -export function addCustomNetwork(payload: CustomNetworkConfig): interfaces.AddCustomNetworkAction { +export function addCustomNetwork( + payload: interfaces.AddCustomNetworkAction['payload'] +): interfaces.AddCustomNetworkAction { return { type: TypeKeys.CONFIG_ADD_CUSTOM_NETWORK, payload @@ -77,7 +78,7 @@ export function addCustomNetwork(payload: CustomNetworkConfig): interfaces.AddCu export type TRemoveCustomNetwork = typeof removeCustomNetwork; export function removeCustomNetwork( - payload: CustomNetworkConfig + payload: interfaces.RemoveCustomNetworkAction['payload'] ): interfaces.RemoveCustomNetworkAction { return { type: TypeKeys.CONFIG_REMOVE_CUSTOM_NETWORK, diff --git a/common/actions/config/actionTypes.ts b/common/actions/config/actionTypes.ts index 56d2290f..9063f867 100644 --- a/common/actions/config/actionTypes.ts +++ b/common/actions/config/actionTypes.ts @@ -1,6 +1,6 @@ import { TypeKeys } from './constants'; -import { CustomNodeConfig } from 'config'; -import { CustomNetworkConfig } from 'reducers/config/networks/typings'; +import { CustomNodeConfig } from 'types/node'; +import { CustomNetworkConfig } from 'types/network'; /*** Toggle Offline ***/ export interface ToggleOfflineAction { diff --git a/common/actions/customTokens/actionCreators.ts b/common/actions/customTokens/actionCreators.ts index a95ed461..72d5246d 100644 --- a/common/actions/customTokens/actionCreators.ts +++ b/common/actions/customTokens/actionCreators.ts @@ -1,6 +1,6 @@ -import { Token } from 'config'; import * as interfaces from './actionTypes'; import { TypeKeys } from './constants'; +import { Token } from 'types/network'; export type TAddCustomToken = typeof addCustomToken; export function addCustomToken(payload: Token): interfaces.AddCustomTokenAction { diff --git a/common/actions/customTokens/actionTypes.ts b/common/actions/customTokens/actionTypes.ts index 7c4f0445..b1368005 100644 --- a/common/actions/customTokens/actionTypes.ts +++ b/common/actions/customTokens/actionTypes.ts @@ -1,5 +1,6 @@ -import { Token } from 'config'; import { TypeKeys } from './constants'; +import { Token } from 'types/network'; + /*** Add custom token ***/ export interface AddCustomTokenAction { type: TypeKeys.CUSTOM_TOKEN_ADD; diff --git a/common/components/BalanceSidebar/AccountInfo.tsx b/common/components/BalanceSidebar/AccountInfo.tsx index 85cccfa3..85eb987f 100644 --- a/common/components/BalanceSidebar/AccountInfo.tsx +++ b/common/components/BalanceSidebar/AccountInfo.tsx @@ -1,5 +1,4 @@ import { Identicon, UnitDisplay } from 'components/ui'; -import { NetworkConfig } from 'config'; import { IWallet, Balance, TrezorWallet, LedgerWallet } from 'libs/wallet'; import React from 'react'; import translate from 'translations'; @@ -8,6 +7,7 @@ import Spinner from 'components/ui/Spinner'; import { getNetworkConfig } from 'selectors/config'; import { AppState } from 'reducers'; import { connect } from 'react-redux'; +import { NetworkConfig } from 'types/network'; interface OwnProps { wallet: IWallet; @@ -66,7 +66,14 @@ class AccountInfo extends React.Component { public render() { const { network, balance } = this.props; const { address, showLongBalance, confirmAddr } = this.state; - const { blockExplorer, tokenExplorer } = network; + let blockExplorer; + let tokenExplorer; + if (!network.isCustom) { + // this is kind of ugly but its the result of typeguards, maybe we can find a cleaner solution later on such as just dedicating it to a selector + blockExplorer = network.blockExplorer; + tokenExplorer = network.tokenExplorer; + } + const wallet = this.props.wallet as LedgerWallet | TrezorWallet; return (
diff --git a/common/components/BalanceSidebar/EquivalentValues.tsx b/common/components/BalanceSidebar/EquivalentValues.tsx index 4a473130..b3bd2a26 100644 --- a/common/components/BalanceSidebar/EquivalentValues.tsx +++ b/common/components/BalanceSidebar/EquivalentValues.tsx @@ -6,12 +6,12 @@ import { TFetchCCRates, fetchCCRates, rateSymbols } from 'actions/rates'; import { chain, flatMap } from 'lodash'; import { TokenBalance, getShownTokenBalances } from 'selectors/wallet'; import { Balance } from 'libs/wallet'; -import { NetworkConfig } from 'config'; import './EquivalentValues.scss'; import { Wei } from 'libs/units'; import { AppState } from 'reducers'; -import { getNetworkConfig } from 'selectors/config'; +import { getNetworkConfig, getOffline } from 'selectors/config'; import { connect } from 'react-redux'; +import { NetworkConfig } from 'types/network'; interface AllValue { symbol: string; @@ -36,10 +36,11 @@ interface State { interface StateProps { balance: Balance; network: NetworkConfig; + tokenBalances: TokenBalance[]; rates: AppState['rates']['rates']; ratesError: AppState['rates']['ratesError']; - isOffline: AppState['config']['offline']; + isOffline: AppState['config']['meta']['offline']; } interface DispatchProps { @@ -67,7 +68,7 @@ class EquivalentValues extends React.Component { public defaultOption( balance: Balance, tokenBalances: TokenBalance[], - network: NetworkConfig + network: StateProps['network'] ): DefaultOption { return { label: 'All', @@ -251,7 +252,6 @@ class EquivalentValues extends React.Component { this.requestedCurrencies = currencies; } } - function mapStateToProps(state: AppState): StateProps { return { balance: state.wallet.balance, @@ -259,7 +259,7 @@ function mapStateToProps(state: AppState): StateProps { network: getNetworkConfig(state), rates: state.rates.rates, ratesError: state.rates.ratesError, - isOffline: state.config.offline + isOffline: getOffline(state) }; } diff --git a/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx b/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx index e14c30a2..77bc52aa 100644 --- a/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx +++ b/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx @@ -1,9 +1,9 @@ import React from 'react'; import classnames from 'classnames'; -import { Token } from 'config'; import { isPositiveIntegerOrZero, isValidETHAddress } from 'libs/validators'; import translate from 'translations'; import NewTabLink from 'components/ui/NewTabLink'; +import { Token } from 'types/network'; import './AddCustomTokenForm.scss'; interface Props { diff --git a/common/components/BalanceSidebar/TokenBalances/Balances.tsx b/common/components/BalanceSidebar/TokenBalances/Balances.tsx index e8f08c7c..50e1917b 100644 --- a/common/components/BalanceSidebar/TokenBalances/Balances.tsx +++ b/common/components/BalanceSidebar/TokenBalances/Balances.tsx @@ -1,9 +1,9 @@ import React from 'react'; import translate from 'translations'; -import { Token } from 'config'; import { TokenBalance } from 'selectors/wallet'; import AddCustomTokenForm from './AddCustomTokenForm'; import TokenRow from './TokenRow'; +import { Token } from 'types/network'; interface Props { allTokens: Token[]; diff --git a/common/components/BalanceSidebar/TokenBalances/index.tsx b/common/components/BalanceSidebar/TokenBalances/index.tsx index 7fca475d..39ce3d42 100644 --- a/common/components/BalanceSidebar/TokenBalances/index.tsx +++ b/common/components/BalanceSidebar/TokenBalances/index.tsx @@ -13,12 +13,12 @@ import { setWalletTokens, TSetWalletTokens } from 'actions/wallet'; -import { getAllTokens } from 'selectors/config'; +import { getAllTokens, getOffline } from 'selectors/config'; import { getTokenBalances, getWalletInst, getWalletConfig, TokenBalance } from 'selectors/wallet'; -import { Token } from 'config'; import translate from 'translations'; import Balances from './Balances'; import Spinner from 'components/ui/Spinner'; +import { Token } from 'types/network'; import './index.scss'; interface StateProps { @@ -29,7 +29,7 @@ interface StateProps { tokensError: AppState['wallet']['tokensError']; isTokensLoading: AppState['wallet']['isTokensLoading']; hasSavedWalletTokens: AppState['wallet']['hasSavedWalletTokens']; - isOffline: AppState['config']['offline']; + isOffline: AppState['config']['meta']['offline']; } interface ActionProps { addCustomToken: TAddCustomToken; @@ -118,7 +118,7 @@ function mapStateToProps(state: AppState): StateProps { tokensError: state.wallet.tokensError, isTokensLoading: state.wallet.isTokensLoading, hasSavedWalletTokens: state.wallet.hasSavedWalletTokens, - isOffline: state.config.offline + isOffline: getOffline(state) }; } diff --git a/common/components/ConfirmationModal/components/Amount.tsx b/common/components/ConfirmationModal/components/Amount.tsx index a02d6e72..10a4b80b 100644 --- a/common/components/ConfirmationModal/components/Amount.tsx +++ b/common/components/ConfirmationModal/components/Amount.tsx @@ -8,11 +8,12 @@ import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { getDecimal, getUnit } from 'selectors/transaction'; import { getNetworkConfig } from 'selectors/config'; +import { NetworkConfig } from 'types/network'; interface StateProps { unit: string; decimal: number; - network: AppState['config']['network']; + network: NetworkConfig; } class AmountClass extends Component { diff --git a/common/components/ConfirmationModal/components/Details/AmountAndGasPrice/components/TransactionFee.tsx b/common/components/ConfirmationModal/components/Details/AmountAndGasPrice/components/TransactionFee.tsx index 224328cd..3f575383 100644 --- a/common/components/ConfirmationModal/components/Details/AmountAndGasPrice/components/TransactionFee.tsx +++ b/common/components/ConfirmationModal/components/Details/AmountAndGasPrice/components/TransactionFee.tsx @@ -4,13 +4,14 @@ import { SerializedTransaction } from 'components/renderCbs'; import { UnitDisplay } from 'components/ui'; import { AppState } from 'reducers'; import { connect } from 'react-redux'; -import { getNetworkConfig } from 'selectors/config'; +import { getNetworkConfig, getOffline } from 'selectors/config'; +import { NetworkConfig } from 'types/network'; import BN from 'bn.js'; interface Props { rates: AppState['rates']['rates']; - network: AppState['config']['network']; - isOffline: AppState['config']['offline']; + network: NetworkConfig; + isOffline: AppState['config']['meta']['offline']; } class TransactionFeeClass extends React.Component { @@ -51,7 +52,7 @@ function mapStateToProps(state: AppState) { return { rates: state.rates.rates, network: getNetworkConfig(state), - isOffline: state.config.offline + isOffline: getOffline(state) }; } export const TransactionFee = connect(mapStateToProps)(TransactionFeeClass); diff --git a/common/components/ConfirmationModal/components/Details/Node.tsx b/common/components/ConfirmationModal/components/Details/Node.tsx index 2d29f2a5..f8941f1e 100644 --- a/common/components/ConfirmationModal/components/Details/Node.tsx +++ b/common/components/ConfirmationModal/components/Details/Node.tsx @@ -1,11 +1,11 @@ -import { NodeConfig } from 'config'; import React, { Component } from 'react'; import { AppState } from 'reducers'; import { connect } from 'react-redux'; import { getNodeConfig } from 'selectors/config'; +import { StaticNodeConfig } from 'types/node'; interface StateProps { - node: NodeConfig; + node: StaticNodeConfig; } class NodeClass extends Component { diff --git a/common/components/ExtendedNotifications/TransactionSucceeded.tsx b/common/components/ExtendedNotifications/TransactionSucceeded.tsx index 1093fd82..307680f8 100644 --- a/common/components/ExtendedNotifications/TransactionSucceeded.tsx +++ b/common/components/ExtendedNotifications/TransactionSucceeded.tsx @@ -1,6 +1,6 @@ -import { BlockExplorerConfig } from 'config'; import React from 'react'; import { translateRaw } from 'translations'; +import { BlockExplorerConfig } from 'types/network'; export interface TransactionSucceededProps { txHash: string; diff --git a/common/components/SendButtonFactory/OfflineBroadcast.tsx b/common/components/SendButtonFactory/OfflineBroadcast.tsx index d8fdce92..178f5efa 100644 --- a/common/components/SendButtonFactory/OfflineBroadcast.tsx +++ b/common/components/SendButtonFactory/OfflineBroadcast.tsx @@ -4,7 +4,7 @@ import { AppState } from 'reducers'; import { getOffline } from 'selectors/config'; interface StateProps { - offline: AppState['config']['offline']; + offline: AppState['config']['meta']['offline']; } class OfflineBroadcastClass extends Component { public render() { diff --git a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx index 17b89254..61885f9b 100644 --- a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx +++ b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx @@ -16,13 +16,14 @@ import SimpleGas from './components/SimpleGas'; import AdvancedGas, { AdvancedOptions } from './components/AdvancedGas'; import './TXMetaDataPanel.scss'; import { getGasPrice } from 'selectors/transaction'; +import { NetworkConfig } from 'types/network'; type SliderStates = 'simple' | 'advanced'; interface StateProps { gasPrice: AppState['transaction']['fields']['gasPrice']; - offline: AppState['config']['offline']; - network: AppState['config']['network']; + offline: AppState['config']['meta']['offline']; + network: NetworkConfig; } interface DispatchProps { diff --git a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx index 0e58a33f..7cdd33e2 100644 --- a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx +++ b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx @@ -27,7 +27,7 @@ interface OwnProps { } interface StateProps { - autoGasLimitEnabled: AppState['config']['autoGasLimit']; + autoGasLimitEnabled: AppState['config']['meta']['autoGasLimit']; validGasPrice: boolean; } diff --git a/common/components/TXMetaDataPanel/components/FeeSummary.tsx b/common/components/TXMetaDataPanel/components/FeeSummary.tsx index 2afc4319..fc42c074 100644 --- a/common/components/TXMetaDataPanel/components/FeeSummary.tsx +++ b/common/components/TXMetaDataPanel/components/FeeSummary.tsx @@ -2,8 +2,9 @@ import React from 'react'; import BN from 'bn.js'; import { connect } from 'react-redux'; import { AppState } from 'reducers'; -import { getNetworkConfig } from 'selectors/config'; +import { getNetworkConfig, getOffline } from 'selectors/config'; import { UnitDisplay } from 'components/ui'; +import { NetworkConfig } from 'types/network'; import './FeeSummary.scss'; interface RenderData { @@ -19,8 +20,8 @@ interface Props { gasPrice: AppState['transaction']['fields']['gasPrice']; gasLimit: AppState['transaction']['fields']['gasLimit']; rates: AppState['rates']['rates']; - network: AppState['config']['network']; - isOffline: AppState['config']['offline']; + network: NetworkConfig; + isOffline: AppState['config']['meta']['offline']; // Component props render(data: RenderData): React.ReactElement | string; } @@ -73,7 +74,7 @@ function mapStateToProps(state: AppState) { gasLimit: state.transaction.fields.gasLimit, rates: state.rates.rates, network: getNetworkConfig(state), - isOffline: state.config.offline + isOffline: getOffline(state) }; } diff --git a/common/components/UnitDropDown/UnitDropDown.tsx b/common/components/UnitDropDown/UnitDropDown.tsx index 389f18d4..4119f357 100644 --- a/common/components/UnitDropDown/UnitDropDown.tsx +++ b/common/components/UnitDropDown/UnitDropDown.tsx @@ -8,6 +8,7 @@ import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { getUnit } from 'selectors/transaction'; import { getNetworkConfig } from 'selectors/config'; +import { NetworkConfig } from 'types/network'; interface DispatchProps { setUnitMeta: TSetUnitMeta; @@ -18,7 +19,7 @@ interface StateProps { tokens: TokenBalance[]; allTokens: MergedToken[]; showAllTokens?: boolean; - network: AppState['config']['network']; + network: NetworkConfig; } const StringDropdown = Dropdown as new () => Dropdown; diff --git a/common/components/WalletDecrypt/WalletDecrypt.tsx b/common/components/WalletDecrypt/WalletDecrypt.tsx index d0a330c9..8f55cde9 100644 --- a/common/components/WalletDecrypt/WalletDecrypt.tsx +++ b/common/components/WalletDecrypt/WalletDecrypt.tsx @@ -45,11 +45,10 @@ import { InsecureWalletName, MiscWalletName, WalletName, - isWeb3NodeAvailable, knowledgeBaseURL } from 'config'; import { unSupportedWalletFormatsOnNetwork } from 'utils/network'; -import { getNetworkConfig } from '../../selectors/config'; +import { getNetworkConfig, getOffline } from '../../selectors/config'; interface OwnProps { hidden?: boolean; @@ -443,7 +442,7 @@ function mapStateToProps(state: AppState, ownProps: Props) { : networkDisabledFormats; return { computedDisabledWallets, - offline: state.config.offline, + offline: getOffline(state), isWalletPending: state.wallet.isWalletPending, isPasswordPending: state.wallet.isPasswordPending }; diff --git a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx index a0b1aef3..fddf4716 100644 --- a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx +++ b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx @@ -8,7 +8,6 @@ import { } from 'actions/deterministicWallets'; import Modal, { IButton } from 'components/ui/Modal'; import { AppState } from 'reducers'; -import { NetworkConfig } from 'config'; import { isValidPath } from 'libs/validators'; import React from 'react'; import { connect } from 'react-redux'; @@ -16,7 +15,7 @@ import { getNetworkConfig } from 'selectors/config'; import { getTokens, MergedToken } from 'selectors/wallet'; import { UnitDisplay } from 'components/ui'; import './DeterministicWalletsModal.scss'; -import { DPath } from 'config/dpaths'; +import { StaticNetworkConfig } from 'types/network'; import Select from 'react-select'; const WALLETS_PER_PAGE = 5; @@ -34,7 +33,7 @@ interface Props { // Redux state wallets: AppState['deterministicWallets']['wallets']; desiredToken: AppState['deterministicWallets']['desiredToken']; - network: NetworkConfig; + network: StaticNetworkConfig; tokens: MergedToken[]; // Redux actions diff --git a/common/components/WalletDecrypt/components/LedgerNano.tsx b/common/components/WalletDecrypt/components/LedgerNano.tsx index af7ef2c4..95a19396 100644 --- a/common/components/WalletDecrypt/components/LedgerNano.tsx +++ b/common/components/WalletDecrypt/components/LedgerNano.tsx @@ -9,7 +9,6 @@ import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { getNetworkConfig } from 'selectors/config'; import { SecureWalletName } from 'config'; -import { DPath } from 'config/dpaths'; import { getPaths, getSingleDPath } from 'utils/network'; interface OwnProps { diff --git a/common/components/WalletDecrypt/components/Mnemonic.tsx b/common/components/WalletDecrypt/components/Mnemonic.tsx index fdb5d2b3..fc658481 100644 --- a/common/components/WalletDecrypt/components/Mnemonic.tsx +++ b/common/components/WalletDecrypt/components/Mnemonic.tsx @@ -7,7 +7,6 @@ import { InsecureWalletName } from 'config'; import { AppState } from 'reducers'; import { getNetworkConfig } from 'selectors/config'; import { connect } from 'react-redux'; -import { DPath } from 'config/dpaths'; import { getPaths, getSingleDPath } from 'utils/network'; interface Props { diff --git a/common/components/WalletDecrypt/components/Trezor.tsx b/common/components/WalletDecrypt/components/Trezor.tsx index c74528f0..371fc700 100644 --- a/common/components/WalletDecrypt/components/Trezor.tsx +++ b/common/components/WalletDecrypt/components/Trezor.tsx @@ -9,7 +9,6 @@ import { getNetworkConfig } from 'selectors/config'; import { AppState } from 'reducers'; import { connect } from 'react-redux'; import { SecureWalletName } from 'config'; -import { DPath } from 'config/dpaths'; import { getPaths, getSingleDPath } from 'utils/network'; //todo: conflicts with comment in walletDecrypt -> onUnlock method diff --git a/common/components/ui/UnitDisplay.tsx b/common/components/ui/UnitDisplay.tsx index e6507287..f5942af8 100644 --- a/common/components/ui/UnitDisplay.tsx +++ b/common/components/ui/UnitDisplay.tsx @@ -85,7 +85,7 @@ export default UnitDisplay; * Circumvents typescript issue with union props on connected components. */ interface OfflineProps { - offline: AppState['config']['offline']; + offline: AppState['config']['meta']['offline']; children: React.ReactElement; } diff --git a/common/config/dpaths.ts b/common/config/dpaths.ts index c162025b..9b2c0a4c 100644 --- a/common/config/dpaths.ts +++ b/common/config/dpaths.ts @@ -1,8 +1,3 @@ -export interface DPath { - label: string; - value: string; // TODO determine method for more precise typing for path -} - export const ETH_DEFAULT: DPath = { label: 'Default (ETH)', value: "m/44'/60'/0'/0" diff --git a/common/config/index.ts b/common/config/index.ts index d64aae8e..5c19ba95 100644 --- a/common/config/index.ts +++ b/common/config/index.ts @@ -1,3 +1,2 @@ -export * from './networks'; export * from './data'; export * from './bity'; diff --git a/common/containers/TabSection/index.tsx b/common/containers/TabSection/index.tsx index 7c58fbd2..55277fb0 100644 --- a/common/containers/TabSection/index.tsx +++ b/common/containers/TabSection/index.tsx @@ -17,32 +17,21 @@ import { AlphaAgreement, Footer, Header } from 'components'; import { AppState } from 'reducers'; import Notifications from './Notifications'; import OfflineTab from './OfflineTab'; +import { + getOffline, + getLanguageSelection, + getCustomNodeConfigs, + getCustomNetworkConfigs, + getLatestBlock, + isNodeChanging +} from 'selectors/config'; +import { NodeConfig, CustomNodeConfig } from 'types/node'; +import { CustomNetworkConfig } from 'types/network'; -interface ReduxProps { - languageSelection: AppState['config']['languageSelection']; - node: AppState['config']['node']; - nodeSelection: AppState['config']['nodeSelection']; - isChangingNode: AppState['config']['isChangingNode']; - isOffline: AppState['config']['offline']; - customNodes: AppState['config']['customNodes']; - customNetworks: AppState['config']['customNetworks']; - latestBlock: AppState['config']['latestBlock']; -} - -interface ActionProps { - changeLanguage: TChangeLanguage; - changeNodeIntent: TChangeNodeIntent; - addCustomNode: TAddCustomNode; - removeCustomNode: TRemoveCustomNode; - addCustomNetwork: TAddCustomNetwork; - setGasPriceField: TSetGasPriceField; -} - -type Props = { +interface Props { isUnavailableOffline?: boolean; children: string | React.ReactElement | React.ReactElement[]; -} & ReduxProps & - ActionProps; +} class TabSection extends Component { public render() { @@ -50,38 +39,9 @@ class TabSection extends Component { isUnavailableOffline, children, // APP - node, - nodeSelection, - isChangingNode, - isOffline, - languageSelection, - customNodes, - customNetworks, - latestBlock, - setGasPriceField, - changeLanguage, - changeNodeIntent, - addCustomNode, - removeCustomNode, - addCustomNetwork + isOffline } = this.props; - const headerProps = { - languageSelection, - node, - nodeSelection, - isChangingNode, - isOffline, - customNodes, - customNetworks, - changeLanguage, - changeNodeIntent, - setGasPriceField, - addCustomNode, - removeCustomNode, - addCustomNetwork - }; - return (
@@ -102,20 +62,13 @@ function mapStateToProps(state: AppState): ReduxProps { return { node: state.config.node, nodeSelection: state.config.nodeSelection, - isChangingNode: state.config.isChangingNode, - isOffline: state.config.offline, - languageSelection: state.config.languageSelection, - customNodes: state.config.customNodes, - customNetworks: state.config.customNetworks, - latestBlock: state.config.latestBlock + isChangingNode: isNodeChanging(state), + isOffline: getOffline(state), + languageSelection: getLanguageSelection(state), + customNodes: getCustomNodeConfigs(state), + customNetworks: getCustomNetworkConfigs(state), + latestBlock: getLatestBlock(state) }; } -export default connect(mapStateToProps, { - setGasPriceField: dSetGasPriceField, - changeLanguage: dChangeLanguage, - changeNodeIntent: dChangeNodeIntent, - addCustomNode: dAddCustomNode, - removeCustomNode: dRemoveCustomNode, - addCustomNetwork: dAddCustomNetwork -})(TabSection); +export default connect(mapStateToProps, {})(TabSection); diff --git a/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/index.tsx b/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/index.tsx index 15cf7981..8e6f05c6 100644 --- a/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/index.tsx +++ b/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/index.tsx @@ -4,7 +4,6 @@ import './InteractExplorer.scss'; import { TShowNotification, showNotification } from 'actions/notifications'; import { getNodeLib } from 'selectors/config'; import { getTo, getDataExists } from 'selectors/transaction'; -import { INode } from 'libs/nodes/INode'; import { GenerateTransaction } from 'components/GenerateTransaction'; import { AppState } from 'reducers'; import { connect } from 'react-redux'; @@ -12,9 +11,11 @@ import { Fields } from './components'; import { setDataField, TSetDataField } from 'actions/transaction'; import { Data } from 'libs/units'; import Select from 'react-select'; +import { Web3Node } from 'libs/nodes'; +import RpcNode from 'libs/nodes/rpc'; interface StateProps { - nodeLib: INode; + nodeLib: RpcNode | Web3Node; to: AppState['transaction']['fields']['to']; dataExists: boolean; } diff --git a/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx b/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx index f6d00aa9..00bc1f7a 100644 --- a/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx +++ b/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx @@ -1,12 +1,12 @@ import React, { Component } from 'react'; import translate from 'translations'; -import { NetworkContract } from 'config'; import { getNetworkContracts } from 'selectors/config'; import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { isValidETHAddress, isValidAbiJson } from 'libs/validators'; import classnames from 'classnames'; import Select from 'react-select'; +import { NetworkContract } from 'types/network'; interface ContractOption { name: string; diff --git a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx index 8c54567f..3579a5f8 100644 --- a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx +++ b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx @@ -12,7 +12,6 @@ import { ICurrentValue } from 'selectors/transaction/current'; import BN from 'bn.js'; -import { NetworkConfig } from 'config'; import { validNumber, validDecimal } from 'libs/validators'; import { getGasLimit } from 'selectors/transaction'; import { AddressField, AmountField, TXMetaDataPanel } from 'components'; @@ -21,6 +20,7 @@ import { buildEIP681EtherRequest, buildEIP681TokenRequest } from 'libs/values'; import { getNetworkConfig, getSelectedTokenContractAddress } from 'selectors/config'; import './RequestPayment.scss'; import { reset, TReset, setCurrentTo, TSetCurrentTo } from 'actions/transaction'; +import { NetworkConfig } from 'types/network'; interface OwnProps { wallet: AppState['wallet']['inst']; @@ -31,7 +31,7 @@ interface StateProps { currentTo: ICurrentTo; currentValue: ICurrentValue; gasLimit: SetGasLimitFieldAction['payload']; - networkConfig: NetworkConfig | undefined; + networkConfig: NetworkConfig; decimal: number; tokenContractAddress: string; } diff --git a/common/containers/Tabs/SendTransaction/index.tsx b/common/containers/Tabs/SendTransaction/index.tsx index e0954a60..a32b8afc 100644 --- a/common/containers/Tabs/SendTransaction/index.tsx +++ b/common/containers/Tabs/SendTransaction/index.tsx @@ -17,6 +17,7 @@ import SubTabs, { Tab } from 'components/SubTabs'; import { getNetworkConfig } from 'selectors/config'; import { isNetworkUnit } from 'utils/network'; import { RouteNotFound } from 'components/RouteNotFound'; +import { NetworkConfig } from 'types/network'; const Send = () => ( @@ -27,7 +28,7 @@ const Send = () => ( interface StateProps { wallet: AppState['wallet']['inst']; - network: AppState['config']['network']; + network: NetworkConfig; } type Props = StateProps & RouteComponentProps<{}>; diff --git a/common/containers/Tabs/Swap/components/LiteSend/LiteSend.tsx b/common/containers/Tabs/Swap/components/LiteSend/LiteSend.tsx index 08491a93..cbebcdd4 100644 --- a/common/containers/Tabs/Swap/components/LiteSend/LiteSend.tsx +++ b/common/containers/Tabs/Swap/components/LiteSend/LiteSend.tsx @@ -8,7 +8,7 @@ import { configureLiteSend, TConfigureLiteSend } from 'actions/swap'; import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { shouldDisplayLiteSend } from 'selectors/swap'; -import { NetworkConfig } from 'config'; +import { NetworkConfig } from 'types/network'; interface DispatchProps { configureLiteSend: TConfigureLiteSend; diff --git a/common/containers/Tabs/Swap/index.tsx b/common/containers/Tabs/Swap/index.tsx index af51b987..d2ccda4c 100644 --- a/common/containers/Tabs/Swap/index.tsx +++ b/common/containers/Tabs/Swap/index.tsx @@ -56,6 +56,7 @@ import TabSection from 'containers/TabSection'; import { merge } from 'lodash'; import { RouteNotFound } from 'components/RouteNotFound'; import { Switch, Route, RouteComponentProps } from 'react-router'; +import { getOffline } from 'selectors/config'; interface ReduxStateProps { step: number; @@ -286,7 +287,7 @@ function mapStateToProps(state: AppState) { bityOrderStatus: state.swap.bityOrderStatus, shapeshiftOrderStatus: state.swap.shapeshiftOrderStatus, paymentAddress: state.swap.paymentAddress, - isOffline: state.config.offline + isOffline: getOffline(state) }; } diff --git a/common/libs/nodes/INode.ts b/common/libs/nodes/INode.ts index 2d29b87d..a2064e71 100644 --- a/common/libs/nodes/INode.ts +++ b/common/libs/nodes/INode.ts @@ -1,6 +1,6 @@ -import { Token } from 'config'; import { Wei, TokenValue } from 'libs/units'; import { IHexStrTransaction } from 'libs/transaction'; +import { Token } from 'types/network'; export interface TxObj { to: string; diff --git a/common/libs/nodes/custom/index.ts b/common/libs/nodes/custom/index.ts index 91f9d9ca..9ee49ad2 100644 --- a/common/libs/nodes/custom/index.ts +++ b/common/libs/nodes/custom/index.ts @@ -1,6 +1,6 @@ import RPCNode from '../rpc'; import RPCClient from '../rpc/client'; -import { CustomNodeConfig } from 'config'; +import { CustomNodeConfig } from 'types/node'; export default class CustomNode extends RPCNode { constructor(config: CustomNodeConfig) { diff --git a/common/libs/nodes/etherscan/requests.ts b/common/libs/nodes/etherscan/requests.ts index 96e0a1d0..6fda0377 100644 --- a/common/libs/nodes/etherscan/requests.ts +++ b/common/libs/nodes/etherscan/requests.ts @@ -1,4 +1,3 @@ -import { Token } from 'config'; import ERC20 from 'libs/erc20'; import RPCRequests from '../rpc/requests'; import { @@ -10,6 +9,7 @@ import { SendRawTxRequest, GetCurrentBlockRequest } from './types'; +import { Token } from 'types/network'; export default class EtherscanRequests extends RPCRequests { public sendRawTx(signedTx: string): SendRawTxRequest { diff --git a/common/libs/nodes/rpc/index.ts b/common/libs/nodes/rpc/index.ts index 8bb52f68..3b6a1674 100644 --- a/common/libs/nodes/rpc/index.ts +++ b/common/libs/nodes/rpc/index.ts @@ -1,5 +1,4 @@ import BN from 'bn.js'; -import { Token } from 'config'; import { IHexStrTransaction } from 'libs/transaction'; import { Wei, TokenValue } from 'libs/units'; import { stripHexPrefix } from 'libs/values'; @@ -15,6 +14,7 @@ import { isValidCurrentBlock, isValidRawTxApi } from '../../validators'; +import { Token } from 'types/network'; export default class RpcNode implements INode { public client: RPCClient; diff --git a/common/libs/nodes/rpc/requests.ts b/common/libs/nodes/rpc/requests.ts index 3db0bb17..1d1c8d4f 100644 --- a/common/libs/nodes/rpc/requests.ts +++ b/common/libs/nodes/rpc/requests.ts @@ -1,4 +1,3 @@ -import { Token } from 'config'; import ERC20 from 'libs/erc20'; import { CallRequest, @@ -11,6 +10,8 @@ import { } from './types'; import { hexEncodeData } from './utils'; import { TxObj } from '../INode'; +import { Token } from 'types/network'; + export default class RPCRequests { public getNetVersion() { return { method: 'net_version' }; diff --git a/common/libs/values.ts b/common/libs/values.ts index a7673753..b10cb951 100644 --- a/common/libs/values.ts +++ b/common/libs/values.ts @@ -1,7 +1,7 @@ import { Wei, toTokenBase } from 'libs/units'; import { addHexPrefix } from 'ethereumjs-util'; import BN from 'bn.js'; -import { NetworkKeys } from 'config'; +import { StaticNetworkNames } from 'types/network'; export function stripHexPrefix(value: string) { return value.replace('0x', ''); @@ -24,7 +24,7 @@ export function sanitizeHex(hex: string) { return hex !== '' ? `0x${padLeftEven(hexStr)}` : ''; } -export function networkIdToName(networkId: string | number): NetworkKeys { +export function networkIdToName(networkId: string | number): StaticNetworkNames { switch (networkId.toString()) { case '1': return 'ETH'; diff --git a/common/libs/wallet/non-deterministic/web3.ts b/common/libs/wallet/non-deterministic/web3.ts index 2db1d939..af844763 100644 --- a/common/libs/wallet/non-deterministic/web3.ts +++ b/common/libs/wallet/non-deterministic/web3.ts @@ -29,6 +29,9 @@ export default class Web3Wallet implements IFullWallet { const state = configuredStore.getState(); const nodeLib: Web3Node | INode = getNodeLib(state); + if (!nodeLib) { + throw new Error(''); + } if (!isWeb3Node(nodeLib)) { throw new Error('Web3 wallets can only be used with a Web3 node.'); } @@ -55,7 +58,7 @@ export default class Web3Wallet implements IFullWallet { }; const state = configuredStore.getState(); - const nodeLib: Web3Node | INode = getNodeLib(state); + const nodeLib: Web3Node | INode | undefined = getNodeLib(state); if (!isWeb3Node(nodeLib)) { throw new Error('Web3 wallets can only be used with a Web3 node.'); diff --git a/common/reducers/config/networks/customNetworks.ts b/common/reducers/config/networks/customNetworks.ts index d9712c4d..fb49972c 100644 --- a/common/reducers/config/networks/customNetworks.ts +++ b/common/reducers/config/networks/customNetworks.ts @@ -4,7 +4,7 @@ import { CustomNetworkAction, TypeKeys } from 'actions/config'; -import { CustomNetworkConfig } from 'reducers/config/networks/typings'; +import { CustomNetworkConfig } from 'types/network'; // TODO: this doesn't accurately represent state, as export interface State { diff --git a/common/reducers/config/networks/index.ts b/common/reducers/config/networks/index.ts index 0338e3e1..c4a6b49e 100644 --- a/common/reducers/config/networks/index.ts +++ b/common/reducers/config/networks/index.ts @@ -1,16 +1,18 @@ import { customNetworks, State as CustomNetworksState } from './customNetworks'; -import { defaultNetworks, State as DefaultNetworksState } from './defaultNetworks'; +import { staticNetworks, State as StaticNetworksState } from './staticNetworks'; import { selectedNetwork, State as SelectedNetworkState } from './selectedNetwork'; import { combineReducers } from 'redux'; -export interface State { +interface State { customNetworks: CustomNetworksState; - defaultNetworks: DefaultNetworksState; + staticNetworks: StaticNetworksState; selectedNetwork: SelectedNetworkState; } -export const networks = combineReducers({ +const networks = combineReducers({ customNetworks, - defaultNetworks, + staticNetworks, selectedNetwork }); + +export { State, networks, StaticNetworksState, SelectedNetworkState, CustomNetworksState }; diff --git a/common/reducers/config/networks/selectedNetwork.ts b/common/reducers/config/networks/selectedNetwork.ts index 8dfc9888..7b4b0485 100644 --- a/common/reducers/config/networks/selectedNetwork.ts +++ b/common/reducers/config/networks/selectedNetwork.ts @@ -1,14 +1,14 @@ import { NodeAction, TypeKeys, ChangeNodeAction } from 'actions/config'; -import { DefaultNetworkNames } from 'reducers/config/networks/typings'; import { INITIAL_STATE as INITIAL_NODE_STATE } from '../nodes/selectedNode'; // could probably consolidate this in the index file of 'nodes' to make it easier to import -import { INITIAL_STATE as INITIAL_DEFAULT_NODE_STATE } from '../nodes/defaultNodes'; -import { NonWeb3NodeConfigs } from 'reducers/config/nodes/typings'; +import { INITIAL_STATE as INITIAL_DEFAULT_NODE_STATE } from '../nodes/staticNodes'; +import { NonWeb3NodeConfigs } from 'types/node'; +import { StaticNetworkNames } from 'types/network'; const initalNode = INITIAL_DEFAULT_NODE_STATE[INITIAL_NODE_STATE.nodeName as keyof NonWeb3NodeConfigs]; -export type State = string | DefaultNetworkNames; -const INITIAL_STATE: State = initalNode.networkName; +export type State = string | StaticNetworkNames; +const INITIAL_STATE: State = initalNode.network; const handleNodeChange = (_: State, { payload }: ChangeNodeAction) => payload.networkName; diff --git a/common/reducers/config/networks/defaultNetworks.ts b/common/reducers/config/networks/staticNetworks.ts similarity index 90% rename from common/reducers/config/networks/defaultNetworks.ts rename to common/reducers/config/networks/staticNetworks.ts index a38dcf2b..92aa91e5 100644 --- a/common/reducers/config/networks/defaultNetworks.ts +++ b/common/reducers/config/networks/staticNetworks.ts @@ -9,14 +9,10 @@ import { EXP_DEFAULT, UBQ_DEFAULT } from 'config/dpaths'; -import { - DefaultNetworkConfig, - BlockExplorerConfig, - DefaultNetworkNames -} from 'reducers/config/networks/typings'; import { ConfigAction } from 'actions/config'; +import { StaticNetworkNames, StaticNetworkConfig, BlockExplorerConfig } from 'types/network'; -export type State = { [key in DefaultNetworkNames]: DefaultNetworkConfig }; +export type State = { [key in StaticNetworkNames]: StaticNetworkConfig }; // Must be a website that follows the ethplorer convention of /tx/[hash] and // address/[address] to generate the correct functions. @@ -34,6 +30,7 @@ const INITIAL_STATE: State = { name: 'ETH', unit: 'ETH', chainId: 1, + isCustom: false, color: '#0e97c0', blockExplorer: makeExplorer('https://etherscan.io'), tokenExplorer: { @@ -52,6 +49,7 @@ const INITIAL_STATE: State = { name: 'Ropsten', unit: 'ETH', chainId: 3, + isCustom: false, color: '#adc101', blockExplorer: makeExplorer('https://ropsten.etherscan.io'), tokens: require('./tokens/ropsten.json'), @@ -67,6 +65,7 @@ const INITIAL_STATE: State = { name: 'Kovan', unit: 'ETH', chainId: 42, + isCustom: false, color: '#adc101', blockExplorer: makeExplorer('https://kovan.etherscan.io'), tokens: require('./tokens/ropsten.json'), @@ -82,6 +81,7 @@ const INITIAL_STATE: State = { name: 'Rinkeby', unit: 'ETH', chainId: 4, + isCustom: false, color: '#adc101', blockExplorer: makeExplorer('https://rinkeby.etherscan.io'), tokens: require('./tokens/rinkeby.json'), @@ -97,6 +97,7 @@ const INITIAL_STATE: State = { name: 'ETC', unit: 'ETC', chainId: 61, + isCustom: false, color: '#669073', blockExplorer: makeExplorer('https://gastracker.io'), tokens: require('./tokens/etc.json'), @@ -111,6 +112,7 @@ const INITIAL_STATE: State = { name: 'UBQ', unit: 'UBQ', chainId: 8, + isCustom: false, color: '#b37aff', blockExplorer: makeExplorer('https://ubiqscan.io/en'), tokens: require('./tokens/ubq.json'), @@ -125,6 +127,7 @@ const INITIAL_STATE: State = { name: 'EXP', unit: 'EXP', chainId: 2, + isCustom: false, color: '#673ab7', blockExplorer: makeExplorer('http://www.gander.tech'), tokens: require('./tokens/exp.json'), @@ -137,7 +140,7 @@ const INITIAL_STATE: State = { } }; -export const defaultNetworks = (state: State = INITIAL_STATE, action: ConfigAction) => { +export const staticNetworks = (state: State = INITIAL_STATE, action: ConfigAction) => { switch (action.type) { default: return state; diff --git a/common/reducers/config/nodes/customNodes.ts b/common/reducers/config/nodes/customNodes.ts index 58a04638..f424af1b 100644 --- a/common/reducers/config/nodes/customNodes.ts +++ b/common/reducers/config/nodes/customNodes.ts @@ -1,10 +1,10 @@ -import { CustomNodeConfig } from 'reducers/config/nodes/typings'; import { TypeKeys, CustomNodeAction, AddCustomNodeAction, RemoveCustomNodeAction } from 'actions/config'; +import { CustomNodeConfig } from 'types/node'; export interface State { [customNodeId: string]: CustomNodeConfig; diff --git a/common/reducers/config/nodes/index.ts b/common/reducers/config/nodes/index.ts index bc9b24c7..07fdebea 100644 --- a/common/reducers/config/nodes/index.ts +++ b/common/reducers/config/nodes/index.ts @@ -1,12 +1,14 @@ -import { customNodes, State as CustomNodeState } from './customNodes'; -import { defaultNodes, State as DefaultNodeState } from './defaultNodes'; +import { customNodes, State as CustomNodesState } from './customNodes'; +import { staticNodes, State as StaticNodesState } from './staticNodes'; import { selectedNode, State as SelectedNodeState } from './selectedNode'; import { combineReducers } from 'redux'; -export interface State { - customNodes: CustomNodeState; - defaultNodes: DefaultNodeState; +interface State { + customNodes: CustomNodesState; + staticNodes: StaticNodesState; selectedNode: SelectedNodeState; } -export const nodes = combineReducers({ customNodes, defaultNodes, selectedNode }); +const nodes = combineReducers({ customNodes, staticNodes, selectedNode }); + +export { State, nodes, CustomNodesState, StaticNodesState, SelectedNodeState }; diff --git a/common/reducers/config/nodes/defaultNodes.ts b/common/reducers/config/nodes/staticNodes.ts similarity index 79% rename from common/reducers/config/nodes/defaultNodes.ts rename to common/reducers/config/nodes/staticNodes.ts index b1be9ae3..3ef4c7ef 100644 --- a/common/reducers/config/nodes/defaultNodes.ts +++ b/common/reducers/config/nodes/staticNodes.ts @@ -1,85 +1,85 @@ -import { NonWeb3NodeConfigs, Web3NodeConfig } from 'reducers/config/nodes/typings'; import { EtherscanNode, InfuraNode, RPCNode } from 'libs/nodes'; import { ConfigAction } from 'actions/config'; +import { Web3NodeConfig, NonWeb3NodeConfigs } from 'types/node'; export type State = NonWeb3NodeConfigs & Web3NodeConfig; export const INITIAL_STATE: State = { eth_mew: { - networkName: 'ETH', + network: 'ETH', lib: new RPCNode('https://api.myetherapi.com/eth'), service: 'MyEtherWallet', estimateGas: true }, eth_mycrypto: { - networkName: 'ETH', + network: 'ETH', lib: new RPCNode('https://api.mycryptoapi.com/eth'), service: 'MyCrypto', estimateGas: true }, eth_ethscan: { - networkName: 'ETH', + network: 'ETH', service: 'Etherscan.io', lib: new EtherscanNode('https://api.etherscan.io/api'), estimateGas: false }, eth_infura: { - networkName: 'ETH', + network: 'ETH', service: 'infura.io', lib: new InfuraNode('https://mainnet.infura.io/mew'), estimateGas: false }, rop_mew: { - networkName: 'Ropsten', + network: 'Ropsten', service: 'MyEtherWallet', lib: new RPCNode('https://api.myetherapi.com/rop'), estimateGas: false }, rop_infura: { - networkName: 'Ropsten', + network: 'Ropsten', service: 'infura.io', lib: new InfuraNode('https://ropsten.infura.io/mew'), estimateGas: false }, kov_ethscan: { - networkName: 'Kovan', + network: 'Kovan', service: 'Etherscan.io', lib: new EtherscanNode('https://kovan.etherscan.io/api'), estimateGas: false }, rin_ethscan: { - networkName: 'Rinkeby', + network: 'Rinkeby', service: 'Etherscan.io', lib: new EtherscanNode('https://rinkeby.etherscan.io/api'), estimateGas: false }, rin_infura: { - networkName: 'Rinkeby', + network: 'Rinkeby', service: 'infura.io', lib: new InfuraNode('https://rinkeby.infura.io/mew'), estimateGas: false }, etc_epool: { - networkName: 'ETC', + network: 'ETC', service: 'Epool.io', lib: new RPCNode('https://mewapi.epool.io'), estimateGas: false }, ubq: { - networkName: 'UBQ', + network: 'UBQ', service: 'ubiqscan.io', lib: new RPCNode('https://pyrus2.ubiqscan.io'), estimateGas: true }, exp_tech: { - networkName: 'EXP', + network: 'EXP', service: 'Expanse.tech', lib: new RPCNode('https://node.expanse.tech/'), estimateGas: true } }; -export const defaultNodes = (state: State = INITIAL_STATE, action: ConfigAction) => { +export const staticNodes = (state: State = INITIAL_STATE, action: ConfigAction) => { switch (action.type) { default: return state; diff --git a/common/reducers/config/nodes/typings.ts b/common/reducers/config/nodes/typings.ts index 470e0b61..471496e9 100644 --- a/common/reducers/config/nodes/typings.ts +++ b/common/reducers/config/nodes/typings.ts @@ -1,46 +1,5 @@ -import { RPCNode, Web3Node } from 'libs/nodes'; +import { Web3Node } from 'libs/nodes'; import { networkIdToName } from 'libs/values'; -import { DefaultNetworkNames } from 'reducers/config/networks/typings'; - -export interface CustomNodeConfig { - name: string; - url: string; - port: number; - network: string; - auth?: { - username: string; - password: string; - }; -} - -export interface DefaultNodeConfig { - networkName: DefaultNetworkNames; - lib: RPCNode | Web3Node; - service: string; - estimateGas?: boolean; - hidden?: boolean; -} - -export enum DefaultNodeName { - ETH_MEW = 'eth_mew', - ETH_MYCRYPTO = 'eth_mycrypto', - ETH_ETHSCAN = 'eth_ethscan', - ETH_INFURA = 'eth_infura', - ROP_MEW = 'rop_mew', - ROP_INFURA = 'rop_infura', - KOV_ETHSCAN = 'kov_ethscan', - RIN_ETHSCAN = 'rin_ethscan', - RIN_INFURA = 'rin_infura', - ETC_EPOOL = 'etc_epool', - UBQ = 'ubq', - EXP_TECH = 'exp_tech' -} - -export type NonWeb3NodeConfigs = { [key in DefaultNodeName]: DefaultNodeConfig }; - -export interface Web3NodeConfig { - web3?: DefaultNodeConfig; -} /** * TODO: Put this in a saga that runs on app mount @@ -85,13 +44,9 @@ export async function isWeb3NodeAvailable(): Promise { export const Web3Service = 'MetaMask / Mist'; -export interface NodeConfigOverride extends DefaultNodeConfig { - networkName: any; -} - export async function initWeb3Node(): Promise { const { networkId, lib } = await setupWeb3Node(); - const web3: NodeConfigOverride = { + const web3 = { network: networkIdToName(networkId), service: Web3Service, lib, diff --git a/common/reducers/customTokens.ts b/common/reducers/customTokens.ts index 3ebca005..23780834 100644 --- a/common/reducers/customTokens.ts +++ b/common/reducers/customTokens.ts @@ -4,7 +4,7 @@ import { RemoveCustomTokenAction } from 'actions/customTokens'; import { TypeKeys } from 'actions/customTokens/constants'; -import { Token } from 'config'; +import { Token } from 'types/network'; export type State = Token[]; diff --git a/common/sagas/config.ts b/common/sagas/config.ts index 2c72d3c1..90fa0fce 100644 --- a/common/sagas/config.ts +++ b/common/sagas/config.ts @@ -10,14 +10,6 @@ import { select, race } from 'redux-saga/effects'; -import { - NODES, - NETWORKS, - NodeConfig, - CustomNodeConfig, - CustomNetworkConfig, - Web3Service -} from 'config'; import { makeCustomNodeId, getCustomNodeConfigFromId, @@ -47,13 +39,15 @@ import { translateRaw } from 'translations'; import { Web3Wallet } from 'libs/wallet'; import { TypeKeys as WalletTypeKeys } from 'actions/wallet/constants'; import { State as ConfigState, INITIAL_STATE as configInitialState } from 'reducers/config'; +import { StaticNodeConfig, CustomNodeConfig } from 'types/node'; +import { CustomNetworkConfig } from 'types/network'; export const getConfig = (state: AppState): ConfigState => state.config; let hasCheckedOnline = false; export function* pollOfflineStatus(): SagaIterator { while (true) { - const node: NodeConfig = yield select(getNodeConfig); + const node: StaticNodeConfig = yield select(getNodeConfig); const isOffline: boolean = yield select(getOffline); // If our offline state disagrees with the browser, run a check @@ -121,7 +115,7 @@ export function* reload(): SagaIterator { export function* handleNodeChangeIntent(action: ChangeNodeIntentAction): SagaIterator { const currentNode: string = yield select(getNodeName); - const currentConfig: NodeConfig = yield select(getNodeConfig); + const currentConfig: StaticNodeConfig = yield select(getNodeConfig); const customNets: CustomNetworkConfig[] = yield select(getCustomNetworkConfigs); const currentNetwork = getNetworkConfigFromId(currentConfig.network, customNets) || NETWORKS[currentConfig.network]; @@ -233,13 +227,13 @@ export function* unsetWeb3Node(): SagaIterator { return; } - const nodeConfig: NodeConfig = yield select(getNodeConfig); + const nodeConfig: StaticNodeConfig = yield select(getNodeConfig); const newNode = equivalentNodeOrDefault(nodeConfig); yield put(changeNodeIntent(newNode)); } -export const equivalentNodeOrDefault = (nodeConfig: NodeConfig) => { +export const equivalentNodeOrDefault = (nodeConfig: StaticNodeConfig) => { const node = Object.keys(NODES) .filter(key => key !== 'web3') .reduce((found, key) => { diff --git a/common/sagas/deterministicWallets.ts b/common/sagas/deterministicWallets.ts index a6818c6f..d4e7164b 100644 --- a/common/sagas/deterministicWallets.ts +++ b/common/sagas/deterministicWallets.ts @@ -5,7 +5,6 @@ import { updateDeterministicWallet } from 'actions/deterministicWallets'; import { showNotification } from 'actions/notifications'; -import { Token } from 'config'; import { publicToAddress, toChecksumAddress } from 'ethereumjs-util'; import HDKey from 'hdkey'; import { INode } from 'libs/nodes/INode'; @@ -16,6 +15,7 @@ import { getDesiredToken, getWallets } from 'selectors/deterministicWallets'; import { getTokens } from 'selectors/wallet'; import translate from 'translations'; import { TokenValue } from 'libs/units'; +import { Token } from 'types/network'; export function* getDeterministicWallets(action: GetDeterministicWalletsAction): SagaIterator { const { seed, dPath, publicKey, chainCode, limit, offset } = action.payload; diff --git a/common/sagas/transaction/signing/helpers.ts b/common/sagas/transaction/signing/helpers.ts index a13de4ec..9e06714b 100644 --- a/common/sagas/transaction/signing/helpers.ts +++ b/common/sagas/transaction/signing/helpers.ts @@ -12,9 +12,9 @@ import { TypeKeys as TK } from 'actions/transaction'; import Tx from 'ethereumjs-tx'; -import { NetworkConfig } from 'config'; import { SagaIterator } from 'redux-saga'; import { showNotification } from 'actions/notifications'; +import { StaticNetworkConfig } from 'types/network'; interface IFullWalletAndTransaction { wallet: IFullWallet; @@ -49,7 +49,7 @@ function* getWalletAndTransaction( throw Error('Could not get wallet instance to sign transaction'); } // get the chainId - const { chainId }: NetworkConfig = yield select(getNetworkConfig); + const { chainId }: StaticNetworkConfig = yield select(getNetworkConfig); // get the rest of the transaction parameters partialTx._chainId = chainId; diff --git a/common/sagas/wallet/helpers.ts b/common/sagas/wallet/helpers.ts index 65044417..6c2041c6 100644 --- a/common/sagas/wallet/helpers.ts +++ b/common/sagas/wallet/helpers.ts @@ -1,6 +1,5 @@ import { apply, select, call } from 'redux-saga/effects'; import { AppState } from 'reducers'; -import { Token } from 'config'; import { INode } from 'libs/nodes/INode'; import { IWallet, WalletConfig } from 'libs/wallet'; import { TokenBalance } from 'selectors/wallet'; @@ -8,6 +7,7 @@ import { getCustomTokens } from 'selectors/customTokens'; import { getNodeLib } from 'selectors/config'; import { loadWalletConfig } from 'utils/localStorage'; import { TokenBalanceLookup } from './wallet'; +import { Token } from 'types/network'; export function* getTokenBalances(wallet: IWallet, tokens: Token[]) { const node: INode = yield select(getNodeLib); diff --git a/common/sagas/wallet/wallet.ts b/common/sagas/wallet/wallet.ts index afff2ce5..7215fd09 100644 --- a/common/sagas/wallet/wallet.ts +++ b/common/sagas/wallet/wallet.ts @@ -36,7 +36,6 @@ import { Web3Wallet, WalletConfig } from 'libs/wallet'; -import { NODES, initWeb3Node, Token } from 'config'; import { SagaIterator, delay, Task } from 'redux-saga'; import { apply, call, fork, put, select, takeEvery, take, cancel } from 'redux-saga/effects'; import { getNodeLib, getAllTokens, getOffline } from 'selectors/config'; @@ -51,6 +50,7 @@ import translate from 'translations'; import Web3Node, { isWeb3Node } from 'libs/nodes/web3'; import { loadWalletConfig, saveWalletConfig } from 'utils/localStorage'; import { getTokenBalances, filterScannedTokenBalances } from './helpers'; +import { Token } from 'types/network'; export interface TokenBalanceLookup { [symbol: string]: TokenBalance; diff --git a/common/selectors/config/networks.ts b/common/selectors/config/networks.ts index c45793f7..578fe530 100644 --- a/common/selectors/config/networks.ts +++ b/common/selectors/config/networks.ts @@ -1,41 +1,50 @@ import { AppState } from 'reducers'; import { getConfig } from 'selectors/config'; import { - DefaultNetworkConfig, CustomNetworkConfig, - DefaultNetworkNames, + StaticNetworkConfig, + StaticNetworkNames, NetworkContract -} from 'reducers/config/networks/typings'; +} from 'types/network'; export const getNetworks = (state: AppState) => getConfig(state).networks; -export const isCurrentNetworkDefault = (state: AppState): DefaultNetworkConfig | undefined => { - const { defaultNetworks, selectedNetwork } = getNetworks(state); - const isDefaultNetworkName = (networkName: string): networkName is DefaultNetworkNames => - Object.keys(defaultNetworks).includes(networkName); +export const getStaticNetworkNames = (state: AppState): StaticNetworkNames[] => + Object.keys(getNetworks(state).staticNetworks) as StaticNetworkNames[]; + +export const getStaticNetworkConfig = (state: AppState): StaticNetworkConfig | undefined => { + const { staticNetworks, selectedNetwork } = getNetworks(state); + const isDefaultNetworkName = (networkName: string): networkName is StaticNetworkNames => + Object.keys(staticNetworks).includes(networkName); const defaultNetwork = isDefaultNetworkName(selectedNetwork) - ? defaultNetworks[selectedNetwork] + ? staticNetworks[selectedNetwork] : undefined; return defaultNetwork; }; -export const isCurrentNetworkCustom = (state: AppState): CustomNetworkConfig | undefined => { +export const getCustomNetworkConfig = (state: AppState): CustomNetworkConfig | undefined => { const { customNetworks, selectedNetwork } = getNetworks(state); const customNetwork = customNetworks[selectedNetwork]; return customNetwork; }; -export const getNetworkConfig = ( - state: AppState -): DefaultNetworkConfig | CustomNetworkConfig | undefined => - isCurrentNetworkDefault(state) || isCurrentNetworkCustom(state); +export const getNetworkConfig = (state: AppState): StaticNetworkConfig | CustomNetworkConfig => { + const config = getStaticNetworkConfig(state) || getCustomNetworkConfig(state); + + if (!config) { + const { selectedNetwork } = getNetworks(state); + throw Error( + `No network config found for ${selectedNetwork} in either static or custom networks` + ); + } + return config; +}; export const getNetworkContracts = (state: AppState): NetworkContract[] | null => { - const network = isCurrentNetworkDefault(state); + const network = getStaticNetworkConfig(state); return network ? network.contracts : []; }; -export const getCustomNetworkConfigs = (state: AppState): CustomNetworkConfig[] => { - const { customNetworks } = getNetworks(state); - return Object.values(customNetworks); -}; +export const getCustomNetworkConfigs = (state: AppState) => getNetworks(state).customNetworks; + +export const getStaticNetworkConfigs = (state: AppState) => getNetworks(state).staticNetworks; diff --git a/common/selectors/config/nodes.ts b/common/selectors/config/nodes.ts index 5da87d34..c66ba2b8 100644 --- a/common/selectors/config/nodes.ts +++ b/common/selectors/config/nodes.ts @@ -1,40 +1,43 @@ import { AppState } from 'reducers'; -import { getConfig } from 'selectors/config'; -import { - DefaultNodeConfig, - DefaultNodeName, - CustomNodeConfig -} from 'reducers/config/nodes/typings'; -import { INode } from 'libs/nodes/INode'; +import { getConfig, getStaticNetworkConfigs } from 'selectors/config'; +import { CustomNodeConfig, StaticNodeConfig, StaticNodeName } from 'types/node'; export const getNodes = (state: AppState) => getConfig(state).nodes; -export const isCurrentNodeDefault = (state: AppState): DefaultNodeConfig | undefined => { - const { defaultNodes, selectedNode: { nodeName } } = getNodes(state); +export const getStaticNodeConfig = (state: AppState): StaticNodeConfig | undefined => { + const { staticNodes, selectedNode: { nodeName } } = getNodes(state); if (nodeName === undefined) { return nodeName; } - const isDefaultNodeName = (networkName: string): networkName is DefaultNodeName => - Object.keys(defaultNodes).includes(networkName); + const isStaticNodeName = (networkName: string): networkName is StaticNodeName => + Object.keys(staticNodes).includes(networkName); - const defaultNetwork = isDefaultNodeName(nodeName) ? defaultNodes[nodeName] : undefined; + const defaultNetwork = isStaticNodeName(nodeName) ? staticNodes[nodeName] : undefined; return defaultNetwork; }; -export const isCurrentNetworkCustom = (state: AppState): CustomNodeConfig | undefined => { +export const getCustomNodeConfig = (state: AppState): CustomNodeConfig | undefined => { const { customNodes, selectedNode: { nodeName } } = getNodes(state); if (nodeName === undefined) { return nodeName; } - const customNetwork = customNodes[nodeName]; - return customNetwork; + const customNode = customNodes[nodeName]; + return customNode; }; -export function getCustomNodeConfigs(state: AppState): CustomNodeConfig[] { - return Object.values(getNodes(state).customNodes); +export function getCustomNodeConfigs(state: AppState) { + return getNodes(state).customNodes; +} + +export function getStaticNodes(state: AppState) { + return getNodes(state).staticNodes; +} + +export function isNodeChanging(state): boolean { + return getNodes(state).selectedNode.pending; } export function getNodeName(state: AppState): string | undefined { @@ -45,11 +48,45 @@ export function getIsWeb3Node(state: AppState): boolean { return getNodeName(state) === 'web3'; } -export function getNodeConfig(state: AppState): DefaultNodeConfig | CustomNodeConfig | undefined { - return isCurrentNodeDefault(state) || isCurrentNetworkCustom(state); +export function getNodeConfig(state: AppState): StaticNodeConfig | CustomNodeConfig | undefined { + const config = getStaticNodeConfig(state) || getCustomNodeConfig(state); + /* + if (!config) { + const { selectedNode } = getNodes(state); + throw Error( + `No node config found for ${selectedNode.nodeName} in either static or custom nodes` + ); + }*/ + return config; } -export function getNodeLib(state: AppState): INode | undefined { - const config = isCurrentNodeDefault(state); - return config ? config.lib : undefined; +export function getNodeLib(state: AppState) { + const config = getStaticNodeConfig(state); + if (!config) { + throw Error('No node lib found when trying to select from state'); + } + return config.lib; +} + +interface NodeOption { + value: string; + name: { networkName?: string; service: string }; + color?: string; + hidden?: boolean; +} + +export function getStaticNodeOptions(state: AppState) { + const staticNetworkConfigs = getStaticNetworkConfigs(state); + Object.entries(getStaticNodes(state)).map( + ([nodeName, nodeConfig]: [string, StaticNodeConfig]) => { + const networkName = nodeConfig.network; + const associatedNetwork = staticNetworkConfigs[networkName]; + return { + value: nodeName, + name: { networkName, service: nodeConfig.service }, + color: associatedNetwork.color, + hidden: nodeConfig.hidden + }; + } + ); } diff --git a/common/selectors/config/tokens.ts b/common/selectors/config/tokens.ts index 877b61e5..a26fd2eb 100644 --- a/common/selectors/config/tokens.ts +++ b/common/selectors/config/tokens.ts @@ -2,11 +2,11 @@ import { AppState } from 'reducers'; import { getUnit } from 'selectors/transaction/meta'; import { isEtherUnit } from 'libs/units'; import { SHAPESHIFT_TOKEN_WHITELIST } from 'api/shapeshift'; -import { isCurrentNetworkDefault } from 'selectors/config'; -import { Token } from 'reducers/config/networks/typings'; +import { getStaticNetworkConfig } from 'selectors/config'; +import { Token } from 'types/network'; export function getNetworkTokens(state: AppState): Token[] { - const network = isCurrentNetworkDefault(state); + const network = getStaticNetworkConfig(state); return network ? network.tokens : []; } diff --git a/common/selectors/wallet.ts b/common/selectors/wallet.ts index c3347b1d..c74f1349 100644 --- a/common/selectors/wallet.ts +++ b/common/selectors/wallet.ts @@ -1,9 +1,9 @@ import { TokenValue, Wei } from 'libs/units'; -import { Token } from 'config'; import { AppState } from 'reducers'; -import { getNetworkConfig } from 'selectors/config'; +import { getStaticNetworkConfig } from 'selectors/config'; import { IWallet, Web3Wallet, LedgerWallet, TrezorWallet, WalletConfig } from 'libs/wallet'; import { isEtherTransaction, getUnit } from './transaction'; +import { Token } from 'types/network'; export function getWalletInst(state: AppState): IWallet | null | undefined { return state.wallet.inst; @@ -30,7 +30,7 @@ export type MergedToken = Token & { }; export function getTokens(state: AppState): MergedToken[] { - const network = getNetworkConfig(state); + const network = getStaticNetworkConfig(state); const tokens: Token[] = network ? network.tokens : []; return tokens.concat( state.customTokens.map((token: Token) => { diff --git a/common/utils/network.ts b/common/utils/network.ts index 82e8291f..8b31b3da 100644 --- a/common/utils/network.ts +++ b/common/utils/network.ts @@ -1,29 +1,28 @@ -import { - CustomNetworkConfig, - DPathFormats, - InsecureWalletName, - NetworkConfig, - NETWORKS, - SecureWalletName, - WalletName, - walletNames -} from 'config'; -import { DPath, EXTRA_PATHS } from 'config/dpaths'; +import { InsecureWalletName, SecureWalletName, WalletName, walletNames } from 'config'; +import { EXTRA_PATHS } from 'config/dpaths'; import sortedUniq from 'lodash/sortedUniq'; import difference from 'lodash/difference'; +import { + CustomNetworkConfig, + StaticNetworkConfig, + NetworkConfig, + DPathFormats +} from 'types/network'; export function makeCustomNetworkId(config: CustomNetworkConfig): string { return config.chainId ? `${config.chainId}` : `${config.name}:${config.unit}`; } -export function makeNetworkConfigFromCustomConfig(config: CustomNetworkConfig): NetworkConfig { +export function makeNetworkConfigFromCustomConfig( + config: CustomNetworkConfig +): StaticNetworkConfig { // TODO - re-enable this block and classify customConfig after user-inputted dPaths are implemented // ------------------------------------------------- // this still provides the type safety we want // as we know config coming in is CustomNetworkConfig // meaning name will be a string // then we cast it as any to keep it as a network key - // interface Override extends NetworkConfig { + // interface Override extends StaticNetworkConfig { // name: any; // } // ------------------------------------------------- @@ -43,7 +42,7 @@ export function makeNetworkConfigFromCustomConfig(config: CustomNetworkConfig): export function getNetworkConfigFromId( id: string, configs: CustomNetworkConfig[] -): NetworkConfig | undefined { +): StaticNetworkConfig | undefined { if (NETWORKS[id]) { return NETWORKS[id]; } diff --git a/common/utils/node.ts b/common/utils/node.ts index 948f934f..3d558f23 100644 --- a/common/utils/node.ts +++ b/common/utils/node.ts @@ -1,5 +1,5 @@ import { CustomNode } from 'libs/nodes'; -import { NODES, NodeConfig, CustomNodeConfig } from 'config'; +import { CustomNodeConfig, StaticNodeConfig } from 'types/node'; export function makeCustomNodeId(config: CustomNodeConfig): string { return `${config.url}:${config.port}`; @@ -15,7 +15,7 @@ export function getCustomNodeConfigFromId( export function getNodeConfigFromId( id: string, configs: CustomNodeConfig[] -): NodeConfig | undefined { +): StaticNodeConfig | undefined { if (NODES[id]) { return NODES[id]; } @@ -26,8 +26,8 @@ export function getNodeConfigFromId( } } -export function makeNodeConfigFromCustomConfig(config: CustomNodeConfig): NodeConfig { - interface Override extends NodeConfig { +export function makeNodeConfigFromCustomConfig(config: CustomNodeConfig): StaticNodeConfig { + interface Override extends StaticNodeConfig { network: any; } diff --git a/common/utils/tokens.ts b/common/utils/tokens.ts index f39a482e..f092624f 100644 --- a/common/utils/tokens.ts +++ b/common/utils/tokens.ts @@ -1,4 +1,4 @@ -import { Token } from 'config'; +import { Token } from 'types/network'; export function dedupeCustomTokens(networkTokens: Token[], customTokens: Token[]): Token[] { if (!customTokens.length) { diff --git a/shared/types/hardware-wallets.d.ts b/shared/types/hardware-wallets.d.ts new file mode 100644 index 00000000..6f568370 --- /dev/null +++ b/shared/types/hardware-wallets.d.ts @@ -0,0 +1,4 @@ +interface DPath { + label: string; + value: string; // TODO determine method for more precise typing for path +} diff --git a/common/reducers/config/networks/typings.ts b/shared/types/network.d.ts similarity index 54% rename from common/reducers/config/networks/typings.ts rename to shared/types/network.d.ts index 201d5d93..f5f9dd7a 100644 --- a/common/reducers/config/networks/typings.ts +++ b/shared/types/network.d.ts @@ -1,35 +1,36 @@ -import { DPath } from 'config/dpaths'; +import { StaticNetworksState, CustomNetworksState } from 'reducers/config/networks'; -export type DefaultNetworkNames = 'ETH' | 'Ropsten' | 'Kovan' | 'Rinkeby' | 'ETC' | 'UBQ' | 'EXP'; +type StaticNetworkNames = 'ETH' | 'Ropsten' | 'Kovan' | 'Rinkeby' | 'ETC' | 'UBQ' | 'EXP'; -export interface BlockExplorerConfig { +interface BlockExplorerConfig { origin: string; txUrl(txHash: string): string; addressUrl(address: string): string; } -export interface Token { +interface Token { address: string; symbol: string; decimal: number; error?: string | null; } -export interface NetworkContract { - name: DefaultNetworkNames; +interface NetworkContract { + name: StaticNetworkNames; address?: string; abi: string; } -export interface DPathFormats { +interface DPathFormats { trezor: DPath; ledgerNanoS: DPath; mnemonicPhrase: DPath; } -export interface DefaultNetworkConfig { +interface StaticNetworkConfig { // TODO really try not to allow strings due to custom networks - name: DefaultNetworkNames; + isCustom: false; // used for type guards + name: StaticNetworkNames; unit: string; color?: string; blockExplorer?: BlockExplorerConfig; @@ -44,9 +45,13 @@ export interface DefaultNetworkConfig { isTestnet?: boolean; } -export interface CustomNetworkConfig { +interface CustomNetworkConfig { + isCustom: true; // used for type guards + isTestnet?: boolean; name: string; unit: string; chainId: number; dPathFormats: DPathFormats | null; } + +type NetworkConfig = StaticNetworksState[StaticNetworkNames] | CustomNetworksState[string]; diff --git a/shared/types/node.d.ts b/shared/types/node.d.ts new file mode 100644 index 00000000..72c64826 --- /dev/null +++ b/shared/types/node.d.ts @@ -0,0 +1,45 @@ +import { RPCNode, Web3Node } from 'libs/nodes'; +import { StaticNetworkNames } from './network'; +import { StaticNodesState, CustomNodesState } from 'reducers/config/nodes'; + +interface CustomNodeConfig { + name: string; + url: string; + port: number; + network: string; + auth?: { + username: string; + password: string; + }; +} + +interface StaticNodeConfig { + network: StaticNetworkNames; + lib: RPCNode | Web3Node; + service: string; + estimateGas?: boolean; + hidden?: boolean; +} + +declare enum StaticNodeName { + ETH_MEW = 'eth_mew', + ETH_MYCRYPTO = 'eth_mycrypto', + ETH_ETHSCAN = 'eth_ethscan', + ETH_INFURA = 'eth_infura', + ROP_MEW = 'rop_mew', + ROP_INFURA = 'rop_infura', + KOV_ETHSCAN = 'kov_ethscan', + RIN_ETHSCAN = 'rin_ethscan', + RIN_INFURA = 'rin_infura', + ETC_EPOOL = 'etc_epool', + UBQ = 'ubq', + EXP_TECH = 'exp_tech' +} + +type NonWeb3NodeConfigs = { [key in StaticNodeName]: StaticNodeConfig }; + +interface Web3NodeConfig { + web3?: StaticNodeConfig; +} + +type NodeConfig = StaticNodesState[StaticNodeName] | CustomNodesState[string]; diff --git a/spec/config/networks.spec.ts b/spec/config/networks.spec.ts index 5227ce5a..3cf48611 100644 --- a/spec/config/networks.spec.ts +++ b/spec/config/networks.spec.ts @@ -1,9 +1,9 @@ -import { NETWORKS, NetworkConfig } from 'config'; +import { StaticNetworkConfig } from 'types/network'; describe('Networks', () => { Object.keys(NETWORKS).forEach(networkId => { it(`${networkId} contains non-null dPathFormats`, () => { - const network: NetworkConfig = NETWORKS[networkId]; + const network: StaticNetworkConfig = NETWORKS[networkId]; Object.values(network.dPathFormats).forEach(dPathFormat => { expect(dPathFormat).toBeTruthy(); }); diff --git a/spec/integration/data.int.ts b/spec/integration/data.int.ts index 8cd56153..e8eb0640 100644 --- a/spec/integration/data.int.ts +++ b/spec/integration/data.int.ts @@ -1,4 +1,3 @@ -import { NODES, NodeConfig } from 'config'; import { RPCNode } from '../../common/libs/nodes'; import { Validator } from 'jsonschema'; import { schema } from '../../common/libs/validators'; @@ -6,6 +5,7 @@ import 'url-search-params-polyfill'; import EtherscanNode from 'libs/nodes/etherscan'; import InfuraNode from 'libs/nodes/infura'; import RpcNodeTestConfig from './RpcNodeTestConfig'; +import { StaticNodeConfig } from 'types/node'; const v = new Validator(); @@ -63,7 +63,7 @@ function testRpcRequests(node: RPCNode, service: string) { }); } -const mapNodeEndpoints = (nodes: { [key: string]: NodeConfig }) => { +const mapNodeEndpoints = (nodes: { [key: string]: StaticNodeConfig }) => { const { RpcNodes, EtherscanNodes, InfuraNodes } = RpcNodeTestConfig; RpcNodes.forEach(n => { diff --git a/spec/pages/SendTransaction.spec.tsx b/spec/pages/SendTransaction.spec.tsx index cd48a794..d086b683 100644 --- a/spec/pages/SendTransaction.spec.tsx +++ b/spec/pages/SendTransaction.spec.tsx @@ -4,7 +4,6 @@ import Adapter from 'enzyme-adapter-react-16'; import SendTransaction from 'containers/Tabs/SendTransaction'; import shallowWithStore from '../utils/shallowWithStore'; import { createMockStore } from 'redux-test-utils'; -import { NODES } from 'config'; import { RouteComponentProps } from 'react-router'; import { createMockRouteComponentProps } from '../utils/mockRouteComponentProps'; diff --git a/spec/reducers/config.spec.ts b/spec/reducers/config.spec.ts index 8eebec9d..1e54bce8 100644 --- a/spec/reducers/config.spec.ts +++ b/spec/reducers/config.spec.ts @@ -1,6 +1,5 @@ -import { config, INITIAL_STATE } from 'reducers/config'; +import { config } from 'reducers/config'; import * as configActions from 'actions/config'; -import { NODES, NETWORKS } from 'config'; import { makeCustomNodeId, makeNodeConfigFromCustomConfig } from 'utils/node'; const custNode = { diff --git a/spec/reducers/customTokens.spec.ts b/spec/reducers/customTokens.spec.ts index a52df732..8b28c5af 100644 --- a/spec/reducers/customTokens.spec.ts +++ b/spec/reducers/customTokens.spec.ts @@ -1,6 +1,6 @@ import { customTokens } from 'reducers/customTokens'; -import { Token } from 'config'; import * as customTokensActions from 'actions/customTokens'; +import { Token } from 'types/network'; describe('customTokens reducer', () => { const token1: Token = { diff --git a/spec/sagas/config.spec.ts b/spec/sagas/config.spec.ts index 965e6e86..0db26a53 100644 --- a/spec/sagas/config.spec.ts +++ b/spec/sagas/config.spec.ts @@ -12,7 +12,6 @@ import { equivalentNodeOrDefault, reload } from 'sagas/config'; -import { NODES, NodeConfig, NETWORKS } from 'config'; import { getNodeName, getNodeConfig, @@ -20,11 +19,12 @@ import { getCustomNodeConfigs, getCustomNetworkConfigs } from 'selectors/config'; -import { INITIAL_STATE as configInitialState } from 'reducers/config'; import { Web3Wallet } from 'libs/wallet'; import { RPCNode } from 'libs/nodes'; import { showNotification } from 'actions/notifications'; import { translateRaw } from 'translations'; +import { StaticNodeConfig } from 'types/node'; + // init module configuredStore.getState(); @@ -289,7 +289,7 @@ describe('unsetWeb3Node*', () => { describe('unsetWeb3NodeOnWalletEvent*', () => { const fakeAction = {}; const mockNode = 'web3'; - const mockNodeConfig: Partial = { network: 'ETH' }; + const mockNodeConfig: Partial = { network: 'ETH' }; const gen = unsetWeb3NodeOnWalletEvent(fakeAction); it('should select getNode', () => { diff --git a/spec/sagas/deterministicWallets.spec.ts b/spec/sagas/deterministicWallets.spec.ts index 630815fe..f05cf444 100644 --- a/spec/sagas/deterministicWallets.spec.ts +++ b/spec/sagas/deterministicWallets.spec.ts @@ -7,13 +7,13 @@ import { getDesiredToken, getWallets } from 'selectors/deterministicWallets'; import { getTokens } from 'selectors/wallet'; import { getNodeLib } from 'selectors/config'; import * as dWalletActions from 'actions/deterministicWallets'; -import { Token } from 'config'; import { getDeterministicWallets, updateWalletValues, updateWalletTokenValues } from 'sagas/deterministicWallets'; import { TokenValue, Wei } from 'libs/units'; +import { Token } from 'types/network'; // init module configuredStore.getState(); diff --git a/spec/sagas/wallet.spec.tsx b/spec/sagas/wallet.spec.tsx index 6a330b83..e1033100 100644 --- a/spec/sagas/wallet.spec.tsx +++ b/spec/sagas/wallet.spec.tsx @@ -14,7 +14,7 @@ import { import { Wei } from 'libs/units'; import { changeNodeIntent, web3UnsetNode } from 'actions/config'; import { INode } from 'libs/nodes/INode'; -import { initWeb3Node, Token, N_FACTOR } from 'config'; +import { N_FACTOR } from 'config'; import { apply, call, fork, put, select, take, cancel } from 'redux-saga/effects'; import { getNodeLib, getOffline } from 'selectors/config'; import { getWalletInst, getWalletConfigTokens } from 'selectors/wallet'; @@ -37,7 +37,7 @@ import { cloneableGenerator, createMockTask } from 'redux-saga/utils'; import { showNotification } from 'actions/notifications'; import translate from 'translations'; import { IFullWallet, fromV3 } from 'ethereumjs-wallet'; - +import { Token } from 'types/network'; // init module configuredStore.getState(); const offline = false; diff --git a/tsconfig.json b/tsconfig.json index 8f948409..dd4638b5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,12 +9,10 @@ "allowJs": true, "baseUrl": "./common/", "paths": { - "shared*": ["../shared*"] + "shared*": ["../shared*"], + "types*": ["../shared/types*"] }, - "lib": [ - "es2017", - "dom" - ], + "lib": ["es2017", "dom"], "allowSyntheticDefaultImports": true, "moduleResolution": "node", "noEmitOnError": false, @@ -23,6 +21,7 @@ }, "include": [ "./common/", + "./shared/", "./electron/", "spec", "./node_modules/types-rlp/index.d.ts"