commit
ab7eb73ecc
@ -1,4 +1,4 @@ |
||||
{ |
||||
"presets": [["env", { "debug": true }], "react", "stage-0"], |
||||
"presets": [["env"], "react", "stage-0"], |
||||
"plugins": ["transform-runtime", "transform-async-to-generator", "transform-class-properties"] |
||||
} |
||||
|
@ -1,13 +0,0 @@ |
||||
#!/usr/bin/env bash |
||||
echo "Checking if firefox was already downloaded" |
||||
if [ -d "firefox" ] |
||||
then |
||||
echo "Firefox found. No need to download" |
||||
else |
||||
FIREFOX_VERSION="61.0.1" |
||||
FIREFOX_BINARY="firefox-$FIREFOX_VERSION.tar.bz2" |
||||
echo "Downloading firefox..." |
||||
wget "https://ftp.mozilla.org/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/$FIREFOX_BINARY" \ |
||||
&& tar xjf "$FIREFOX_BINARY" |
||||
echo "firefox download complete" |
||||
fi |
@ -0,0 +1,29 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
set -e |
||||
set -u |
||||
set -o pipefail |
||||
|
||||
FIREFOX_VERSION='61.0.2' |
||||
FIREFOX_BINARY="firefox-${FIREFOX_VERSION}.tar.bz2" |
||||
FIREFOX_BINARY_URL="https://ftp.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/${FIREFOX_BINARY}" |
||||
FIREFOX_PATH='/opt/firefox' |
||||
|
||||
printf '%s\n' "Removing old Firefox installation" |
||||
|
||||
sudo rm -r "${FIREFOX_PATH}" |
||||
|
||||
printf '%s\n' "Downloading & installing Firefox ${FIREFOX_VERSION}" |
||||
|
||||
wget --quiet --show-progress -O- "${FIREFOX_BINARY_URL}" | sudo tar xj -C /opt |
||||
|
||||
printf '%s\n' "Firefox ${FIREFOX_VERSION} installed" |
||||
|
||||
{ |
||||
printf '%s\n' 'pref("general.config.filename", "firefox.cfg");' |
||||
printf '%s\n' 'pref("general.config.obscure_value", 0);' |
||||
} | sudo tee "${FIREFOX_PATH}/defaults/pref/autoconfig.js" |
||||
|
||||
sudo cp .circleci/scripts/firefox.cfg "${FIREFOX_PATH}" |
||||
|
||||
printf '%s\n' "Firefox ${FIREFOX_VERSION} configured" |
@ -1,8 +0,0 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
echo "Installing firefox..." |
||||
sudo rm -r /opt/firefox |
||||
sudo mv firefox /opt/firefox61 |
||||
sudo mv /usr/bin/firefox /usr/bin/firefox-old |
||||
sudo ln -s /opt/firefox61/firefox /usr/bin/firefox |
||||
echo "Firefox installed." |
@ -0,0 +1,13 @@ |
||||
// IMPORTANT: Start your code on the 2nd line |
||||
|
||||
lockPref("app.update.enabled", false); |
||||
lockPref("app.update.auto", false); |
||||
lockPref("app.update.mode", 0); |
||||
lockPref("app.update.service.enabled", false); |
||||
|
||||
pref("browser.rights.3.shown", true); |
||||
|
||||
pref("browser.startup.homepage_override.mstone","ignore"); |
||||
|
||||
lockPref("plugins.hide_infobar_for_outdated_plugin", true); |
||||
clearPref("plugins.update.url"); |
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1020 B |
@ -0,0 +1,25 @@ |
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') |
||||
const createBlockReEmitMiddleware = require('eth-json-rpc-middleware/block-reemit') |
||||
const createBlockCacheMiddleware = require('eth-json-rpc-middleware/block-cache') |
||||
const createInflightMiddleware = require('eth-json-rpc-middleware/inflight-cache') |
||||
const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector') |
||||
const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware') |
||||
const createInfuraMiddleware = require('eth-json-rpc-infura') |
||||
const BlockTracker = require('eth-block-tracker') |
||||
|
||||
module.exports = createInfuraClient |
||||
|
||||
function createInfuraClient ({ network }) { |
||||
const infuraMiddleware = createInfuraMiddleware({ network }) |
||||
const blockProvider = providerFromMiddleware(infuraMiddleware) |
||||
const blockTracker = new BlockTracker({ provider: blockProvider }) |
||||
|
||||
const networkMiddleware = mergeMiddleware([ |
||||
createBlockCacheMiddleware({ blockTracker }), |
||||
createInflightMiddleware(), |
||||
createBlockReEmitMiddleware({ blockTracker, provider: blockProvider }), |
||||
createBlockTrackerInspectorMiddleware({ blockTracker }), |
||||
infuraMiddleware, |
||||
]) |
||||
return { networkMiddleware, blockTracker } |
||||
} |
@ -0,0 +1,25 @@ |
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') |
||||
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch') |
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-ref') |
||||
const createBlockCacheMiddleware = require('eth-json-rpc-middleware/block-cache') |
||||
const createInflightMiddleware = require('eth-json-rpc-middleware/inflight-cache') |
||||
const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector') |
||||
const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware') |
||||
const BlockTracker = require('eth-block-tracker') |
||||
|
||||
module.exports = createJsonRpcClient |
||||
|
||||
function createJsonRpcClient ({ rpcUrl }) { |
||||
const fetchMiddleware = createFetchMiddleware({ rpcUrl }) |
||||
const blockProvider = providerFromMiddleware(fetchMiddleware) |
||||
const blockTracker = new BlockTracker({ provider: blockProvider }) |
||||
|
||||
const networkMiddleware = mergeMiddleware([ |
||||
createBlockRefMiddleware({ blockTracker }), |
||||
createBlockCacheMiddleware({ blockTracker }), |
||||
createInflightMiddleware(), |
||||
createBlockTrackerInspectorMiddleware({ blockTracker }), |
||||
fetchMiddleware, |
||||
]) |
||||
return { networkMiddleware, blockTracker } |
||||
} |
@ -0,0 +1,21 @@ |
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') |
||||
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch') |
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-ref') |
||||
const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector') |
||||
const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware') |
||||
const BlockTracker = require('eth-block-tracker') |
||||
|
||||
module.exports = createLocalhostClient |
||||
|
||||
function createLocalhostClient () { |
||||
const fetchMiddleware = createFetchMiddleware({ rpcUrl: 'http://localhost:8545/' }) |
||||
const blockProvider = providerFromMiddleware(fetchMiddleware) |
||||
const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 }) |
||||
|
||||
const networkMiddleware = mergeMiddleware([ |
||||
createBlockRefMiddleware({ blockTracker }), |
||||
createBlockTrackerInspectorMiddleware({ blockTracker }), |
||||
fetchMiddleware, |
||||
]) |
||||
return { networkMiddleware, blockTracker } |
||||
} |
@ -0,0 +1,43 @@ |
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') |
||||
const createScaffoldMiddleware = require('json-rpc-engine/src/createScaffoldMiddleware') |
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') |
||||
const createWalletSubprovider = require('eth-json-rpc-middleware/wallet') |
||||
|
||||
module.exports = createMetamaskMiddleware |
||||
|
||||
function createMetamaskMiddleware ({ |
||||
version, |
||||
getAccounts, |
||||
processTransaction, |
||||
processEthSignMessage, |
||||
processTypedMessage, |
||||
processPersonalMessage, |
||||
getPendingNonce, |
||||
}) { |
||||
const metamaskMiddleware = mergeMiddleware([ |
||||
createScaffoldMiddleware({ |
||||
// staticSubprovider
|
||||
eth_syncing: false, |
||||
web3_clientVersion: `MetaMask/v${version}`, |
||||
}), |
||||
createWalletSubprovider({ |
||||
getAccounts, |
||||
processTransaction, |
||||
processEthSignMessage, |
||||
processTypedMessage, |
||||
processPersonalMessage, |
||||
}), |
||||
createPendingNonceMiddleware({ getPendingNonce }), |
||||
]) |
||||
return metamaskMiddleware |
||||
} |
||||
|
||||
function createPendingNonceMiddleware ({ getPendingNonce }) { |
||||
return createAsyncMiddleware(async (req, res, next) => { |
||||
if (req.method !== 'eth_getTransactionCount') return next() |
||||
const address = req.params[0] |
||||
const blockRef = req.params[1] |
||||
if (blockRef !== 'pending') return next() |
||||
req.result = await getPendingNonce(address) |
||||
}) |
||||
} |
@ -1,42 +0,0 @@ |
||||
/** |
||||
* Returns an EventEmitter that proxies events from the given event emitter |
||||
* @param {any} eventEmitter |
||||
* @param {object} listeners - The listeners to proxy to |
||||
* @returns {any} |
||||
*/ |
||||
module.exports = function createEventEmitterProxy (eventEmitter, listeners) { |
||||
let target = eventEmitter |
||||
const eventHandlers = listeners || {} |
||||
const proxy = /** @type {any} */ (new Proxy({}, { |
||||
get: (_, name) => { |
||||
// intercept listeners
|
||||
if (name === 'on') return addListener |
||||
if (name === 'setTarget') return setTarget |
||||
if (name === 'proxyEventHandlers') return eventHandlers |
||||
return (/** @type {any} */ (target))[name] |
||||
}, |
||||
set: (_, name, value) => { |
||||
target[name] = value |
||||
return true |
||||
}, |
||||
})) |
||||
function setTarget (/** @type {EventEmitter} */ eventEmitter) { |
||||
target = eventEmitter |
||||
// migrate listeners
|
||||
Object.keys(eventHandlers).forEach((name) => { |
||||
/** @type {Array<Function>} */ (eventHandlers[name]).forEach((handler) => target.on(name, handler)) |
||||
}) |
||||
} |
||||
/** |
||||
* Attaches a function to be called whenever the specified event is emitted |
||||
* @param {string} name |
||||
* @param {Function} handler |
||||
*/ |
||||
function addListener (name, handler) { |
||||
if (!eventHandlers[name]) eventHandlers[name] = [] |
||||
eventHandlers[name].push(handler) |
||||
target.on(name, handler) |
||||
} |
||||
if (listeners) proxy.setTarget(eventEmitter) |
||||
return proxy |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@ |
||||
const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper') |
||||
|
||||
module.exports = createTxMeta |
||||
|
||||
function createTxMeta (partialMeta) { |
||||
const txMeta = Object.assign({ |
||||
status: 'unapproved', |
||||
txParams: {}, |
||||
}, partialMeta) |
||||
// initialize history
|
||||
txMeta.history = [] |
||||
// capture initial snapshot of txMeta for history
|
||||
const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) |
||||
txMeta.history.push(snapshot) |
||||
return txMeta |
||||
} |
@ -0,0 +1,21 @@ |
||||
|
||||
/** |
||||
* @typedef {Object} FirstTimeState |
||||
* @property {Object} config Initial configuration parameters |
||||
* @property {Object} NetworkController Network controller state |
||||
*/ |
||||
|
||||
/** |
||||
* @type {FirstTimeState} |
||||
*/ |
||||
const initialState = { |
||||
config: {}, |
||||
NetworkController: { |
||||
provider: { |
||||
type: 'rpc', |
||||
rpcTarget: 'http://localhost:8545', |
||||
}, |
||||
}, |
||||
} |
||||
|
||||
module.exports = initialState |
@ -1,2 +1 @@ |
||||
import AppHeader from './app-header.container' |
||||
module.exports = AppHeader |
||||
export { default } from './app-header.container' |
||||
|
@ -0,0 +1,2 @@ |
||||
import QrScanner from './qr-scanner.container' |
||||
module.exports = QrScanner |
@ -0,0 +1,83 @@ |
||||
.qr-scanner { |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: #fff; |
||||
display: flex; |
||||
flex-flow: column; |
||||
border-radius: 8px; |
||||
|
||||
&__title { |
||||
font-size: 1.5rem; |
||||
font-weight: 500; |
||||
padding: 16px 0; |
||||
text-align: center; |
||||
} |
||||
|
||||
&__content { |
||||
padding-left: 20px; |
||||
padding-right: 20px; |
||||
|
||||
&__video-wrapper { |
||||
overflow: hidden; |
||||
width: 100%; |
||||
height: 275px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
|
||||
video { |
||||
transform: scaleX(-1); |
||||
width: auto; |
||||
height: 275px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&__status { |
||||
text-align: center; |
||||
font-size: 14px; |
||||
padding: 15px; |
||||
} |
||||
|
||||
&__image { |
||||
font-size: 1.5rem; |
||||
font-weight: 500; |
||||
padding: 16px 0 0; |
||||
text-align: center; |
||||
} |
||||
|
||||
&__error { |
||||
text-align: center; |
||||
font-size: 16px; |
||||
padding: 15px; |
||||
} |
||||
|
||||
&__footer { |
||||
padding: 20px; |
||||
flex-direction: row; |
||||
display: flex; |
||||
|
||||
button { |
||||
margin-right: 15px; |
||||
} |
||||
|
||||
button:last-of-type { |
||||
margin-right: 0; |
||||
background-color: #009eec; |
||||
border: none; |
||||
color: #fff; |
||||
} |
||||
} |
||||
|
||||
&__close::after { |
||||
content: '\00D7'; |
||||
font-size: 35px; |
||||
color: #9b9b9b; |
||||
position: absolute; |
||||
top: 4px; |
||||
right: 20px; |
||||
cursor: pointer; |
||||
font-weight: 300; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,216 @@ |
||||
import React, { Component } from 'react' |
||||
import PropTypes from 'prop-types' |
||||
import { BrowserQRCodeReader } from '@zxing/library' |
||||
import adapter from 'webrtc-adapter' // eslint-disable-line import/no-nodejs-modules, no-unused-vars
|
||||
import Spinner from '../../spinner' |
||||
import WebcamUtils from '../../../../lib/webcam-utils' |
||||
import PageContainerFooter from '../../page-container/page-container-footer/page-container-footer.component' |
||||
|
||||
export default class QrScanner extends Component { |
||||
static propTypes = { |
||||
hideModal: PropTypes.func.isRequired, |
||||
qrCodeDetected: PropTypes.func, |
||||
scanQrCode: PropTypes.func, |
||||
error: PropTypes.bool, |
||||
errorType: PropTypes.string, |
||||
} |
||||
|
||||
static contextTypes = { |
||||
t: PropTypes.func, |
||||
} |
||||
|
||||
constructor (props, context) { |
||||
super(props) |
||||
|
||||
this.state = { |
||||
ready: false, |
||||
msg: context.t('accessingYourCamera'), |
||||
} |
||||
this.codeReader = null |
||||
this.permissionChecker = null |
||||
this.needsToReinit = false |
||||
|
||||
// Clear pre-existing qr code data before scanning
|
||||
this.props.qrCodeDetected(null) |
||||
} |
||||
|
||||
componentDidMount () { |
||||
this.initCamera() |
||||
} |
||||
|
||||
async checkPermisisions () { |
||||
const { permissions } = await WebcamUtils.checkStatus() |
||||
if (permissions) { |
||||
clearTimeout(this.permissionChecker) |
||||
// Let the video stream load first...
|
||||
setTimeout(_ => { |
||||
this.setState({ |
||||
ready: true, |
||||
msg: this.context.t('scanInstructions'), |
||||
}) |
||||
if (this.needsToReinit) { |
||||
this.initCamera() |
||||
this.needsToReinit = false |
||||
} |
||||
}, 2000) |
||||
} else { |
||||
// Keep checking for permissions
|
||||
this.permissionChecker = setTimeout(_ => { |
||||
this.checkPermisisions() |
||||
}, 1000) |
||||
} |
||||
} |
||||
|
||||
componentWillUnmount () { |
||||
clearTimeout(this.permissionChecker) |
||||
if (this.codeReader) { |
||||
this.codeReader.reset() |
||||
} |
||||
} |
||||
|
||||
initCamera () { |
||||
this.codeReader = new BrowserQRCodeReader() |
||||
this.codeReader.getVideoInputDevices() |
||||
.then(videoInputDevices => { |
||||
clearTimeout(this.permissionChecker) |
||||
this.checkPermisisions() |
||||
this.codeReader.decodeFromInputVideoDevice(undefined, 'video') |
||||
.then(content => { |
||||
const result = this.parseContent(content.text) |
||||
if (result.type !== 'unknown') { |
||||
this.props.qrCodeDetected(result) |
||||
this.stopAndClose() |
||||
} else { |
||||
this.setState({msg: this.context.t('unknownQrCode')}) |
||||
} |
||||
}) |
||||
.catch(err => { |
||||
if (err && err.name === 'NotAllowedError') { |
||||
this.setState({msg: this.context.t('youNeedToAllowCameraAccess')}) |
||||
clearTimeout(this.permissionChecker) |
||||
this.needsToReinit = true |
||||
this.checkPermisisions() |
||||
} |
||||
}) |
||||
}).catch(err => { |
||||
console.error('[QR-SCANNER]: getVideoInputDevices threw an exception: ', err) |
||||
}) |
||||
} |
||||
|
||||
parseContent (content) { |
||||
let type = 'unknown' |
||||
let values = {} |
||||
|
||||
// Here we could add more cases
|
||||
// To parse other type of links
|
||||
// For ex. EIP-681 (https://eips.ethereum.org/EIPS/eip-681)
|
||||
|
||||
|
||||
// Ethereum address links - fox ex. ethereum:0x.....1111
|
||||
if (content.split('ethereum:').length > 1) { |
||||
|
||||
type = 'address' |
||||
values = {'address': content.split('ethereum:')[1] } |
||||
|
||||
// Regular ethereum addresses - fox ex. 0x.....1111
|
||||
} else if (content.substring(0, 2).toLowerCase() === '0x') { |
||||
|
||||
type = 'address' |
||||
values = {'address': content } |
||||
|
||||
} |
||||
return {type, values} |
||||
} |
||||
|
||||
|
||||
stopAndClose = () => { |
||||
if (this.codeReader) { |
||||
this.codeReader.reset() |
||||
} |
||||
this.setState({ ready: false }) |
||||
this.props.hideModal() |
||||
} |
||||
|
||||
tryAgain = () => { |
||||
// close the modal
|
||||
this.stopAndClose() |
||||
// wait for the animation and try again
|
||||
setTimeout(_ => { |
||||
this.props.scanQrCode() |
||||
}, 1000) |
||||
} |
||||
|
||||
renderVideo () { |
||||
return ( |
||||
<div className={'qr-scanner__content__video-wrapper'}> |
||||
<video |
||||
id="video" |
||||
style={{ |
||||
display: this.state.ready ? 'block' : 'none', |
||||
}} |
||||
/> |
||||
{ !this.state.ready ? <Spinner color={'#F7C06C'} /> : null} |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
renderErrorModal () { |
||||
let title, msg |
||||
|
||||
if (this.props.error) { |
||||
if (this.props.errorType === 'NO_WEBCAM_FOUND') { |
||||
title = this.context.t('noWebcamFoundTitle') |
||||
msg = this.context.t('noWebcamFound') |
||||
} else { |
||||
title = this.context.t('unknownCameraErrorTitle') |
||||
msg = this.context.t('unknownCameraError') |
||||
} |
||||
} |
||||
|
||||
return ( |
||||
<div className="qr-scanner"> |
||||
<div className="qr-scanner__close" onClick={this.stopAndClose}></div> |
||||
|
||||
<div className="qr-scanner__image"> |
||||
<img src={'images/webcam.svg'} width={70} height={70} /> |
||||
</div> |
||||
<div className="qr-scanner__title"> |
||||
{ title } |
||||
</div> |
||||
<div className={'qr-scanner__error'}> |
||||
{msg} |
||||
</div> |
||||
<PageContainerFooter |
||||
onCancel={this.stopAndClose} |
||||
onSubmit={this.tryAgain} |
||||
cancelText={this.context.t('cancel')} |
||||
submitText={this.context.t('tryAgain')} |
||||
submitButtonType="confirm" |
||||
/> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
render () { |
||||
const { t } = this.context |
||||
|
||||
if (this.props.error) { |
||||
return this.renderErrorModal() |
||||
} |
||||
|
||||
return ( |
||||
<div className="qr-scanner"> |
||||
<div className="qr-scanner__close" onClick={this.stopAndClose}></div> |
||||
<div className="qr-scanner__title"> |
||||
{ `${t('scanQrCode')}` } |
||||
</div> |
||||
<div className="qr-scanner__content"> |
||||
{ this.renderVideo() } |
||||
</div> |
||||
<div className={'qr-scanner__status'}> |
||||
{this.state.msg} |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
import { connect } from 'react-redux' |
||||
import QrScanner from './qr-scanner.component' |
||||
|
||||
const { hideModal, qrCodeDetected, showQrScanner } = require('../../../actions') |
||||
import { |
||||
SEND_ROUTE, |
||||
} from '../../../routes' |
||||
|
||||
const mapStateToProps = state => { |
||||
return { |
||||
error: state.appState.modal.modalState.props.error, |
||||
errorType: state.appState.modal.modalState.props.errorType, |
||||
} |
||||
} |
||||
|
||||
const mapDispatchToProps = dispatch => { |
||||
return { |
||||
hideModal: () => dispatch(hideModal()), |
||||
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), |
||||
scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)), |
||||
} |
||||
} |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(QrScanner) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue