Refactor Languages / Fix RPC Node Regression (#239)

* simplify language dropdown; move language mapping to separate file (json)
* re-add rpc options (removed in bad merge)
This commit is contained in:
Daniel Ternyak 2017-09-26 16:03:38 -07:00 committed by GitHub
parent af84a589c5
commit cc391f551a
6 changed files with 194 additions and 125 deletions

View File

@ -13,7 +13,7 @@ import {
} from '../../config/data';
import GasPriceDropdown from './components/GasPriceDropdown';
import Navigation from './components/Navigation';
import { getKeyByValue } from 'utils/helpers';
import './index.scss';
interface Props {
@ -30,8 +30,7 @@ interface Props {
export default class Header extends Component<Props, {}> {
public render() {
const { languageSelection, changeNode, nodeSelection } = this.props;
const selectedLanguage =
languages.find(l => l.sign === languageSelection) || languages[0];
const selectedLanguage = languageSelection;
const selectedNode = NODES[nodeSelection];
const selectedNetwork = NETWORKS[selectedNode.network];
const LanguageDropDown = Dropdown as new () => Dropdown<
@ -76,10 +75,11 @@ export default class Header extends Component<Props, {}> {
/>
<LanguageDropDown
ariaLabel={`change language. current language ${selectedLanguage.name}`}
options={languages}
formatTitle={this.extractName}
value={selectedLanguage}
ariaLabel={`change language. current language ${languages[
selectedLanguage
]}`}
options={Object.values(languages)}
value={languages[selectedLanguage]}
extra={[
<li key={'separator'} role="separator" className="divider" />,
<li key={'disclaimer'}>
@ -109,19 +109,18 @@ export default class Header extends Component<Props, {}> {
<Navigation
location={this.props.location}
// color={selectedNetwork.color}
color={selectedNetwork.color}
/>
</div>
);
}
public changeLanguage = (value: { sign: string }) => {
this.props.changeLanguage(value.sign);
};
private extractName(): (option: { sign: string; name: string }) => string {
return name;
public changeLanguage = (value: string) => {
const key = getKeyByValue(languages, value);
if (key) {
this.props.changeLanguage(key);
}
};
private nodeNetworkAndService = (option: string) => [
NODES[option].network,

View File

@ -5,7 +5,7 @@ interface Props<T> {
options: T[];
ariaLabel: string;
extra?: any;
formatTitle(option: T): any;
formatTitle?(option: T): any;
onChange(value: T): void;
}
@ -32,10 +32,10 @@ export default class DropdownComponent<T> extends Component<Props<T>, State> {
className="dropdown-toggle"
onClick={this.toggleExpanded}
>
{this.formatTitle(value)}
{this.props.formatTitle ? this.formatTitle(value) : value}
<i className="caret" />
</a>
{expanded &&
{expanded && (
<ul className="dropdown-menu">
{options.map((option, i) => {
return (
@ -44,20 +44,23 @@ export default class DropdownComponent<T> extends Component<Props<T>, State> {
className={option === value ? 'active' : ''}
onClick={this.onChange.bind(null, option)}
>
{this.formatTitle(option)}
{this.props.formatTitle ? this.formatTitle(option) : option}
</a>
</li>
);
})}
{extra}
</ul>}
</ul>
)}
</span>
);
}
public formatTitle(option: any) {
public formatTitle = (option: any) => {
if (this.props.formatTitle) {
return this.props.formatTitle(option);
}
};
public toggleExpanded = () => {
this.setState(state => {

View File

@ -1,5 +1,5 @@
import { EtherscanNode, InfuraNode, RPCNode } from 'libs/nodes';
export const languages = require('./languages.json');
// Displays in the header
export const VERSION = '4.0.0 (Alpha 0.0.2)';
@ -40,101 +40,6 @@ export const gasPriceDefaults = {
export const bityReferralURL = 'https://bity.com/af/jshkb37v';
export const languages = [
{
sign: 'en',
name: 'English'
},
{
sign: 'de',
name: 'Deutsch'
},
{
sign: 'el',
name: 'Ελληνικά'
},
{
sign: 'es',
name: 'Español'
},
{
sign: 'fi',
name: 'Suomi'
},
{
sign: 'fr',
name: 'Français'
},
{
sign: 'hu',
name: 'Magyar'
},
{
sign: 'id',
name: 'Indonesian'
},
{
sign: 'it',
name: 'Italiano'
},
{
sign: 'ja',
name: '日本語'
},
{
sign: 'nl',
name: 'Nederlands'
},
{
sign: 'no',
name: 'Norsk Bokmål'
},
{
sign: 'pl',
name: 'Polski'
},
{
sign: 'pt',
name: 'Português'
},
{
sign: 'ru',
name: 'Русский'
},
{
sign: 'ko',
name: 'Korean'
},
// {
// 'sign': 'sk',
// 'name': 'Slovenčina'
// },
// {
// 'sign': 'sl',
// 'name': 'Slovenščina'
// },
// {
// 'sign': 'sv',
// 'name': 'Svenska'
// },
{
sign: 'tr',
name: 'Türkçe'
},
{
sign: 'vi',
name: 'Tiếng Việt'
},
{
sign: 'zhcn',
name: '简体中文'
},
{
sign: 'zhtw',
name: '繁體中文'
}
];
export interface BlockExplorerConfig {
name: string;
tx(txHash: string): string;
@ -156,6 +61,7 @@ export interface NetworkContract {
export interface NetworkConfig {
name: string;
unit: string;
color?: string;
blockExplorer?: BlockExplorerConfig;
tokenExplorer?: {
name: string;
@ -173,22 +79,92 @@ export interface NodeConfig {
estimateGas?: boolean;
}
// Must be a website that follows the ethplorer convention of /tx/[hash] and
// address/[address] to generate the correct functions.
function makeExplorer(url): BlockExplorerConfig {
return {
name: url,
tx: hash => `${url}/tx/${hash}`,
address: address => `${url}/address/${address}`
};
}
export const NETWORKS: { [key: string]: NetworkConfig } = {
ETH: {
name: 'ETH',
unit: 'ETH',
chainId: 1,
blockExplorer: {
name: etherScan,
tx: ETHTxExplorer,
address: ETHAddressExplorer
},
color: '#0e97c0',
blockExplorer: makeExplorer('https://etherscan.io'),
tokenExplorer: {
name: ethPlorer,
address: ETHTokenExplorer
},
tokens: require('./tokens/eth'),
tokens: require('./tokens/eth.json'),
contracts: require('./contracts/eth.json')
},
ETC: {
name: 'ETC',
unit: 'ETC',
chainId: 61,
color: '#669073',
blockExplorer: makeExplorer('https://gastracker.io'),
tokens: require('./tokens/etc.json'),
contracts: require('./contracts/etc.json')
},
Ropsten: {
name: 'Ropsten',
unit: 'ETH',
chainId: 3,
color: '#adc101',
blockExplorer: makeExplorer('https://ropsten.etherscan.io'),
tokens: require('./tokens/ropsten.json'),
contracts: require('./contracts/ropsten.json')
},
Kovan: {
name: 'Kovan',
unit: 'ETH',
chainId: 42,
color: '#adc101',
blockExplorer: makeExplorer('https://kovan.etherscan.io'),
tokens: require('./tokens/ropsten.json'),
contracts: require('./contracts/ropsten.json')
},
Rinkeby: {
name: 'Rinkeby',
unit: 'ETH',
chainId: 4,
color: '#adc101',
blockExplorer: makeExplorer('https://rinkeby.etherscan.io'),
tokens: require('./tokens/rinkeby.json'),
contracts: require('./contracts/rinkeby.json')
},
RSK: {
name: 'RSK',
unit: 'RSK',
chainId: 31,
color: '#ff794f',
blockExplorer: makeExplorer('https://explorer.rsk.co'),
tokens: require('./tokens/rsk.json'),
contracts: require('./contracts/rsk.json')
},
EXP: {
name: 'EXP',
unit: 'EXP',
chainId: 2,
color: '#673ab7',
blockExplorer: makeExplorer('http://www.gander.tech'),
tokens: require('./tokens/exp.json'),
contracts: require('./contracts/exp.json')
},
UBQ: {
name: 'UBQ',
unit: 'UBQ',
chainId: 8,
color: '#b37aff',
blockExplorer: makeExplorer('https://ubiqscan.io/en'),
tokens: require('./tokens/ubq.json'),
contracts: require('./contracts/ubq.json')
}
};
@ -198,5 +174,71 @@ export const NODES: { [key: string]: NodeConfig } = {
lib: new RPCNode('https://api.myetherapi.com/eth'),
service: 'MyEtherWallet',
estimateGas: true
},
eth_ethscan: {
network: 'ETH',
service: 'Etherscan.io',
lib: new EtherscanNode('https://api.etherscan.io/api'),
estimateGas: false
},
eth_infura: {
network: 'ETH',
service: 'infura.io',
lib: new InfuraNode('https://mainnet.infura.io/mew'),
estimateGas: false
},
etc_epool: {
network: 'ETC',
service: 'Epool.io',
lib: new RPCNode('https://mewapi.epool.io'),
estimateGas: false
},
rop_mew: {
network: 'Ropsten',
service: 'MyEtherWallet',
lib: new RPCNode('https://api.myetherapi.com/rop'),
estimateGas: false
},
rop_infura: {
network: 'Ropsten',
service: 'infura.io',
lib: new InfuraNode('https://ropsten.infura.io/mew'),
estimateGas: false
},
kov_ethscan: {
network: 'Kovan',
service: 'Etherscan.io',
lib: new EtherscanNode('https://kovan.etherscan.io/api'),
estimateGas: false
},
rin_ethscan: {
network: 'Rinkeby',
service: 'Etherscan.io',
lib: new EtherscanNode('https://rinkeby.etherscan.io/api'),
estimateGas: false
},
rin_infura: {
network: 'Rinkeby',
service: 'infura.io',
lib: new InfuraNode('https://rinkeby.infura.io/mew'),
estimateGas: false
},
rsk: {
network: 'RSK',
service: 'GK2.sk',
lib: new RPCNode('https://rsk-test.gk2.sk/'),
estimateGas: true
},
exp: {
network: 'EXP',
service: 'Expanse.tech',
lib: new RPCNode('https://node.expanse.tech/'),
estimateGas: true
},
ubq: {
network: 'UBQ',
service: 'ubiqscan.io',
lib: new RPCNode('https://pyrus2.ubiqscan.io'),
estimateGas: true
}
};

View File

@ -0,0 +1,22 @@
{
"en": "English",
"de": "Deutsch",
"el": "Ελληνικά",
"es": "Español",
"fi": "Suomi",
"fr": "Français",
"hu": "Magyar",
"id": "Indonesian",
"it": "Italiano",
"ja": "日本語",
"nl": "Nederlands",
"no": "Norsk Bokmål",
"pl": "Polski",
"pt": "Português",
"ru": "Русский",
"ko": "Korean",
"tr": "Türkçe",
"vi": "Tiếng Việt",
"zhcn": "简体中文",
"zhtw": "繁體中文"
}

View File

@ -15,7 +15,7 @@ export interface State {
}
export const INITIAL_STATE: State = {
languageSelection: languages[0].sign,
languageSelection: 'en',
nodeSelection: Object.keys(NODES)[0],
gasPriceGwei: 21
};

3
common/utils/helpers.ts Normal file
View File

@ -0,0 +1,3 @@
export function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}