Merge pull request #209 from poanetwork/enhance-rpc-validation
(Fix) Enhance custom RPC validation
This commit is contained in:
commit
600c54054a
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
## 4.9.1 Tue Nov 27 2018
|
||||||
|
|
||||||
|
- [#209](https://github.com/poanetwork/nifty-wallet/pull/209): (Fix) Enhance custom RPC validation
|
||||||
|
|
||||||
## 4.9.0 Mon Nov 26 2018
|
## 4.9.0 Mon Nov 26 2018
|
||||||
|
|
||||||
- [#183](https://github.com/poanetwork/nifty-wallet/pull/183), [#205](https://github.com/poanetwork/nifty-wallet/pull/205): HD wallets support
|
- [#183](https://github.com/poanetwork/nifty-wallet/pull/183), [#205](https://github.com/poanetwork/nifty-wallet/pull/205): HD wallets support
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "__MSG_appName__",
|
"name": "__MSG_appName__",
|
||||||
"short_name": "__MSG_appName__",
|
"short_name": "__MSG_appName__",
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"author": "POA Network",
|
"author": "POA Network",
|
||||||
"description": "__MSG_appDescription__",
|
"description": "__MSG_appDescription__",
|
||||||
|
|
|
@ -3,9 +3,8 @@ const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const actions = require('../../ui/app/actions')
|
const actions = require('../../ui/app/actions')
|
||||||
const url = require('url')
|
const LoadingIndicator = require('./components/loading')
|
||||||
const http = require('http')
|
const Web3 = require('web3')
|
||||||
const https = require('https')
|
|
||||||
const infuraCurrencies = require('./infura-conversion.json').objects.sort((a, b) => {
|
const infuraCurrencies = require('./infura-conversion.json').objects.sort((a, b) => {
|
||||||
return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase())
|
return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase())
|
||||||
})
|
})
|
||||||
|
@ -25,13 +24,16 @@ function mapStateToProps (state) {
|
||||||
|
|
||||||
inherits(ConfigScreen, Component)
|
inherits(ConfigScreen, Component)
|
||||||
function ConfigScreen () {
|
function ConfigScreen () {
|
||||||
|
this.state = {
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigScreen.prototype.render = function () {
|
ConfigScreen.prototype.render = function () {
|
||||||
var state = this.props
|
const state = this.props
|
||||||
var metamaskState = state.metamask
|
const metamaskState = state.metamask
|
||||||
var warning = state.warning
|
const warning = state.warning
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h('.flex-column.flex-grow', {
|
h('.flex-column.flex-grow', {
|
||||||
|
@ -41,6 +43,10 @@ ConfigScreen.prototype.render = function () {
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
|
h(LoadingIndicator, {
|
||||||
|
isLoading: this.state.loading,
|
||||||
|
}),
|
||||||
|
|
||||||
h(Modal, {}, []),
|
h(Modal, {}, []),
|
||||||
|
|
||||||
// subtitle and nav
|
// subtitle and nav
|
||||||
|
@ -92,11 +98,11 @@ ConfigScreen.prototype.render = function () {
|
||||||
border: '1px solid #e2e2e2',
|
border: '1px solid #e2e2e2',
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
},
|
},
|
||||||
onKeyPress (event) {
|
onKeyPress: (event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
var element = event.target
|
const element = event.target
|
||||||
var newRpc = element.value
|
const newRpc = element.value
|
||||||
rpcValidation(newRpc, state)
|
this.rpcValidation(newRpc, state)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -105,11 +111,11 @@ ConfigScreen.prototype.render = function () {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
marginTop: '20px',
|
marginTop: '20px',
|
||||||
},
|
},
|
||||||
onClick (event) {
|
onClick: (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
var element = document.querySelector('input#new_rpc')
|
const element = document.querySelector('input#new_rpc')
|
||||||
var newRpc = element.value
|
const newRpc = element.value
|
||||||
rpcValidation(newRpc, state)
|
this.rpcValidation(newRpc, state)
|
||||||
},
|
},
|
||||||
}, 'Save'),
|
}, 'Save'),
|
||||||
]),
|
]),
|
||||||
|
@ -234,23 +240,24 @@ ConfigScreen.prototype.componentWillUnmount = function () {
|
||||||
this.props.dispatch(actions.displayWarning(''))
|
this.props.dispatch(actions.displayWarning(''))
|
||||||
}
|
}
|
||||||
|
|
||||||
function rpcValidation (newRpc, state) {
|
ConfigScreen.prototype.rpcValidation = function (newRpc, state) {
|
||||||
if (validUrl.isWebUri(newRpc)) {
|
if (validUrl.isWebUri(newRpc)) {
|
||||||
const rpc = url.parse(newRpc)
|
this.setState({
|
||||||
const protocolName = rpc.protocol.replace(/:/g, '')
|
loading: true,
|
||||||
const protocol = protocolName === 'https' ? https : http
|
|
||||||
const options = {method: 'GET', host: rpc.hostname, port: rpc.port, path: rpc.pathname}
|
|
||||||
const req = protocol.request(options)
|
|
||||||
.on('response', () => {
|
|
||||||
state.dispatch(actions.setRpcTarget(newRpc))
|
|
||||||
})
|
})
|
||||||
.on('error', () => {
|
const web3 = new Web3(new Web3.providers.HttpProvider(newRpc))
|
||||||
state.dispatch(actions.displayWarning('Invalid RPC endpoint'))
|
web3.eth.getBlockNumber((err, res) => {
|
||||||
|
if (err) {
|
||||||
|
state.dispatch(actions.displayWarning('Invalid RPC endpoint'))
|
||||||
|
} else {
|
||||||
|
state.dispatch(actions.setRpcTarget(newRpc))
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
req.end()
|
|
||||||
} else {
|
} else {
|
||||||
var appendedRpc = `http://${newRpc}`
|
if (!newRpc.startsWith('http')) {
|
||||||
if (validUrl.isWebUri(appendedRpc)) {
|
|
||||||
state.dispatch(actions.displayWarning('URIs require the appropriate HTTP/HTTPS prefix.'))
|
state.dispatch(actions.displayWarning('URIs require the appropriate HTTP/HTTPS prefix.'))
|
||||||
} else {
|
} else {
|
||||||
state.dispatch(actions.displayWarning('Invalid RPC URI'))
|
state.dispatch(actions.displayWarning('Invalid RPC URI'))
|
||||||
|
@ -259,16 +266,16 @@ function rpcValidation (newRpc, state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentConversionInformation (metamaskState, state) {
|
function currentConversionInformation (metamaskState, state) {
|
||||||
var currentCurrency = metamaskState.currentCurrency
|
const currentCurrency = metamaskState.currentCurrency
|
||||||
var conversionDate = metamaskState.conversionDate
|
const conversionDate = metamaskState.conversionDate
|
||||||
return h('div', [
|
return h('div', [
|
||||||
h('span', {style: { fontWeight: 'bold', paddingRight: '10px'}}, 'Current Conversion'),
|
h('span', {style: { fontWeight: 'bold', paddingRight: '10px'}}, 'Current Conversion'),
|
||||||
h('span', {style: { fontWeight: 'bold', paddingRight: '10px', fontSize: '13px'}}, `Updated ${Date(conversionDate)}`),
|
h('span', {style: { fontWeight: 'bold', paddingRight: '10px', fontSize: '13px'}}, `Updated ${Date(conversionDate)}`),
|
||||||
h('select#currentCurrency', {
|
h('select#currentCurrency', {
|
||||||
onChange (event) {
|
onChange (event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
var element = document.getElementById('currentCurrency')
|
const element = document.getElementById('currentCurrency')
|
||||||
var newCurrency = element.value
|
const newCurrency = element.value
|
||||||
state.dispatch(actions.setCurrentCurrency(newCurrency))
|
state.dispatch(actions.setCurrentCurrency(newCurrency))
|
||||||
},
|
},
|
||||||
defaultValue: currentCurrency,
|
defaultValue: currentCurrency,
|
||||||
|
@ -280,8 +287,8 @@ function currentConversionInformation (metamaskState, state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentProviderDisplay (metamaskState, state) {
|
function currentProviderDisplay (metamaskState, state) {
|
||||||
var provider = metamaskState.provider
|
const provider = metamaskState.provider
|
||||||
var title, value
|
let title, value
|
||||||
|
|
||||||
switch (provider.type) {
|
switch (provider.type) {
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,7 +38,7 @@
|
||||||
"test:mascara:build:locales": "mkdirp dist/chrome && cp -R app/_locales dist/chrome/_locales",
|
"test:mascara:build:locales": "mkdirp dist/chrome && cp -R app/_locales dist/chrome/_locales",
|
||||||
"test:mascara:build:background": "browserify mascara/src/background.js -o dist/mascara/background.js",
|
"test:mascara:build:background": "browserify mascara/src/background.js -o dist/mascara/background.js",
|
||||||
"test:mascara:build:tests": "browserify test/integration/lib/first-time.js -o dist/mascara/tests.js",
|
"test:mascara:build:tests": "browserify test/integration/lib/first-time.js -o dist/mascara/tests.js",
|
||||||
"ganache:start": "ganache-cli --noVMErrorsOnRPCResponse -m 'juice teach unaware view expand beef divorce spatial evolve rack scheme foster'",
|
"ganache:start": "ganache-cli --noVMErrorsOnRPCResponse -m 'horn among position unable audit puzzle cannon apology gun autumn plug parrot'",
|
||||||
"sentry:publish": "node ./development/sentry-publish.js",
|
"sentry:publish": "node ./development/sentry-publish.js",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint . --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Abstract contract for the full ERC 20 Token standard
|
||||||
|
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
|
||||||
|
pragma solidity ^0.4.21;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
contract EIP20 {
|
||||||
|
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||||
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||||
|
uint256 public totalSupply;
|
||||||
|
uint256 constant private MAX_UINT256 = 2**256 - 1;
|
||||||
|
mapping (address => uint256) public balances;
|
||||||
|
mapping (address => mapping (address => uint256)) public allowed;
|
||||||
|
/*
|
||||||
|
NOTE:
|
||||||
|
The following variables are OPTIONAL vanities. One does not have to include them.
|
||||||
|
They allow one to customise the token contract & in no way influences the core functionality.
|
||||||
|
Some wallets/interfaces might not even bother to look at this information.
|
||||||
|
*/
|
||||||
|
string public name; //fancy name: eg Simon Bucks
|
||||||
|
uint8 public decimals; //How many decimals to show.
|
||||||
|
string public symbol; //An identifier: eg SBX
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
uint256 _initialAmount,
|
||||||
|
string _tokenName,
|
||||||
|
uint8 _decimalUnits,
|
||||||
|
string _tokenSymbol
|
||||||
|
) public {
|
||||||
|
balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
|
||||||
|
totalSupply = _initialAmount; // Update total supply
|
||||||
|
name = _tokenName; // Set the name for display purposes
|
||||||
|
decimals = _decimalUnits; // Amount of decimals for display purposes
|
||||||
|
symbol = _tokenSymbol; // Set the symbol for display purposes
|
||||||
|
}
|
||||||
|
|
||||||
|
function transfer(address _to, uint256 _value) public returns (bool success) {
|
||||||
|
require(balances[msg.sender] >= _value);
|
||||||
|
balances[msg.sender] -= _value;
|
||||||
|
balances[_to] += _value;
|
||||||
|
emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
|
||||||
|
uint256 allowance = allowed[_from][msg.sender];
|
||||||
|
require(balances[_from] >= _value && allowance >= _value);
|
||||||
|
balances[_to] += _value;
|
||||||
|
balances[_from] -= _value;
|
||||||
|
if (allowance < MAX_UINT256) {
|
||||||
|
allowed[_from][msg.sender] -= _value;
|
||||||
|
}
|
||||||
|
emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function balanceOf(address _owner) public view returns (uint256 balance) {
|
||||||
|
return balances[_owner];
|
||||||
|
}
|
||||||
|
|
||||||
|
function approve(address _spender, uint256 _value) public returns (bool success) {
|
||||||
|
allowed[msg.sender][_spender] = _value;
|
||||||
|
emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
|
||||||
|
return allowed[_owner][_spender];
|
||||||
|
}
|
||||||
|
}
|
|
@ -267,7 +267,7 @@ module.exports = {
|
||||||
title: By.className('page-subtitle'),
|
title: By.className('page-subtitle'),
|
||||||
titleText: 'Remove Token',
|
titleText: 'Remove Token',
|
||||||
label: By.className('confirm-label'),
|
label: By.className('confirm-label'),
|
||||||
labelText: 'Are you sure you want to remove token "TST"?',
|
labelText: 'Are you sure you want to remove token "',
|
||||||
buttons: {
|
buttons: {
|
||||||
back: By.className('fa fa-arrow-left fa-lg cursor-pointer'),
|
back: By.className('fa fa-arrow-left fa-lg cursor-pointer'),
|
||||||
no: By.className('btn-violet'),
|
no: By.className('btn-violet'),
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue