mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
camera working back and forth
This commit is contained in:
parent
0209148609
commit
f7ad978474
@ -6,6 +6,7 @@ const PongStream = require('ping-pong-stream/pong')
|
|||||||
const ObjectMultiplex = require('obj-multiplex')
|
const ObjectMultiplex = require('obj-multiplex')
|
||||||
const extension = require('extensionizer')
|
const extension = require('extensionizer')
|
||||||
const PortStream = require('./lib/port-stream.js')
|
const PortStream = require('./lib/port-stream.js')
|
||||||
|
const Instascan = require('instascan')
|
||||||
|
|
||||||
const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
|
const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
|
||||||
const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
|
const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
|
||||||
@ -199,3 +200,49 @@ function redirectToPhishingWarning () {
|
|||||||
console.log('MetaMask - redirecting to phishing warning')
|
console.log('MetaMask - redirecting to phishing warning')
|
||||||
window.location.href = 'https://metamask.io/phishing.html'
|
window.location.href = 'https://metamask.io/phishing.html'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initQrCodeScanner () {
|
||||||
|
// Append preview div
|
||||||
|
const preview = document.createElement('div')
|
||||||
|
preview.id = 'metamask-preview-wrapper'
|
||||||
|
preview.style = 'position:absolute; top: 20px; left: 20px; width: 300px; height: 300px; overflow: hidden; z-index: 999999999;'
|
||||||
|
const previewVideo = document.createElement('video')
|
||||||
|
previewVideo.id = 'metamask-preview-video'
|
||||||
|
previewVideo.style = 'width: 100%; height: 100%; object-fit: none; margin-left: -10%; margin-top: 10%;'
|
||||||
|
preview.appendChild(previewVideo)
|
||||||
|
document.body.appendChild(preview)
|
||||||
|
console.log('injected')
|
||||||
|
const scanner = new Instascan.Scanner({
|
||||||
|
video: document.getElementById('metamask-preview-video'),
|
||||||
|
backgroundScan: false,
|
||||||
|
continuous: true,
|
||||||
|
})
|
||||||
|
scanner.addListener('scan', function (content) {
|
||||||
|
console.log('QR-SCANNER: got code (IN-PAGE)', content)
|
||||||
|
scanner.stop().then(_ => {
|
||||||
|
console.log('QR-SCANNER: stopped scanner and sending msg (IN-PAGE)', content)
|
||||||
|
extension.runtime.sendMessage({
|
||||||
|
action: 'qr-code-scanner-data',
|
||||||
|
data: content,
|
||||||
|
})
|
||||||
|
console.log('QR-SCANNER: message sent (IN-PAGE)', content)
|
||||||
|
document.getElementById('metamask-preview-wrapper').parentElement.removeChild(document.getElementById('metamask-preview-wrapper'))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Instascan.Camera.getCameras().then(function (cameras) {
|
||||||
|
if (cameras.length > 0) {
|
||||||
|
scanner.start(cameras[0])
|
||||||
|
} else {
|
||||||
|
console.error('No cameras found.')
|
||||||
|
}
|
||||||
|
}).catch(function (e) {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
extension.runtime.onMessage.addListener(({ action }) => {
|
||||||
|
console.log('QR-SCANNER: message received (IN-PAGE)', action)
|
||||||
|
initQrCodeScanner()
|
||||||
|
})
|
||||||
|
console.log('QR-SCANNER: now listening (IN-PAGE)')
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ const log = require('loglevel')
|
|||||||
const LocalMessageDuplexStream = require('post-message-stream')
|
const LocalMessageDuplexStream = require('post-message-stream')
|
||||||
const setupDappAutoReload = require('./lib/auto-reload.js')
|
const setupDappAutoReload = require('./lib/auto-reload.js')
|
||||||
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
|
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
|
||||||
const Instascan = require('instascan')
|
|
||||||
restoreContextAfterImports()
|
restoreContextAfterImports()
|
||||||
|
|
||||||
log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
|
log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
|
||||||
@ -98,40 +97,3 @@ function restoreContextAfterImports () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initCameraScanner () {
|
|
||||||
// Append preview div
|
|
||||||
const preview = document.createElement('div')
|
|
||||||
preview.id = 'metamask-preview-wrapper'
|
|
||||||
preview.style = 'position:absolute; top: 20px; left: 20px; width: 300px; height: 300px; overflow: hidden; z-index: 999999999;'
|
|
||||||
const previewVideo = document.createElement('video')
|
|
||||||
previewVideo.id = 'metamask-preview-video'
|
|
||||||
previewVideo.style = 'width: 100%; height: 100%; object-fit: none; margin-left: -10%; margin-top: 10%;'
|
|
||||||
preview.appendChild(previewVideo)
|
|
||||||
document.body.appendChild(preview)
|
|
||||||
console.log('injected')
|
|
||||||
const scanner = new Instascan.Scanner({
|
|
||||||
video: document.getElementById('metamask-preview-video'),
|
|
||||||
backgroundScan: false,
|
|
||||||
continuous: true,
|
|
||||||
})
|
|
||||||
scanner.addListener('scan', function (content) {
|
|
||||||
alert(content)
|
|
||||||
scanner.stop().then(_ => {
|
|
||||||
document.getElementById('metamask-preview-wrapper').parentElement.removeChild(document.getElementById('metamask-preview-wrapper'))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Instascan.Camera.getCameras().then(function (cameras) {
|
|
||||||
if (cameras.length > 0) {
|
|
||||||
scanner.start(cameras[0])
|
|
||||||
} else {
|
|
||||||
console.error('No cameras found.')
|
|
||||||
}
|
|
||||||
}).catch(function (e) {
|
|
||||||
console.error(e)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(_ => {
|
|
||||||
console.log('injecting...')
|
|
||||||
initCameraScanner()
|
|
||||||
}, 3000)
|
|
||||||
|
@ -380,6 +380,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
// TREZOR
|
// TREZOR
|
||||||
unlockTrezorAccount: nodeify(this.unlockTrezorAccount, this),
|
unlockTrezorAccount: nodeify(this.unlockTrezorAccount, this),
|
||||||
|
|
||||||
|
// QR code scanner
|
||||||
|
scanQrCode: nodeify(this.scanQrCode, this),
|
||||||
|
|
||||||
// vault management
|
// vault management
|
||||||
submitPassword: nodeify(this.submitPassword, this),
|
submitPassword: nodeify(this.submitPassword, this),
|
||||||
|
|
||||||
@ -655,6 +658,25 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
return { ...keyState, identities }
|
return { ...keyState, identities }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanQrCode () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
console.log('QR-SCANNER: intializing QR code scanner feature (MM controller)')
|
||||||
|
// Tell contentscript to inject the QR reader
|
||||||
|
this.platform.sendMessage('qr-code-scanner-init')
|
||||||
|
console.log('QR-SCANNER: message to initialize has been sent (MM controller)')
|
||||||
|
// Wait for the scanner to send something back
|
||||||
|
this.platform.addMessageListener(({ action, data }) => {
|
||||||
|
console.log('QR-SCANNER: message received (MM controller)', action, data)
|
||||||
|
if (action && action === 'qr-code-scanner-data') {
|
||||||
|
const normalizedAddress = data.replace('ethereum:', '')
|
||||||
|
console.log('QR-SCANNER: resolving promise!', normalizedAddress)
|
||||||
|
return Promise.resolve(normalizedAddress)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('QR-SCANNER: now listening (MM controller)')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Account Management
|
// Account Management
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
const extension = require('extensionizer')
|
const extension = require('extensionizer')
|
||||||
const explorerLink = require('etherscan-link').createExplorerLink
|
|
||||||
|
|
||||||
class ExtensionPlatform {
|
class ExtensionPlatform {
|
||||||
|
|
||||||
@ -18,11 +17,8 @@ class ExtensionPlatform {
|
|||||||
return extension.runtime.getManifest().version
|
return extension.runtime.getManifest().version
|
||||||
}
|
}
|
||||||
|
|
||||||
openExtensionInBrowser (route = null) {
|
openExtensionInBrowser () {
|
||||||
let extensionURL = extension.runtime.getURL('home.html')
|
const extensionURL = extension.runtime.getURL('home.html')
|
||||||
if (route) {
|
|
||||||
extensionURL += `#${route}`
|
|
||||||
}
|
|
||||||
this.openWindow({ url: extensionURL })
|
this.openWindow({ url: extensionURL })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,58 +32,17 @@ class ExtensionPlatform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showTransactionNotification (txMeta) {
|
addMessageListener (cb) {
|
||||||
|
extension.runtime.onMessage.addListener(cb)
|
||||||
const status = txMeta.status
|
|
||||||
if (status === 'confirmed') {
|
|
||||||
this._showConfirmedTransaction(txMeta)
|
|
||||||
} else if (status === 'failed') {
|
|
||||||
this._showFailedTransaction(txMeta)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_showConfirmedTransaction (txMeta) {
|
sendMessage (message, query = {}) {
|
||||||
|
extension.tabs.query(query, tabs => {
|
||||||
this._subscribeToNotificationClicked()
|
const activeTab = tabs.filter(tab => tab.active)[0]
|
||||||
|
extension.tabs.sendMessage(activeTab.id, message)
|
||||||
const url = explorerLink(txMeta.hash, parseInt(txMeta.metamaskNetworkId))
|
console.log('QR-SCANNER: message sent to tab', message, activeTab)
|
||||||
const nonce = parseInt(txMeta.txParams.nonce, 16)
|
|
||||||
|
|
||||||
const title = 'Confirmed transaction'
|
|
||||||
const message = `Transaction ${nonce} confirmed! View on EtherScan`
|
|
||||||
this._showNotification(title, message, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
_showFailedTransaction (txMeta) {
|
|
||||||
|
|
||||||
const nonce = parseInt(txMeta.txParams.nonce, 16)
|
|
||||||
const title = 'Failed transaction'
|
|
||||||
const message = `Transaction ${nonce} failed! ${txMeta.err.message}`
|
|
||||||
this._showNotification(title, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
_showNotification (title, message, url) {
|
|
||||||
extension.notifications.create(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
'type': 'basic',
|
|
||||||
'title': title,
|
|
||||||
'iconUrl': extension.extension.getURL('../../images/icon-64.png'),
|
|
||||||
'message': message,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribeToNotificationClicked () {
|
|
||||||
if (!extension.notifications.onClicked.hasListener(this._viewOnEtherScan)) {
|
|
||||||
extension.notifications.onClicked.addListener(this._viewOnEtherScan)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewOnEtherScan (txId) {
|
|
||||||
if (txId.startsWith('http://')) {
|
|
||||||
global.metamaskController.platform.openWindow({ url: txId })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ExtensionPlatform
|
module.exports = ExtensionPlatform
|
||||||
|
@ -302,6 +302,7 @@ var actions = {
|
|||||||
CLEAR_PENDING_TOKENS: 'CLEAR_PENDING_TOKENS',
|
CLEAR_PENDING_TOKENS: 'CLEAR_PENDING_TOKENS',
|
||||||
setPendingTokens,
|
setPendingTokens,
|
||||||
clearPendingTokens,
|
clearPendingTokens,
|
||||||
|
scanQrCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = actions
|
module.exports = actions
|
||||||
@ -2194,3 +2195,23 @@ function clearPendingTokens () {
|
|||||||
type: actions.CLEAR_PENDING_TOKENS,
|
type: actions.CLEAR_PENDING_TOKENS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scanQrCode () {
|
||||||
|
log.debug(`background.scanQrCode`)
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.scanQrCode((err, data) => {
|
||||||
|
log.debug(`background.scanQrCode resolved!`, err, data)
|
||||||
|
if (err) {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
return resolve(data)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@ export default class SendContent extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
updateGas: PropTypes.func,
|
updateGas: PropTypes.func,
|
||||||
|
scanQrCode: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -19,6 +20,7 @@ export default class SendContent extends Component {
|
|||||||
<div className="send-v2__form">
|
<div className="send-v2__form">
|
||||||
<SendFromRow />
|
<SendFromRow />
|
||||||
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
||||||
|
<button onClick={_ => this.props.scanQrCode() }>or scan a QR code</button>
|
||||||
<SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
<SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
||||||
<SendGasRow />
|
<SendGasRow />
|
||||||
<SendHexDataRow />
|
<SendHexDataRow />
|
||||||
|
@ -38,12 +38,19 @@ export default class SendTransactionScreen extends PersistentForm {
|
|||||||
updateAndSetGasTotal: PropTypes.func,
|
updateAndSetGasTotal: PropTypes.func,
|
||||||
updateSendErrors: PropTypes.func,
|
updateSendErrors: PropTypes.func,
|
||||||
updateSendTokenBalance: PropTypes.func,
|
updateSendTokenBalance: PropTypes.func,
|
||||||
|
scanQrCode: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scanQrCode = async () => {
|
||||||
|
const scannedAddress = await this.props.scanQrCode()
|
||||||
|
console.log('QR-SCANNER: Got address (UI)', scannedAddress)
|
||||||
|
this.updateGas({ to: scannedAddress })
|
||||||
|
}
|
||||||
|
|
||||||
updateGas ({ to: updatedToAddress, amount: value } = {}) {
|
updateGas ({ to: updatedToAddress, amount: value } = {}) {
|
||||||
const {
|
const {
|
||||||
amount,
|
amount,
|
||||||
@ -170,7 +177,10 @@ export default class SendTransactionScreen extends PersistentForm {
|
|||||||
return (
|
return (
|
||||||
<div className="page-container">
|
<div className="page-container">
|
||||||
<SendHeader history={history}/>
|
<SendHeader history={history}/>
|
||||||
<SendContent updateGas={(updateData) => this.updateGas(updateData)}/>
|
<SendContent
|
||||||
|
updateGas={(updateData) => this.updateGas(updateData)}
|
||||||
|
scanQrCode={_ => this.scanQrCode()}
|
||||||
|
/>
|
||||||
<SendFooter history={history}/>
|
<SendFooter history={history}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
updateSendTokenBalance,
|
updateSendTokenBalance,
|
||||||
updateGasData,
|
updateGasData,
|
||||||
setGasTotal,
|
setGasTotal,
|
||||||
|
scanQrCode,
|
||||||
} from '../../actions'
|
} from '../../actions'
|
||||||
import {
|
import {
|
||||||
resetSendState,
|
resetSendState,
|
||||||
@ -89,5 +90,6 @@ function mapDispatchToProps (dispatch) {
|
|||||||
},
|
},
|
||||||
updateSendErrors: newError => dispatch(updateSendErrors(newError)),
|
updateSendErrors: newError => dispatch(updateSendErrors(newError)),
|
||||||
resetSendState: () => dispatch(resetSendState()),
|
resetSendState: () => dispatch(resetSendState()),
|
||||||
|
scanQrCode: () => dispatch(scanQrCode()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user