Merge pull request #333 from poanetwork/vb-rsk-testnet-explorer-links-support

Support RSK testnet explorer links
This commit is contained in:
Victor Baranov 2020-03-23 19:29:30 +03:00 committed by GitHub
commit 91918a6cdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 184 additions and 108 deletions

View File

@ -2,6 +2,7 @@
## Current Master ## Current Master
- [#333](https://github.com/poanetwork/nifty-wallet/pull/333) - (Fix) Support RSK testnet explorer links
- [#332](https://github.com/poanetwork/nifty-wallet/pull/332) - (Chore) Return to main screen from removal of imported account - [#332](https://github.com/poanetwork/nifty-wallet/pull/332) - (Chore) Return to main screen from removal of imported account
- [#330](https://github.com/poanetwork/nifty-wallet/pull/330) - (Fix) Derive correct addresses for custom networks (RSK/ETC) - [#330](https://github.com/poanetwork/nifty-wallet/pull/330) - (Fix) Derive correct addresses for custom networks (RSK/ETC)
- [#329](https://github.com/poanetwork/nifty-wallet/pull/329) - (Fix) Connect to unknown private network fix - [#329](https://github.com/poanetwork/nifty-wallet/pull/329) - (Fix) Connect to unknown private network fix

View File

@ -37,7 +37,7 @@ class ContractImportView extends Component {
this.setState({ this.setState({
contractAddr, contractAddr,
}, () => { }, () => {
this.autodetectContractAbi() this.autodetectContractABI()
}) })
} }
@ -52,7 +52,7 @@ class ContractImportView extends Component {
}) })
} }
} catch (e) { } catch (e) {
this.clearAbi() this.clearABI()
log.debug('ABI can not be parsed') log.debug('ABI can not be parsed')
} }
} }
@ -116,11 +116,11 @@ class ContractImportView extends Component {
) )
} }
autodetectContractAbi = () => { autodetectContractABI = () => {
const { contractAddr, web3 } = this.state const { contractAddr, web3 } = this.state
const { type, network } = this.props const { type, network } = this.props
if (!contractAddr || !web3.isAddress(contractAddr)) { if (!contractAddr || !web3.isAddress(contractAddr)) {
this.clearAbi() this.clearABI()
return return
} }
getFullABI(web3.eth, contractAddr, network, type) getFullABI(web3.eth, contractAddr, network, type)
@ -134,7 +134,7 @@ class ContractImportView extends Component {
} }
}) })
.catch(e => { .catch(e => {
this.clearAbi() this.clearABI()
log.debug(e) log.debug(e)
this.props.displayWarning(e.message) this.props.displayWarning(e.message)
}) })
@ -166,13 +166,13 @@ class ContractImportView extends Component {
const { contractAddr, web3 } = this.state const { contractAddr, web3 } = this.state
if (!contractAddr || !web3.isAddress(contractAddr)) { if (!contractAddr || !web3.isAddress(contractAddr)) {
this.clearAbi() this.clearABI()
return this.props.displayWarning('Invalid contract address') return this.props.displayWarning('Invalid contract address')
} }
const contractAddrCode = await this.getContractCode() const contractAddrCode = await this.getContractCode()
if (contractAddrCode === '0x') { if (contractAddrCode === '0x') {
this.clearAbi() this.clearABI()
return this.props.displayWarning('This is not a contract address') return this.props.displayWarning('This is not a contract address')
} }
@ -180,12 +180,12 @@ class ContractImportView extends Component {
try { try {
abi = JSON.parse(this.state.abi) abi = JSON.parse(this.state.abi)
} catch (e) { } catch (e) {
this.clearAbi() this.clearABI()
this.props.displayWarning('Invalid ABI') this.props.displayWarning('Invalid ABI')
} }
if (!abi) { if (!abi) {
this.clearAbi() this.clearABI()
return this.props.displayWarning('Invalid contract ABI') return this.props.displayWarning('Invalid contract ABI')
} }
@ -203,7 +203,7 @@ class ContractImportView extends Component {
}) })
} }
clearAbi () { clearABI () {
this.setState({ this.setState({
abi: '', abi: '',
abiInputDisabled: false, abiInputDisabled: false,

View File

@ -57,25 +57,46 @@ const getBlockscoutApiNetworkSuffix = (network) => {
} }
} }
const _isBlockscoutInstanceForThisChain = (network) => {
switch (Number(network)) {
case 1:
case 99:
case 77:
case 100:
return true
case 42:
case 3:
case 4:
return false
default:
return false
}
}
const fetchABI = (addr, network) => { const fetchABI = (addr, network) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const networkParent = getBlockscoutApiNetworkPrefix(network) const blockscoutInstanceExists = _isBlockscoutInstanceForThisChain(network)
const networkName = getBlockscoutApiNetworkSuffix(network) if (blockscoutInstanceExists) {
const bloscoutApiLink = `https://blockscout.com/${networkParent}/${networkName}/api` const networkParent = getBlockscoutApiNetworkPrefix(network)
const bloscoutApiContractPath = '?module=contract' const networkName = getBlockscoutApiNetworkSuffix(network)
const blockscoutApiGetAbiPath = `&action=getabi&address=${addr}` const bloscoutApiLink = `https://blockscout.com/${networkParent}/${networkName}/api`
const apiLink = `${bloscoutApiLink}${bloscoutApiContractPath}${blockscoutApiGetAbiPath}` const bloscoutApiContractPath = '?module=contract'
fetch(apiLink) const blockscoutApiGetAbiPath = `&action=getabi&address=${addr}`
.then(response => { const apiLink = `${bloscoutApiLink}${bloscoutApiContractPath}${blockscoutApiGetAbiPath}`
return response.json() fetch(apiLink)
}) .then(response => {
.then(responseJson => { return response.json()
resolve(responseJson && responseJson.result) })
}) .then(responseJson => {
.catch((e) => { resolve(responseJson && responseJson.result)
log.debug(e) })
.catch(e => {
log.debug(e)
reject(e)
})
} else {
resolve() resolve()
}) }
}) })
} }
@ -94,13 +115,17 @@ const getFullABI = (eth, contractAddr, network, type) => {
} }
try { try {
eth.contract(targetABI).at(contractAddr).implementation.call((err, implAddr) => { eth.contract(targetABI).at(contractAddr).implementation.call((err, implAddr) => {
fetchABI(implAddr, network) if (err) {
.then((implABI) => { reject(err)
implABI = implABI && JSON.parse(implABI) } else {
finalABI = implABI ? targetABI.concat(implABI) : targetABI fetchABI(implAddr, network)
resolve(finalABI) .then((implABI) => {
}) implABI = implABI && JSON.parse(implABI)
.catch(e => reject(e)) finalABI = implABI ? targetABI.concat(implABI) : targetABI
resolve(finalABI)
})
.catch(e => reject(e))
}
}) })
} catch (e) { } catch (e) {
reject(e) reject(e)

View File

@ -205,7 +205,8 @@ class AccountDropdowns extends Component {
viewOnBlockExplorer = () => { viewOnBlockExplorer = () => {
const { selected, network } = this.props const { selected, network } = this.props
const url = ethNetProps.explorerLinks.getExplorerAccountLinkFor(selected, network) const networkCode = parseInt(network, 10)
const url = ethNetProps.explorerLinks.getExplorerAccountLinkFor(selected, networkCode)
global.platform.openWindow({ url }) global.platform.openWindow({ url })
} }

View File

@ -17,8 +17,8 @@ class NetworksMenu extends Component {
provider: PropTypes.any.isRequired, provider: PropTypes.any.isRequired,
frequentRpcList: PropTypes.array.isRequired, frequentRpcList: PropTypes.array.isRequired,
isNetworkMenuOpen: PropTypes.bool, isNetworkMenuOpen: PropTypes.bool,
setProviderType: PropTypes.function, setProviderType: PropTypes.func,
showDeleteRPC: PropTypes.function, showDeleteRPC: PropTypes.func,
} }
render () { render () {
@ -50,7 +50,7 @@ class NetworksMenu extends Component {
// classes from three constituent nodes of the toggle element // classes from three constituent nodes of the toggle element
if (isNotToggleElement) { if (isNotToggleElement) {
this.props.updateNetworksMenuOpenState(false) props.updateNetworksMenuOpenState(false)
} }
}} }}
zIndex={11} zIndex={11}
@ -70,7 +70,7 @@ class NetworksMenu extends Component {
<DropdownMenuItem <DropdownMenuItem
key={'default'} key={'default'}
closeMenu={() => this.props.updateNetworksMenuOpenState(!isOpen)} closeMenu={() => props.updateNetworksMenuOpenState(!isOpen)}
onClick={() => { onClick={() => {
props.setProviderType(LOCALHOST, LOCALHOST_RPC_URL) props.setProviderType(LOCALHOST, LOCALHOST_RPC_URL)
props.setRpcTarget(LOCALHOST_RPC_URL) props.setRpcTarget(LOCALHOST_RPC_URL)
@ -86,8 +86,8 @@ class NetworksMenu extends Component {
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
closeMenu={() => this.props.updateNetworksMenuOpenState(!isOpen)} closeMenu={() => props.updateNetworksMenuOpenState(!isOpen)}
onClick={() => this.props.showConfigPage()} onClick={() => props.showConfigPage()}
className={'app-bar-networks-dropdown-custom-rpc'} className={'app-bar-networks-dropdown-custom-rpc'}
>Custom RPC</DropdownMenuItem> >Custom RPC</DropdownMenuItem>
@ -109,7 +109,7 @@ class NetworksMenu extends Component {
return ( return (
<DropdownMenuItem <DropdownMenuItem
key={networkObj.providerName} key={networkObj.providerName}
closeMenu={() => this.props.updateNetworksMenuOpenState(!isOpen)} closeMenu={() => props.updateNetworksMenuOpenState(!isOpen)}
onClick={() => props.setProviderType(networkObj.providerName)} onClick={() => props.setProviderType(networkObj.providerName)}
style={{ style={{
paddingLeft: '20px', paddingLeft: '20px',
@ -132,6 +132,7 @@ class NetworksMenu extends Component {
} }
renderCustomOption ({ rpcTarget, type }) { renderCustomOption ({ rpcTarget, type }) {
const props = this.props
if (type !== 'rpc') { if (type !== 'rpc') {
return null return null
} }
@ -149,8 +150,8 @@ class NetworksMenu extends Component {
return ( return (
<DropdownMenuItem <DropdownMenuItem
key={rpcTarget} key={rpcTarget}
onClick={() => this.props.setRpcTarget(rpcTarget)} onClick={() => props.setRpcTarget(rpcTarget)}
closeMenu={() => this.props.updateNetworksMenuOpenState(false)} closeMenu={() => props.updateNetworksMenuOpenState(false)}
> >
<i className="fa fa-question-circle fa-lg menu-icon" /> <i className="fa fa-question-circle fa-lg menu-icon" />
{label} {label}
@ -171,7 +172,7 @@ class NetworksMenu extends Component {
return ( return (
<DropdownMenuItem <DropdownMenuItem
key={`common${rpc}`} key={`common${rpc}`}
closeMenu={() => this.props.updateNetworksMenuOpenState(false)} closeMenu={() => props.updateNetworksMenuOpenState(false)}
onClick={() => props.setRpcTarget(rpc)} onClick={() => props.setRpcTarget(rpc)}
style={{ style={{
paddingLeft: '20px', paddingLeft: '20px',
@ -183,8 +184,8 @@ class NetworksMenu extends Component {
onClick={(event) => { onClick={(event) => {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
this.props.updateNetworksMenuOpenState(false) props.updateNetworksMenuOpenState(false)
props.showDeleteRPC(rpc) props.showDeleteRPC(rpc, true)
}} }}
/> />
</DropdownMenuItem> </DropdownMenuItem>
@ -210,7 +211,7 @@ class NetworksMenu extends Component {
<DropdownMenuItem <DropdownMenuItem
key={rpcTarget} key={rpcTarget}
onClick={() => props.setRpcTarget(rpcTarget)} onClick={() => props.setRpcTarget(rpcTarget)}
closeMenu={() => this.props.updateNetworksMenuOpenState(false)} closeMenu={() => props.updateNetworksMenuOpenState(false)}
style={{ style={{
paddingLeft: '20px', paddingLeft: '20px',
color: 'white', color: 'white',
@ -223,8 +224,8 @@ class NetworksMenu extends Component {
onClick={(event) => { onClick={(event) => {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
this.props.updateNetworksMenuOpenState(false) props.updateNetworksMenuOpenState(false)
props.showDeleteRPC(label) props.showDeleteRPC(label, true)
}} }}
/> />
</DropdownMenuItem> </DropdownMenuItem>
@ -238,7 +239,7 @@ const mapDispatchToProps = dispatch => {
showConfigPage: () => dispatch(actions.showConfigPage()), showConfigPage: () => dispatch(actions.showConfigPage()),
setRpcTarget: (rpcTarget) => dispatch(actions.setRpcTarget(rpcTarget)), setRpcTarget: (rpcTarget) => dispatch(actions.setRpcTarget(rpcTarget)),
setProviderType: (providerType) => dispatch(actions.setProviderType(providerType)), setProviderType: (providerType) => dispatch(actions.setProviderType(providerType)),
showDeleteRPC: (label) => dispatch(actions.showDeleteRPC(label)), showDeleteRPC: (label, transitionForward) => dispatch(actions.showDeleteRPC(label, transitionForward)),
} }
} }

View File

@ -4,17 +4,21 @@ import { connect } from 'react-redux'
import actions from '../../../ui/app/actions' import actions from '../../../ui/app/actions'
class DeleteRpc extends ConfirmScreen { class DeleteRpc extends ConfirmScreen {
static propTypes = {
}
render () { render () {
const props = this.props
return ( return (
<ConfirmScreen <ConfirmScreen
subtitle="Delete Custom RPC" subtitle="Delete Custom RPC"
question={`Are you sure to delete ${this.props.url} ?`} question={`Are you sure to delete ${props.url} ?`}
onCancelClick={() => this.props.dispatch(actions.showConfigPage())} onCancelClick={() => props.showConfigPage()}
onNoClick={() => this.props.dispatch(actions.showConfigPage())} onNoClick={() => props.showConfigPage()}
onYesClick={() => { onYesClick={() => {
this.props.dispatch(actions.removeCustomRPC(this.props.url, this.props.provider)) props.removeCustomRPC(props.url, props.provider)
.then(() => { .then(() => {
this.props.dispatch(actions.showConfigPage()) props.showConfigPage()
}) })
}} }}
/> />
@ -30,4 +34,11 @@ function mapStateToProps (state) {
} }
} }
module.exports = connect(mapStateToProps)(DeleteRpc) const mapDispatchToProps = dispatch => {
return {
showConfigPage: () => dispatch(actions.showConfigPage()),
removeCustomRPC: (url, provider) => dispatch(actions.removeCustomRPC(url, provider)),
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(DeleteRpc)

View File

@ -5,8 +5,8 @@ import PropTypes from 'prop-types'
export default class PendingMsg extends Component { export default class PendingMsg extends Component {
static propTypes = { static propTypes = {
txData: PropTypes.object, txData: PropTypes.object,
cancelMessage: PropTypes.function, cancelMessage: PropTypes.func,
signMessage: PropTypes.function, signMessage: PropTypes.func,
} }
render () { render () {

View File

@ -5,8 +5,8 @@ import PropTypes from 'prop-types'
export default class PendingMsg extends Component { export default class PendingMsg extends Component {
static propTypes = { static propTypes = {
txData: PropTypes.object, txData: PropTypes.object,
cancelPersonalMessage: PropTypes.function, cancelPersonalMessage: PropTypes.func,
signPersonalMessage: PropTypes.function, signPersonalMessage: PropTypes.func,
} }
render () { render () {

View File

@ -5,8 +5,8 @@ import PropTypes from 'prop-types'
export default class PendingMsg extends Component { export default class PendingMsg extends Component {
static propTypes = { static propTypes = {
txData: PropTypes.object, txData: PropTypes.object,
cancelTypedMessage: PropTypes.function, cancelTypedMessage: PropTypes.func,
signTypedMessage: PropTypes.function, signTypedMessage: PropTypes.func,
} }
render () { render () {

View File

@ -26,6 +26,7 @@ const { POA_CODE,
GOERLI_TESTNET_CODE, GOERLI_TESTNET_CODE,
CLASSIC_CODE, CLASSIC_CODE,
RSK_CODE, RSK_CODE,
RSK_TESTNET_CODE,
} = require('../../../app/scripts/controllers/network/enums') } = require('../../../app/scripts/controllers/network/enums')
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
@ -87,7 +88,8 @@ TransactionListItem.prototype.render = function () {
numericNet === DAI_CODE || numericNet === DAI_CODE ||
numericNet === GOERLI_TESTNET_CODE || numericNet === GOERLI_TESTNET_CODE ||
numericNet === CLASSIC_CODE || numericNet === CLASSIC_CODE ||
numericNet === RSK_CODE numericNet === RSK_CODE ||
numericNet === RSK_TESTNET_CODE
var isMsg = ('msgParams' in transaction) var isMsg = ('msgParams' in transaction)
var isTx = ('txParams' in transaction) var isTx = ('txParams' in transaction)

View File

@ -26,29 +26,39 @@ const {
const POCKET_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, POA, DAI, GOERLI_TESTNET, POA_SOKOL] const POCKET_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, POA, DAI, GOERLI_TESTNET, POA_SOKOL]
class ConfigScreen extends Component { class ConfigScreen extends Component {
static propTypes = {
metamask: PropTypes.object,
warning: PropTypes.string,
provider: PropTypes.object,
dProviderStore: PropTypes.object,
setProviderType: PropTypes.func,
showDeleteRPC: PropTypes.func,
displayWarning: PropTypes.func,
goHome: PropTypes.func,
setDProvider: PropTypes.func,
setRpcTarget: PropTypes.func,
confirmChangePassword: PropTypes.func,
revealSeedConfirmation: PropTypes.func,
resetAccount: PropTypes.func,
setCurrentCurrency: PropTypes.func,
}
constructor (props) { constructor (props) {
super(props) super(props)
this.state = { this.state = {
loading: false, loading: false,
dProvider: props.metamask.dProviderStore.dProvider, dProvider: props.dProviderStore.dProvider,
} }
} }
static propTypes = {
dispatch: PropTypes.func,
metamask: PropTypes.object,
warning: PropTypes.string,
}
render () { render () {
const state = this.props const props = this.props
const metamaskState = state.metamask const metamaskState = props.metamask
const warning = state.warning const warning = props.warning
if (state.metamask.dProviderStore.dProvider !== this.state.dProvider) { if (props.dProviderStore.dProvider !== this.state.dProvider) {
this.setState({ this.setState({
dProvider: this.props.metamask.dProviderStore.dProvider, dProvider: props.dProviderStore.dProvider,
}) })
} }
@ -70,7 +80,7 @@ class ConfigScreen extends Component {
h('.section-title.flex-row.flex-center', [ h('.section-title.flex-row.flex-center', [
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
onClick: () => { onClick: () => {
state.dispatch(actions.goHome()) props.goHome()
}, },
style: { style: {
position: 'absolute', position: 'absolute',
@ -101,7 +111,7 @@ class ConfigScreen extends Component {
}, },
}, [ }, [
this.currentProviderDisplay(metamaskState, state), this.currentProviderDisplay(metamaskState),
h('div', { style: {display: 'flex'} }, [ h('div', { style: {display: 'flex'} }, [
h('input#new_rpc', { h('input#new_rpc', {
@ -119,7 +129,7 @@ class ConfigScreen extends Component {
if (event.key === 'Enter') { if (event.key === 'Enter') {
const element = event.target const element = event.target
const newRpc = element.value const newRpc = element.value
this.rpcValidation(newRpc, state) this.rpcValidation(newRpc)
} }
}, },
}), }),
@ -130,13 +140,13 @@ class ConfigScreen extends Component {
event.preventDefault() event.preventDefault()
const element = document.querySelector('input#new_rpc') const element = document.querySelector('input#new_rpc')
const newRpc = element.value const newRpc = element.value
this.rpcValidation(newRpc, state) this.rpcValidation(newRpc)
}, },
}, 'Save'), }, 'Save'),
h('hr.horizontal-line'), h('hr.horizontal-line'),
this.currentConversionInformation(metamaskState, state), this.currentConversionInformation(metamaskState),
h('hr.horizontal-line'), h('hr.horizontal-line'),
@ -150,7 +160,7 @@ class ConfigScreen extends Component {
onClick (event) { onClick (event) {
window.logStateString((err, result) => { window.logStateString((err, result) => {
if (err) { if (err) {
state.dispatch(actions.displayWarning('Error in retrieving state logs.')) props.displayWarning('Error in retrieving state logs.')
} else { } else {
exportAsFile('Nifty Wallet State Logs.json', result) exportAsFile('Nifty Wallet State Logs.json', result)
} }
@ -170,7 +180,7 @@ class ConfigScreen extends Component {
}, },
onClick (event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.revealSeedConfirmation()) props.revealSeedConfirmation()
}, },
}, 'Reveal Seed Words'), }, 'Reveal Seed Words'),
]), ]),
@ -221,7 +231,7 @@ class ConfigScreen extends Component {
}, },
onClick (event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.resetAccount()) props.resetAccount()
}, },
}, 'Reset Account'), }, 'Reset Account'),
@ -230,7 +240,7 @@ class ConfigScreen extends Component {
h('button.btn-spread', { h('button.btn-spread', {
onClick (event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.confirmChangePassword()) props.confirmChangePassword()
}, },
}, 'Change password'), }, 'Change password'),
]), ]),
@ -241,30 +251,32 @@ class ConfigScreen extends Component {
} }
toggleProvider () { toggleProvider () {
const isPocket = POCKET_PROVIDER_TYPES.includes(this.props.metamask.provider.type) const props = this.props
const isPocket = POCKET_PROVIDER_TYPES.includes(props.provider.type)
if (isPocket) { if (isPocket) {
if (!this.state.dProvider) { if (!this.state.dProvider) {
this.props.dispatch(actions.setDProvider(true)) props.setDProvider(true)
this.setState({ this.setState({
dProvider: true, dProvider: true,
}) })
} else { } else {
this.props.dispatch(actions.setDProvider(false)) props.setDProvider(false)
this.setState({ this.setState({
dProvider: false, dProvider: false,
}) })
} }
this.props.dispatch(actions.setProviderType(this.props.metamask.provider.type)) props.setProviderType(props.provider.type)
} else { } else {
alert('Pocket does not support this network, using centralized provider') alert('Pocket does not support this network, using centralized provider')
} }
} }
componentWillUnmount () { componentWillUnmount () {
this.props.dispatch(actions.displayWarning('')) this.props.displayWarning('')
} }
rpcValidation (newRpc, state) { rpcValidation (newRpc) {
const props = this.props
if (validUrl.isWebUri(newRpc)) { if (validUrl.isWebUri(newRpc)) {
this.setState({ this.setState({
loading: true, loading: true,
@ -272,9 +284,9 @@ class ConfigScreen extends Component {
const web3 = new Web3(new Web3.providers.HttpProvider(newRpc)) const web3 = new Web3(new Web3.providers.HttpProvider(newRpc))
web3.eth.getBlockNumber((err, res) => { web3.eth.getBlockNumber((err, res) => {
if (err) { if (err) {
state.dispatch(actions.displayWarning('Invalid RPC endpoint')) props.displayWarning('Invalid RPC endpoint')
} else { } else {
state.dispatch(actions.setRpcTarget(newRpc)) props.setRpcTarget(newRpc)
} }
this.setState({ this.setState({
loading: false, loading: false,
@ -282,14 +294,15 @@ class ConfigScreen extends Component {
}) })
} else { } else {
if (!newRpc.startsWith('http')) { if (!newRpc.startsWith('http')) {
state.dispatch(actions.displayWarning('URIs require the appropriate HTTP/HTTPS prefix.')) props.displayWarning('URIs require the appropriate HTTP/HTTPS prefix.')
} else { } else {
state.dispatch(actions.displayWarning('Invalid RPC URI')) props.displayWarning('Invalid RPC URI')
} }
} }
} }
currentConversionInformation (metamaskState, state) { currentConversionInformation (metamaskState) {
const props = this.props
const currentCurrency = metamaskState.currentCurrency const currentCurrency = metamaskState.currentCurrency
const conversionDate = metamaskState.conversionDate const conversionDate = metamaskState.conversionDate
return h('div', [ return h('div', [
@ -300,7 +313,7 @@ class ConfigScreen extends Component {
event.preventDefault() event.preventDefault()
const element = document.getElementById('currentCurrency') const element = document.getElementById('currentCurrency')
const newCurrency = element.value const newCurrency = element.value
state.dispatch(actions.setCurrentCurrency(newCurrency)) props.setCurrentCurrency(newCurrency)
}, },
defaultValue: currentCurrency, defaultValue: currentCurrency,
}, infuraCurrencies.map((currency) => { }, infuraCurrencies.map((currency) => {
@ -310,7 +323,8 @@ class ConfigScreen extends Component {
]) ])
} }
currentProviderDisplay (metamaskState, state) { currentProviderDisplay (metamaskState) {
const props = this.props
const provider = metamaskState.provider const provider = metamaskState.provider
let title, value let title, value
@ -328,7 +342,7 @@ class ConfigScreen extends Component {
provider.type === 'rpc' && h('button.btn-spread', { provider.type === 'rpc' && h('button.btn-spread', {
onClick (event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.showDeleteRPC()) props.showDeleteRPC()
}, },
}, 'Delete'), }, 'Delete'),
]) ])
@ -338,8 +352,25 @@ class ConfigScreen extends Component {
function mapStateToProps (state) { function mapStateToProps (state) {
return { return {
metamask: state.metamask, metamask: state.metamask,
provider: state.metamask.provider,
dProviderStore: state.metamask.dProviderStore,
warning: state.appState.warning, warning: state.appState.warning,
} }
} }
module.exports = connect(mapStateToProps)(ConfigScreen) const mapDispatchToProps = dispatch => {
return {
setProviderType: (providerType) => dispatch(actions.setProviderType(providerType)),
showDeleteRPC: (label, transitionForward) => dispatch(actions.showDeleteRPC(label, transitionForward)),
displayWarning: (msg) => dispatch(actions.displayWarning(msg)),
goHome: () => dispatch(actions.goHome()),
setDProvider: (set) => dispatch(actions.setDProvider(set)),
setRpcTarget: (rpcTarget) => dispatch(actions.setRpcTarget(rpcTarget)),
setCurrentCurrency: (newCurrency) => dispatch(actions.setRpcTarget(newCurrency)),
confirmChangePassword: () => dispatch(actions.confirmChangePassword()),
resetAccount: () => dispatch(actions.resetAccount()),
revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()),
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfigScreen)

View File

@ -4,17 +4,21 @@ import { connect } from 'react-redux'
import actions from '../../ui/app/actions' import actions from '../../ui/app/actions'
class RemoveTokenScreen extends ConfirmScreen { class RemoveTokenScreen extends ConfirmScreen {
static propTypes = {
}
render () { render () {
const props = this.props
return ( return (
<ConfirmScreen <ConfirmScreen
subtitle="Remove Token" subtitle="Remove Token"
question={`Are you sure you want to remove token "${this.props.symbol}"?`} question={`Are you sure you want to remove token "${props.symbol}"?`}
onCancelClick={() => this.props.goHome()} onCancelClick={() => props.goHome()}
onNoClick={() => this.props.goHome()} onNoClick={() => props.goHome()}
onYesClick={() => { onYesClick={() => {
this.props.removeToken(this.props.address) props.removeToken(props.address)
.then(() => { .then(() => {
this.props.goHome() props.goHome()
}) })
}} }}
/> />

6
package-lock.json generated
View File

@ -12001,9 +12001,9 @@
} }
}, },
"eth-net-props": { "eth-net-props": {
"version": "1.0.32", "version": "1.0.33",
"resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.32.tgz", "resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.33.tgz",
"integrity": "sha512-t0BN0xoHZlwUjLZFJCdHyA6d5PMG1Ic+ykii4gW4kU/cRQ4q60utO/MgBerRHQnjwraQzYgy0OxcX94RLoM/NA==", "integrity": "sha512-RoqoXkY3+ztjdD9EfbjnMapWqfRjUscPon4Vjt48RLHDDYyNmz7LiQ4Qgb4E41PNS7xRoGkQCWJvJRAI9vDsFQ==",
"requires": { "requires": {
"chai": "^4.2.0" "chai": "^4.2.0"
} }

View File

@ -116,7 +116,7 @@
"eth-keychain-controller": "github:vbaranov/KeyringController#5.1.0", "eth-keychain-controller": "github:vbaranov/KeyringController#5.1.0",
"eth-ledger-bridge-keyring": "github:vbaranov/eth-ledger-bridge-keyring#0.1.0-clear-accounts-flag", "eth-ledger-bridge-keyring": "github:vbaranov/eth-ledger-bridge-keyring#0.1.0-clear-accounts-flag",
"eth-method-registry": "^1.0.0", "eth-method-registry": "^1.0.0",
"eth-net-props": "^1.0.32", "eth-net-props": "^1.0.33",
"eth-phishing-detect": "^1.1.4", "eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
"eth-sig-util": "^2.2.0", "eth-sig-util": "^2.2.0",