mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'i328-MultiVault' of github.com:MetaMask/metamask-plugin into i328-MultiVault
This commit is contained in:
commit
331bb735c7
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
## 2.13.5 2016-10-18
|
||||||
|
|
||||||
|
- Increase default max gas to `100000` over the RPC's `estimateGas` response.
|
||||||
|
- Fix bug where slow-loading dapps would sometimes trigger infinite reload loops.
|
||||||
|
|
||||||
|
## 2.13.4 2016-10-17
|
||||||
|
|
||||||
|
- Add custom transaction fee field to send form.
|
||||||
|
- Fix bug where web3 was being injected into XML files.
|
||||||
|
- Fix bug where changing network would not reload current Dapps.
|
||||||
|
|
||||||
## 2.13.3 2016-10-4
|
## 2.13.3 2016-10-4
|
||||||
|
|
||||||
- Fix bug where log queries were filtered out.
|
- Fix bug where log queries were filtered out.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "MetaMask",
|
"name": "MetaMask",
|
||||||
"short_name": "Metamask",
|
"short_name": "Metamask",
|
||||||
"version": "2.13.3",
|
"version": "2.13.5",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"author": "https://metamask.io",
|
"author": "https://metamask.io",
|
||||||
"description": "Ethereum Browser Extension",
|
"description": "Ethereum Browser Extension",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const LocalMessageDuplexStream = require('post-message-stream')
|
const LocalMessageDuplexStream = require('post-message-stream')
|
||||||
|
const PongStream = require('ping-pong-stream/pong')
|
||||||
const PortStream = require('./lib/port-stream.js')
|
const PortStream = require('./lib/port-stream.js')
|
||||||
const ObjectMultiplex = require('./lib/obj-multiplex')
|
const ObjectMultiplex = require('./lib/obj-multiplex')
|
||||||
const extension = require('./lib/extension')
|
const extension = require('./lib/extension')
|
||||||
@ -51,20 +52,35 @@ function setupStreams(){
|
|||||||
// forward communication plugin->inpage
|
// forward communication plugin->inpage
|
||||||
pageStream.pipe(pluginStream).pipe(pageStream)
|
pageStream.pipe(pluginStream).pipe(pageStream)
|
||||||
|
|
||||||
// connect contentscript->inpage reload stream
|
// setup local multistream channels
|
||||||
var mx = ObjectMultiplex()
|
var mx = ObjectMultiplex()
|
||||||
mx.on('error', console.error)
|
mx.on('error', console.error)
|
||||||
mx.pipe(pageStream)
|
mx.pipe(pageStream).pipe(mx)
|
||||||
var reloadStream = mx.createStream('reload')
|
|
||||||
reloadStream.on('error', console.error)
|
// connect ping stream
|
||||||
|
var pongStream = new PongStream({ objectMode: true })
|
||||||
|
pongStream.pipe(mx.createStream('pingpong')).pipe(pongStream)
|
||||||
|
|
||||||
|
// ignore unused channels (handled by background)
|
||||||
|
mx.ignoreStream('provider')
|
||||||
|
mx.ignoreStream('publicConfig')
|
||||||
|
mx.ignoreStream('reload')
|
||||||
|
|
||||||
// if we lose connection with the plugin, trigger tab refresh
|
|
||||||
pluginStream.on('close', function () {
|
|
||||||
reloadStream.write({ method: 'reset' })
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldInjectWeb3(){
|
function shouldInjectWeb3(){
|
||||||
var shouldInject = (window.location.href.indexOf('.pdf') === -1)
|
return isAllowedSuffix(window.location.href)
|
||||||
return shouldInject
|
}
|
||||||
|
|
||||||
|
function isAllowedSuffix(testCase) {
|
||||||
|
var prohibitedTypes = ['xml', 'pdf']
|
||||||
|
var currentUrl = window.location.href
|
||||||
|
var currentRegex
|
||||||
|
for (let i = 0; i < prohibitedTypes.length; i++) {
|
||||||
|
currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`)
|
||||||
|
if (currentRegex.test(currentUrl)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
cleanContextForImports()
|
cleanContextForImports()
|
||||||
require('web3/dist/web3.min.js')
|
require('web3/dist/web3.min.js')
|
||||||
const LocalMessageDuplexStream = require('post-message-stream')
|
const LocalMessageDuplexStream = require('post-message-stream')
|
||||||
|
const PingStream = require('ping-pong-stream/ping')
|
||||||
|
const endOfStream = require('end-of-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')
|
||||||
restoreContextAfterImports()
|
restoreContextAfterImports()
|
||||||
@ -29,13 +31,22 @@ web3.setProvider = function () {
|
|||||||
console.log('MetaMask - overrode web3.setProvider')
|
console.log('MetaMask - overrode web3.setProvider')
|
||||||
}
|
}
|
||||||
console.log('MetaMask - injected web3')
|
console.log('MetaMask - injected web3')
|
||||||
|
// export global web3, with usage-detection reload fn
|
||||||
|
var triggerReload = setupDappAutoReload(web3)
|
||||||
|
|
||||||
//
|
// listen for reset requests from metamask
|
||||||
// export global web3 with auto dapp reload
|
|
||||||
//
|
|
||||||
|
|
||||||
var reloadStream = inpageProvider.multiStream.createStream('reload')
|
var reloadStream = inpageProvider.multiStream.createStream('reload')
|
||||||
setupDappAutoReload(web3, reloadStream)
|
reloadStream.once('data', triggerReload)
|
||||||
|
|
||||||
|
// setup ping timeout autoreload
|
||||||
|
// LocalMessageDuplexStream does not self-close, so reload if pingStream fails
|
||||||
|
var pingChannel = inpageProvider.multiStream.createStream('pingpong')
|
||||||
|
var pingStream = new PingStream({ objectMode: true })
|
||||||
|
// wait for first successful reponse
|
||||||
|
metamaskStream.once('_data', function(){
|
||||||
|
pingStream.pipe(pingChannel).pipe(pingStream)
|
||||||
|
})
|
||||||
|
endOfStream(pingStream, triggerReload)
|
||||||
|
|
||||||
// set web3 defaultAcount
|
// set web3 defaultAcount
|
||||||
inpageProvider.publicConfigStore.subscribe(function (state) {
|
inpageProvider.publicConfigStore.subscribe(function (state) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const scrypt = require('scrypt-async')
|
|
||||||
const bitcore = require('bitcore-lib')
|
|
||||||
const configManager = require('./lib/config-manager')
|
|
||||||
const EventEmitter = require('events').EventEmitter
|
const EventEmitter = require('events').EventEmitter
|
||||||
|
const encryptor = require('./lib/encryptor')
|
||||||
|
const messageManager = require('./lib/message-manager')
|
||||||
|
|
||||||
|
|
||||||
module.exports = class KeyringController extends EventEmitter {
|
module.exports = class KeyringController extends EventEmitter {
|
||||||
|
|
||||||
@ -12,12 +12,17 @@ module.exports = class KeyringController extends EventEmitter {
|
|||||||
this.keyChains = []
|
this.keyChains = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyFromPassword(password, callback) {
|
||||||
|
deriveKeyFromPassword(password, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes a pw and callback, returns a password-dervied key
|
||||||
getKeyForPassword(password, callback) {
|
getKeyForPassword(password, callback) {
|
||||||
let salt = this.configManager.getSalt()
|
let salt = this.configManager.getSalt()
|
||||||
|
|
||||||
if (!salt) {
|
if (!salt) {
|
||||||
salt = generateSalt(32)
|
salt = generateSalt(32)
|
||||||
configManager.setSalt(salt)
|
this.configManager.setSalt(salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
var logN = 14
|
var logN = 14
|
||||||
@ -39,7 +44,21 @@ module.exports = class KeyringController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getState() {
|
getState() {
|
||||||
return {}
|
return {
|
||||||
|
isInitialized: !!this.key,
|
||||||
|
isUnlocked: !!this.key,
|
||||||
|
isConfirmed: true, // this.configManager.getConfirmed(),
|
||||||
|
isEthConfirmed: this.configManager.getShouldntShowWarning(),
|
||||||
|
unconfTxs: this.configManager.unconfirmedTxs(),
|
||||||
|
transactions: this.configManager.getTxList(),
|
||||||
|
unconfMsgs: messageManager.unconfirmedMsgs(),
|
||||||
|
messages: messageManager.getMsgList(),
|
||||||
|
selectedAddress: this.configManager.getSelectedAccount(),
|
||||||
|
shapeShiftTxList: this.configManager.getShapeShiftTxList(),
|
||||||
|
currentFiat: this.configManager.getCurrentFiat(),
|
||||||
|
conversionRate: this.configManager.getConversionRate(),
|
||||||
|
conversionDate: this.configManager.getConversionDate(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setStore(ethStore) {
|
setStore(ethStore) {
|
||||||
@ -47,9 +66,22 @@ module.exports = class KeyringController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createNewVault(password, entropy, cb) {
|
createNewVault(password, entropy, cb) {
|
||||||
cb()
|
encryptor.keyFromPassword(password)
|
||||||
|
.then((key) => {
|
||||||
|
this.key = key
|
||||||
|
return encryptor.encryptWithKey(key, {})
|
||||||
|
})
|
||||||
|
.then((encryptedString) => {
|
||||||
|
this.configManager.setVault(encryptedString)
|
||||||
|
cb(null, [])
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
cb(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
submitPassword(password, cb) {
|
submitPassword(password, cb) {
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ const ensnare = require('ensnare')
|
|||||||
|
|
||||||
module.exports = setupDappAutoReload
|
module.exports = setupDappAutoReload
|
||||||
|
|
||||||
function setupDappAutoReload (web3, controlStream) {
|
function setupDappAutoReload (web3) {
|
||||||
// export web3 as a global, checking for usage
|
// export web3 as a global, checking for usage
|
||||||
var pageIsUsingWeb3 = false
|
var pageIsUsingWeb3 = false
|
||||||
var resetWasRequested = false
|
var resetWasRequested = false
|
||||||
@ -16,19 +16,19 @@ function setupDappAutoReload (web3, controlStream) {
|
|||||||
global.web3 = web3
|
global.web3 = web3
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// listen for reset requests from metamask
|
return handleResetRequest
|
||||||
controlStream.once('data', function () {
|
|
||||||
|
function handleResetRequest() {
|
||||||
resetWasRequested = true
|
resetWasRequested = true
|
||||||
// ignore if web3 was not used
|
// ignore if web3 was not used
|
||||||
if (!pageIsUsingWeb3) return
|
if (!pageIsUsingWeb3) return
|
||||||
// reload after short timeout
|
// reload after short timeout
|
||||||
triggerReset()
|
setTimeout(triggerReset, 500)
|
||||||
})
|
|
||||||
|
|
||||||
// reload the page
|
|
||||||
function triggerReset () {
|
|
||||||
setTimeout(function () {
|
|
||||||
global.location.reload()
|
|
||||||
}, 500)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reload the page
|
||||||
|
function triggerReset () {
|
||||||
|
global.location.reload()
|
||||||
|
}
|
@ -110,6 +110,27 @@ ConfigManager.prototype.setWallet = function (wallet) {
|
|||||||
this.setData(data)
|
this.setData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.setVault = function (encryptedString) {
|
||||||
|
var data = this.getData()
|
||||||
|
data.vault = encryptedString
|
||||||
|
this.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.getVault = function () {
|
||||||
|
var data = this.getData()
|
||||||
|
return ('vault' in data) && data.vault
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.getKeychains = function () {
|
||||||
|
return this.migrator.getData().keychains || []
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.setKeychains = function (keychains) {
|
||||||
|
var data = this.migrator.getData()
|
||||||
|
data.keychains = keychains
|
||||||
|
this.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
ConfigManager.prototype.getSelectedAccount = function () {
|
ConfigManager.prototype.getSelectedAccount = function () {
|
||||||
var config = this.getConfig()
|
var config = this.getConfig()
|
||||||
return config.selectedAccount
|
return config.selectedAccount
|
||||||
@ -249,6 +270,17 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) {
|
|||||||
|
|
||||||
// observable
|
// observable
|
||||||
|
|
||||||
|
ConfigManager.prototype.getSalt = function () {
|
||||||
|
var data = this.getData()
|
||||||
|
return ('salt' in data) && data.salt
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.setSalt = function(salt) {
|
||||||
|
var data = this.getData()
|
||||||
|
data.salt = salt
|
||||||
|
this.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
ConfigManager.prototype.subscribe = function (fn) {
|
ConfigManager.prototype.subscribe = function (fn) {
|
||||||
this._subs.push(fn)
|
this._subs.push(fn)
|
||||||
var unsubscribe = this.unsubscribe.bind(this, fn)
|
var unsubscribe = this.unsubscribe.bind(this, fn)
|
||||||
@ -384,3 +416,15 @@ ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositTy
|
|||||||
}
|
}
|
||||||
this.setData(data)
|
this.setData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.getGasMultiplier = function () {
|
||||||
|
var data = this.getData()
|
||||||
|
return ('gasMultiplier' in data) && data.gasMultiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) {
|
||||||
|
var data = this.getData()
|
||||||
|
|
||||||
|
data.gasMultiplier = gasMultiplier
|
||||||
|
this.setData(data)
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
const Transaction = require('ethereumjs-tx')
|
const Transaction = require('ethereumjs-tx')
|
||||||
|
|
||||||
module.exports = IdManagement
|
module.exports = IdManagement
|
||||||
@ -24,7 +25,13 @@ function IdManagement (opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.signTx = function (txParams) {
|
this.signTx = function (txParams) {
|
||||||
|
// calculate gas with custom gas multiplier
|
||||||
|
var gasMultiplier = this.configManager.getGasMultiplier() || 1
|
||||||
|
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16)
|
||||||
|
gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10))
|
||||||
|
txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber())
|
||||||
// normalize values
|
// normalize values
|
||||||
|
|
||||||
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
||||||
txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase())
|
txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase())
|
||||||
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
||||||
|
@ -2,6 +2,7 @@ const EventEmitter = require('events').EventEmitter
|
|||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
const EthQuery = require('eth-query')
|
const EthQuery = require('eth-query')
|
||||||
const KeyStore = require('eth-lightwallet').keystore
|
const KeyStore = require('eth-lightwallet').keystore
|
||||||
const clone = require('clone')
|
const clone = require('clone')
|
||||||
@ -112,6 +113,8 @@ IdentityStore.prototype.getState = function () {
|
|||||||
currentFiat: configManager.getCurrentFiat(),
|
currentFiat: configManager.getCurrentFiat(),
|
||||||
conversionRate: configManager.getConversionRate(),
|
conversionRate: configManager.getConversionRate(),
|
||||||
conversionDate: configManager.getConversionDate(),
|
conversionDate: configManager.getConversionDate(),
|
||||||
|
gasMultiplier: configManager.getGasMultiplier(),
|
||||||
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +214,7 @@ IdentityStore.prototype.exportAccount = function (address, cb) {
|
|||||||
// comes from dapp via zero-client hooked-wallet provider
|
// comes from dapp via zero-client hooked-wallet provider
|
||||||
IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
|
IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
|
||||||
const configManager = this.configManager
|
const configManager = this.configManager
|
||||||
|
|
||||||
var self = this
|
var self = this
|
||||||
// create txData obj with parameters and meta data
|
// create txData obj with parameters and meta data
|
||||||
var time = (new Date()).getTime()
|
var time = (new Date()).getTime()
|
||||||
@ -222,6 +226,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
|
|||||||
txParams: txParams,
|
txParams: txParams,
|
||||||
time: time,
|
time: time,
|
||||||
status: 'unconfirmed',
|
status: 'unconfirmed',
|
||||||
|
gasMultiplier: configManager.getGasMultiplier() || 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('addUnconfirmedTransaction:', txData)
|
console.log('addUnconfirmedTransaction:', txData)
|
||||||
@ -262,7 +267,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
|
|||||||
function estimateGas(cb){
|
function estimateGas(cb){
|
||||||
query.estimateGas(txParams, function(err, result){
|
query.estimateGas(txParams, function(err, result){
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
txData.estimatedGas = result
|
txData.estimatedGas = self.addGasBuffer(result)
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -277,6 +282,13 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentityStore.prototype.addGasBuffer = function (gasHex) {
|
||||||
|
var gas = new BN(gasHex, 16)
|
||||||
|
var buffer = new BN('100000', 10)
|
||||||
|
var result = gas.add(buffer)
|
||||||
|
return ethUtil.addHexPrefix(result.toString(16))
|
||||||
|
}
|
||||||
|
|
||||||
// comes from metamask ui
|
// comes from metamask ui
|
||||||
IdentityStore.prototype.approveTransaction = function (txId, cb) {
|
IdentityStore.prototype.approveTransaction = function (txId, cb) {
|
||||||
const configManager = this.configManager
|
const configManager = this.configManager
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const Streams = require('mississippi')
|
const Streams = require('mississippi')
|
||||||
const ObjectMultiplex = require('./obj-multiplex')
|
|
||||||
const StreamProvider = require('web3-stream-provider')
|
const StreamProvider = require('web3-stream-provider')
|
||||||
|
const ObjectMultiplex = require('./obj-multiplex')
|
||||||
const RemoteStore = require('./remote-store.js').RemoteStore
|
const RemoteStore = require('./remote-store.js').RemoteStore
|
||||||
|
|
||||||
module.exports = MetamaskInpageProvider
|
module.exports = MetamaskInpageProvider
|
||||||
@ -11,8 +11,9 @@ function MetamaskInpageProvider (connectionStream) {
|
|||||||
// setup connectionStream multiplexing
|
// setup connectionStream multiplexing
|
||||||
var multiStream = ObjectMultiplex()
|
var multiStream = ObjectMultiplex()
|
||||||
Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
|
Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
|
||||||
console.warn('MetamaskInpageProvider - lost connection to MetaMask')
|
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask'
|
||||||
if (err) throw err
|
if (err) warningMsg += '\n' + err.stack
|
||||||
|
console.warn(warningMsg)
|
||||||
})
|
})
|
||||||
self.multiStream = multiStream
|
self.multiStream = multiStream
|
||||||
|
|
||||||
@ -20,16 +21,18 @@ function MetamaskInpageProvider (connectionStream) {
|
|||||||
var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config')
|
var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config')
|
||||||
var storeStream = publicConfigStore.createStream()
|
var storeStream = publicConfigStore.createStream()
|
||||||
Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
|
Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
|
||||||
console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig')
|
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask publicConfig'
|
||||||
if (err) throw err
|
if (err) warningMsg += '\n' + err.stack
|
||||||
|
console.warn(warningMsg)
|
||||||
})
|
})
|
||||||
self.publicConfigStore = publicConfigStore
|
self.publicConfigStore = publicConfigStore
|
||||||
|
|
||||||
// connect to async provider
|
// connect to async provider
|
||||||
var asyncProvider = new StreamProvider()
|
var asyncProvider = new StreamProvider()
|
||||||
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
|
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
|
||||||
console.warn('MetamaskInpageProvider - lost connection to MetaMask provider')
|
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask provider'
|
||||||
if (err) throw err
|
if (err) warningMsg += '\n' + err.stack
|
||||||
|
console.warn(warningMsg)
|
||||||
})
|
})
|
||||||
asyncProvider.on('error', console.error.bind(console))
|
asyncProvider.on('error', console.error.bind(console))
|
||||||
self.asyncProvider = asyncProvider
|
self.asyncProvider = asyncProvider
|
||||||
|
@ -10,9 +10,9 @@ function ObjectMultiplex (opts) {
|
|||||||
var data = chunk.data
|
var data = chunk.data
|
||||||
var substream = mx.streams[name]
|
var substream = mx.streams[name]
|
||||||
if (!substream) {
|
if (!substream) {
|
||||||
console.warn('orphaned data for stream ' + name)
|
console.warn(`orphaned data for stream "${name}"`)
|
||||||
} else {
|
} else {
|
||||||
substream.push(data)
|
if (substream.push) substream.push(data)
|
||||||
}
|
}
|
||||||
return cb()
|
return cb()
|
||||||
})
|
})
|
||||||
@ -36,5 +36,9 @@ function ObjectMultiplex (opts) {
|
|||||||
}
|
}
|
||||||
return substream
|
return substream
|
||||||
}
|
}
|
||||||
|
// ignore streams (dont display orphaned data warning)
|
||||||
|
mx.ignoreStream = function (name) {
|
||||||
|
mx.streams[name] = true
|
||||||
|
}
|
||||||
return mx
|
return mx
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,7 @@ PortDuplexStream.prototype._write = function (msg, encoding, cb) {
|
|||||||
}
|
}
|
||||||
cb()
|
cb()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
// console.error(err)
|
||||||
// this.emit('error', err)
|
|
||||||
cb(new Error('PortDuplexStream - disconnected'))
|
cb(new Error('PortDuplexStream - disconnected'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ module.exports = class MetamaskController {
|
|||||||
agreeToEthWarning: this.agreeToEthWarning.bind(this),
|
agreeToEthWarning: this.agreeToEthWarning.bind(this),
|
||||||
setTOSHash: this.setTOSHash.bind(this),
|
setTOSHash: this.setTOSHash.bind(this),
|
||||||
checkTOSChange: this.checkTOSChange.bind(this),
|
checkTOSChange: this.checkTOSChange.bind(this),
|
||||||
|
setGasMultiplier: this.setGasMultiplier.bind(this),
|
||||||
|
|
||||||
// forward directly to idStore
|
// forward directly to idStore
|
||||||
createNewVault: idStore.createNewVault.bind(idStore),
|
createNewVault: idStore.createNewVault.bind(idStore),
|
||||||
@ -278,9 +279,9 @@ module.exports = class MetamaskController {
|
|||||||
checkTOSChange () {
|
checkTOSChange () {
|
||||||
try {
|
try {
|
||||||
const storedHash = this.configManager.getTOSHash() || 0
|
const storedHash = this.configManager.getTOSHash() || 0
|
||||||
if (storedHash !== global.newTOSHash) {
|
if (storedHash !== global.TOS_HASH) {
|
||||||
this.resetDisclaimer()
|
this.resetDisclaimer()
|
||||||
this.setTOSHash(global.newTOSHash)
|
this.setTOSHash(global.TOS_HASH)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error in checking TOS change.')
|
console.error('Error in checking TOS change.')
|
||||||
@ -395,4 +396,12 @@ module.exports = class MetamaskController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setGasMultiplier (gasMultiplier, cb) {
|
||||||
|
try {
|
||||||
|
this.configManager.setGasMultiplier(gasMultiplier)
|
||||||
|
cb()
|
||||||
|
} catch (e) {
|
||||||
|
cb(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ function getOldStyleData () {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
actions._setAccountManager(controller.getApi())
|
actions._setKeyringController(controller.getApi())
|
||||||
actions.update = function(stateName) {
|
actions.update = function(stateName) {
|
||||||
selectedView = stateName
|
selectedView = stateName
|
||||||
updateQueryParams(stateName)
|
updateQueryParams(stateName)
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run dev",
|
"start": "npm run dev",
|
||||||
"lint": "gulp lint",
|
"lint": "gulp lint",
|
||||||
"dev": "gulp dev --debug",
|
|
||||||
"dist": "gulp dist",
|
|
||||||
"buildCiUnits": "node test/integration/index.js",
|
"buildCiUnits": "node test/integration/index.js",
|
||||||
|
"dev": "gulp dev --debug",
|
||||||
|
"dist": "gulp dist --disableLiveReload",
|
||||||
"test": "npm run fastTest && npm run ci && npm run lint",
|
"test": "npm run fastTest && npm run ci && npm run lint",
|
||||||
"fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
"fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
||||||
"watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
"watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
||||||
@ -60,6 +60,7 @@
|
|||||||
"mississippi": "^1.2.0",
|
"mississippi": "^1.2.0",
|
||||||
"multiplex": "^6.7.0",
|
"multiplex": "^6.7.0",
|
||||||
"once": "^1.3.3",
|
"once": "^1.3.3",
|
||||||
|
"ping-pong-stream": "^1.0.0",
|
||||||
"pojo-migrator": "^2.1.0",
|
"pojo-migrator": "^2.1.0",
|
||||||
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
||||||
"post-message-stream": "^1.0.0",
|
"post-message-stream": "^1.0.0",
|
||||||
|
@ -20,7 +20,7 @@ describe('#recoverFromSeed(password, seed)', function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// stub out account manager
|
// stub out account manager
|
||||||
actions._setAccountManager({
|
actions._setKeyringController({
|
||||||
recoverFromSeed(pw, seed, cb) {
|
recoverFromSeed(pw, seed, cb) {
|
||||||
cb(null, {
|
cb(null, {
|
||||||
identities: {
|
identities: {
|
||||||
|
@ -46,7 +46,7 @@ describe('tx confirmation screen', function() {
|
|||||||
describe('cancelTx', function() {
|
describe('cancelTx', function() {
|
||||||
|
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
actions._setAccountManager({
|
actions._setKeyringController({
|
||||||
approveTransaction(txId, cb) { cb('An error!') },
|
approveTransaction(txId, cb) { cb('An error!') },
|
||||||
cancelTransaction(txId) { /* noop */ },
|
cancelTransaction(txId) { /* noop */ },
|
||||||
clearSeedWordCache(cb) { cb() },
|
clearSeedWordCache(cb) { cb() },
|
||||||
@ -75,7 +75,7 @@ describe('tx confirmation screen', function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
alert = () => {/* noop */}
|
alert = () => {/* noop */}
|
||||||
|
|
||||||
actions._setAccountManager({
|
actions._setKeyringController({
|
||||||
approveTransaction(txId, cb) { cb({message: 'An error!'}) },
|
approveTransaction(txId, cb) { cb({message: 'An error!'}) },
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ describe('tx confirmation screen', function() {
|
|||||||
|
|
||||||
describe('when there is success', function() {
|
describe('when there is success', function() {
|
||||||
it('should complete tx and go home', function() {
|
it('should complete tx and go home', function() {
|
||||||
actions._setAccountManager({
|
actions._setKeyringController({
|
||||||
approveTransaction(txId, cb) { cb() },
|
approveTransaction(txId, cb) { cb() },
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ describe('tx confirmation screen', function() {
|
|||||||
}
|
}
|
||||||
freeze(initialState)
|
freeze(initialState)
|
||||||
|
|
||||||
actions._setAccountManager({
|
actions._setKeyringController({
|
||||||
approveTransaction(txId, cb) { cb() },
|
approveTransaction(txId, cb) { cb() },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ var assert = require('assert')
|
|||||||
var IdentityStore = require('../../app/scripts/lib/idStore')
|
var IdentityStore = require('../../app/scripts/lib/idStore')
|
||||||
var configManagerGen = require('../lib/mock-config-manager')
|
var configManagerGen = require('../lib/mock-config-manager')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
|
|
||||||
describe('IdentityStore', function() {
|
describe('IdentityStore', function() {
|
||||||
@ -138,4 +139,21 @@ describe('IdentityStore', function() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#addGasBuffer', function() {
|
||||||
|
const idStore = new IdentityStore({
|
||||||
|
configManager: configManagerGen(),
|
||||||
|
ethStore: {
|
||||||
|
addAccount(acct) { accounts.push(ethUtil.addHexPrefix(acct)) },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const gas = '0x01'
|
||||||
|
const bnGas = new BN(gas, 16)
|
||||||
|
const result = idStore.addGasBuffer(gas)
|
||||||
|
const bnResult = new BN(result, 16)
|
||||||
|
|
||||||
|
assert.ok(bnResult.gt(gas), 'added more gas as buffer.')
|
||||||
|
assert.equal(result.indexOf('0x'), 0, 'include hex prefix')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -41,7 +41,7 @@ function updateQueryParams(newView) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
_setAccountManager(){},
|
_setKeyringController(){},
|
||||||
update: function(stateName) {
|
update: function(stateName) {
|
||||||
selectedView = stateName
|
selectedView = stateName
|
||||||
updateQueryParams(stateName)
|
updateQueryParams(stateName)
|
||||||
|
@ -95,7 +95,7 @@ var actions = {
|
|||||||
setRpcTarget: setRpcTarget,
|
setRpcTarget: setRpcTarget,
|
||||||
setProviderType: setProviderType,
|
setProviderType: setProviderType,
|
||||||
// hacky - need a way to get a reference to account manager
|
// hacky - need a way to get a reference to account manager
|
||||||
_setAccountManager: _setAccountManager,
|
_setKeyringController: _setKeyringController,
|
||||||
// loading overlay
|
// loading overlay
|
||||||
SHOW_LOADING: 'SHOW_LOADING_INDICATION',
|
SHOW_LOADING: 'SHOW_LOADING_INDICATION',
|
||||||
HIDE_LOADING: 'HIDE_LOADING_INDICATION',
|
HIDE_LOADING: 'HIDE_LOADING_INDICATION',
|
||||||
@ -132,13 +132,17 @@ var actions = {
|
|||||||
RECOVERY_IN_PROGRESS: 'RECOVERY_IN_PROGRESS',
|
RECOVERY_IN_PROGRESS: 'RECOVERY_IN_PROGRESS',
|
||||||
BACK_TO_UNLOCK_VIEW: 'BACK_TO_UNLOCK_VIEW',
|
BACK_TO_UNLOCK_VIEW: 'BACK_TO_UNLOCK_VIEW',
|
||||||
backToUnlockView: backToUnlockView,
|
backToUnlockView: backToUnlockView,
|
||||||
|
// SHOWING KEYCHAIN
|
||||||
|
SHOW_NEW_KEYCHAIN: 'SHOW_NEW_KEYCHAIN',
|
||||||
|
showNewKeychain: showNewKeychain,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = actions
|
module.exports = actions
|
||||||
|
|
||||||
var _accountManager = null
|
var _keyringController = null
|
||||||
function _setAccountManager (accountManager) {
|
function _setKeyringController (accountManager) {
|
||||||
_accountManager = accountManager
|
_keyringController = accountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
function goHome () {
|
function goHome () {
|
||||||
@ -153,7 +157,7 @@ function tryUnlockMetamask (password) {
|
|||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
dispatch(actions.unlockInProgress())
|
dispatch(actions.unlockInProgress())
|
||||||
_accountManager.submitPassword(password, (err, selectedAccount) => {
|
_keyringController.submitPassword(password, (err, selectedAccount) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(actions.unlockFailed())
|
dispatch(actions.unlockFailed())
|
||||||
@ -167,11 +171,11 @@ function tryUnlockMetamask (password) {
|
|||||||
function createNewVault (password, entropy) {
|
function createNewVault (password, entropy) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.createNewVaultInProgress())
|
dispatch(actions.createNewVaultInProgress())
|
||||||
_accountManager.createNewVault(password, entropy, (err, result) => {
|
_keyringController.createNewVault(password, entropy, (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showWarning(err.message))
|
return dispatch(actions.showWarning(err.message))
|
||||||
}
|
}
|
||||||
dispatch(this.goHome())
|
dispatch(this.showAccountsPage())
|
||||||
dispatch(this.hideLoadingIndication())
|
dispatch(this.hideLoadingIndication())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -185,14 +189,14 @@ function showInfoPage () {
|
|||||||
|
|
||||||
function setSelectedAddress (address) {
|
function setSelectedAddress (address) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
_accountManager.setSelectedAddress(address)
|
_keyringController.setSelectedAddress(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCurrentFiat (fiat) {
|
function setCurrentFiat (fiat) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(this.showLoadingIndication())
|
dispatch(this.showLoadingIndication())
|
||||||
_accountManager.setCurrentFiat(fiat, (data, err) => {
|
_keyringController.setCurrentFiat(fiat, (data, err) => {
|
||||||
dispatch(this.hideLoadingIndication())
|
dispatch(this.hideLoadingIndication())
|
||||||
dispatch({
|
dispatch({
|
||||||
type: this.SET_CURRENT_FIAT,
|
type: this.SET_CURRENT_FIAT,
|
||||||
@ -210,7 +214,7 @@ function signMsg (msgData) {
|
|||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
_accountManager.signMessage(msgData, (err) => {
|
_keyringController.signMessage(msgData, (err) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
@ -221,20 +225,22 @@ function signMsg (msgData) {
|
|||||||
|
|
||||||
function signTx (txData) {
|
function signTx (txData) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
web3.eth.sendTransaction(txData, (err, data) => {
|
_accountManager.setGasMultiplier(txData.gasMultiplier, (err) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
|
||||||
|
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
dispatch(actions.hideWarning())
|
web3.eth.sendTransaction(txData, (err, data) => {
|
||||||
dispatch(actions.goHome())
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
dispatch(actions.hideWarning())
|
||||||
|
dispatch(actions.goHome())
|
||||||
|
})
|
||||||
|
dispatch(this.showConfTxPage())
|
||||||
})
|
})
|
||||||
dispatch(this.showConfTxPage())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendTx (txData) {
|
function sendTx (txData) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
_accountManager.approveTransaction(txData.id, (err) => {
|
_keyringController.approveTransaction(txData.id, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
alert(err.message)
|
alert(err.message)
|
||||||
dispatch(actions.txError(err))
|
dispatch(actions.txError(err))
|
||||||
@ -260,12 +266,12 @@ function txError (err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelMsg (msgData) {
|
function cancelMsg (msgData) {
|
||||||
_accountManager.cancelMessage(msgData.id)
|
_keyringController.cancelMessage(msgData.id)
|
||||||
return actions.completedTx(msgData.id)
|
return actions.completedTx(msgData.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelTx (txData) {
|
function cancelTx (txData) {
|
||||||
_accountManager.cancelTransaction(txData.id)
|
_keyringController.cancelTransaction(txData.id)
|
||||||
return actions.completedTx(txData.id)
|
return actions.completedTx(txData.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +300,7 @@ function showInitializeMenu () {
|
|||||||
function agreeToDisclaimer () {
|
function agreeToDisclaimer () {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(this.showLoadingIndication())
|
dispatch(this.showLoadingIndication())
|
||||||
_accountManager.agreeToDisclaimer((err) => {
|
_keyringController.agreeToDisclaimer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showWarning(err.message))
|
return dispatch(actions.showWarning(err.message))
|
||||||
}
|
}
|
||||||
@ -326,6 +332,12 @@ function backToUnlockView () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showNewKeychain () {
|
||||||
|
return {
|
||||||
|
type: actions.SHOW_NEW_KEYCHAIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// unlock screen
|
// unlock screen
|
||||||
//
|
//
|
||||||
@ -358,7 +370,7 @@ function updateMetamaskState (newState) {
|
|||||||
|
|
||||||
function lockMetamask () {
|
function lockMetamask () {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
_accountManager.setLocked((err) => {
|
_keyringController.setLocked((err) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showWarning(err.message))
|
return dispatch(actions.showWarning(err.message))
|
||||||
@ -374,7 +386,7 @@ function lockMetamask () {
|
|||||||
function showAccountDetail (address) {
|
function showAccountDetail (address) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
_accountManager.setSelectedAddress(address, (err, address) => {
|
_keyringController.setSelectedAddress(address, (err, address) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showWarning(err.message))
|
return dispatch(actions.showWarning(err.message))
|
||||||
@ -445,7 +457,7 @@ function goBackToInitView () {
|
|||||||
//
|
//
|
||||||
|
|
||||||
function setRpcTarget (newRpc) {
|
function setRpcTarget (newRpc) {
|
||||||
_accountManager.setRpcTarget(newRpc)
|
_keyringController.setRpcTarget(newRpc)
|
||||||
return {
|
return {
|
||||||
type: actions.SET_RPC_TARGET,
|
type: actions.SET_RPC_TARGET,
|
||||||
value: newRpc,
|
value: newRpc,
|
||||||
@ -453,7 +465,7 @@ function setRpcTarget (newRpc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setProviderType (type) {
|
function setProviderType (type) {
|
||||||
_accountManager.setProviderType(type)
|
_keyringController.setProviderType(type)
|
||||||
return {
|
return {
|
||||||
type: actions.SET_PROVIDER_TYPE,
|
type: actions.SET_PROVIDER_TYPE,
|
||||||
value: type,
|
value: type,
|
||||||
@ -461,7 +473,7 @@ function setProviderType (type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function useEtherscanProvider () {
|
function useEtherscanProvider () {
|
||||||
_accountManager.useEtherscanProvider()
|
_keyringController.useEtherscanProvider()
|
||||||
return {
|
return {
|
||||||
type: actions.USE_ETHERSCAN_PROVIDER,
|
type: actions.USE_ETHERSCAN_PROVIDER,
|
||||||
}
|
}
|
||||||
@ -520,7 +532,7 @@ function exportAccount (address) {
|
|||||||
return function (dispatch) {
|
return function (dispatch) {
|
||||||
dispatch(self.showLoadingIndication())
|
dispatch(self.showLoadingIndication())
|
||||||
|
|
||||||
_accountManager.exportAccount(address, function (err, result) {
|
_keyringController.exportAccount(address, function (err, result) {
|
||||||
dispatch(self.hideLoadingIndication())
|
dispatch(self.hideLoadingIndication())
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -543,7 +555,7 @@ function showPrivateKey (key) {
|
|||||||
function saveAccountLabel (account, label) {
|
function saveAccountLabel (account, label) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
_accountManager.saveAccountLabel(account, label, (err) => {
|
_keyringController.saveAccountLabel(account, label, (err) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showWarning(err.message))
|
return dispatch(actions.showWarning(err.message))
|
||||||
@ -564,7 +576,7 @@ function showSendPage () {
|
|||||||
|
|
||||||
function agreeToEthWarning () {
|
function agreeToEthWarning () {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
_accountManager.agreeToEthWarning((err) => {
|
_keyringController.agreeToEthWarning((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.showEthWarning(err.message))
|
return dispatch(actions.showEthWarning(err.message))
|
||||||
}
|
}
|
||||||
@ -583,7 +595,7 @@ function showEthWarning () {
|
|||||||
|
|
||||||
function buyEth (address, amount) {
|
function buyEth (address, amount) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
_accountManager.buyEth(address, amount)
|
_keyringController.buyEth(address, amount)
|
||||||
dispatch({
|
dispatch({
|
||||||
type: actions.BUY_ETH,
|
type: actions.BUY_ETH,
|
||||||
})
|
})
|
||||||
@ -661,7 +673,7 @@ function coinShiftRquest (data, marketData) {
|
|||||||
if (response.error) return dispatch(actions.showWarning(response.error))
|
if (response.error) return dispatch(actions.showWarning(response.error))
|
||||||
var message = `
|
var message = `
|
||||||
Deposit your ${response.depositType} to the address bellow:`
|
Deposit your ${response.depositType} to the address bellow:`
|
||||||
_accountManager.createShapeShiftTx(response.deposit, response.depositType)
|
_keyringController.createShapeShiftTx(response.deposit, response.depositType)
|
||||||
dispatch(actions.showQrView(response.deposit, [message].concat(marketData)))
|
dispatch(actions.showQrView(response.deposit, [message].concat(marketData)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
|
|||||||
const DisclaimerScreen = require('./first-time/disclaimer')
|
const DisclaimerScreen = require('./first-time/disclaimer')
|
||||||
const InitializeMenuScreen = require('./first-time/init-menu')
|
const InitializeMenuScreen = require('./first-time/init-menu')
|
||||||
const CreateVaultScreen = require('./first-time/create-vault')
|
const CreateVaultScreen = require('./first-time/create-vault')
|
||||||
|
const NewKeychainScreen = require('./new-keychain')
|
||||||
// unlock
|
// unlock
|
||||||
const UnlockScreen = require('./unlock')
|
const UnlockScreen = require('./unlock')
|
||||||
// accounts
|
// accounts
|
||||||
@ -432,6 +433,9 @@ App.prototype.renderPrimary = function () {
|
|||||||
case 'sendTransaction':
|
case 'sendTransaction':
|
||||||
return h(SendTransactionScreen, {key: 'send-transaction'})
|
return h(SendTransactionScreen, {key: 'send-transaction'})
|
||||||
|
|
||||||
|
case 'newKeychain':
|
||||||
|
return h(NewKeyChainScreen, {key: 'new-keychain'})
|
||||||
|
|
||||||
case 'confTx':
|
case 'confTx':
|
||||||
return h(ConfirmTxScreen, {key: 'confirm-tx'})
|
return h(ConfirmTxScreen, {key: 'confirm-tx'})
|
||||||
|
|
||||||
|
@ -29,8 +29,10 @@ PTXP.render = function () {
|
|||||||
var account = props.accounts[address]
|
var account = props.accounts[address]
|
||||||
var balance = account ? account.balance : '0x0'
|
var balance = account ? account.balance : '0x0'
|
||||||
|
|
||||||
|
var gasMultiplier = txData.gasMultiplier
|
||||||
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
|
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
|
||||||
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16)
|
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16)
|
||||||
|
gasPrice = gasPrice.mul(new BN(gasMultiplier * 100), 10).div(new BN(100, 10))
|
||||||
var txFee = gasCost.mul(gasPrice)
|
var txFee = gasCost.mul(gasPrice)
|
||||||
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
|
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
|
||||||
var maxCost = txValue.add(txFee)
|
var maxCost = txValue.add(txFee)
|
||||||
|
58
ui/app/components/range-slider.js
Normal file
58
ui/app/components/range-slider.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
|
module.exports = RangeSlider
|
||||||
|
|
||||||
|
inherits(RangeSlider, Component)
|
||||||
|
function RangeSlider () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeSlider.prototype.render = function () {
|
||||||
|
const state = this.state || {}
|
||||||
|
const props = this.props
|
||||||
|
const onInput = props.onInput || function () {}
|
||||||
|
const name = props.name
|
||||||
|
const {
|
||||||
|
min = 0,
|
||||||
|
max = 100,
|
||||||
|
increment = 1,
|
||||||
|
defaultValue = 50,
|
||||||
|
mirrorInput = false,
|
||||||
|
} = this.props.options
|
||||||
|
const {container, input, range} = props.style
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.flex-row', {
|
||||||
|
style: container,
|
||||||
|
}, [
|
||||||
|
h('input', {
|
||||||
|
type: 'range',
|
||||||
|
name: name,
|
||||||
|
min: min,
|
||||||
|
max: max,
|
||||||
|
step: increment,
|
||||||
|
style: range,
|
||||||
|
value: state.value || defaultValue,
|
||||||
|
onChange: mirrorInput ? this.mirrorInputs.bind(this, event) : onInput,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Mirrored input for range
|
||||||
|
mirrorInput ? h('input.large-input', {
|
||||||
|
type: 'number',
|
||||||
|
name: `${name}Mirror`,
|
||||||
|
min: min,
|
||||||
|
max: max,
|
||||||
|
value: state.value || defaultValue,
|
||||||
|
step: increment,
|
||||||
|
style: input,
|
||||||
|
onChange: this.mirrorInputs.bind(this, event),
|
||||||
|
}) : null,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeSlider.prototype.mirrorInputs = function (event) {
|
||||||
|
this.setState({value: event.target.value})
|
||||||
|
}
|
33
ui/app/new-keychain.js
Normal file
33
ui/app/new-keychain.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const inherits = require('util').inherits
|
||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(NewKeychain)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(NewKeychain, Component)
|
||||||
|
function NewKeychain () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
NewKeychain.prototype.render = function () {
|
||||||
|
const props = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
background: 'blue',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h1',`Here's a list!!!!`),
|
||||||
|
h('button',
|
||||||
|
{
|
||||||
|
onClick: () => this.props.dispatch(actions.goHome())
|
||||||
|
})
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
@ -119,6 +119,15 @@ function reduceApp (state, action) {
|
|||||||
warning: null,
|
warning: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case actions.SHOW_NEW_KEYCHAIN:
|
||||||
|
return extend(appState, {
|
||||||
|
currentView: {
|
||||||
|
name: 'newKeychain',
|
||||||
|
context: appState.currentView.context
|
||||||
|
},
|
||||||
|
transForward: true,
|
||||||
|
})
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
|
|
||||||
case actions.UNLOCK_METAMASK:
|
case actions.UNLOCK_METAMASK:
|
||||||
@ -540,4 +549,3 @@ function indexForPending (state, txId) {
|
|||||||
})
|
})
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
163
ui/app/send.js
163
ui/app/send.js
@ -9,7 +9,8 @@ const numericBalance = require('./util').numericBalance
|
|||||||
const addressSummary = require('./util').addressSummary
|
const addressSummary = require('./util').addressSummary
|
||||||
const EthBalance = require('./components/eth-balance')
|
const EthBalance = require('./components/eth-balance')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const RangeSlider = require('./components/range-slider')
|
||||||
|
const Tooltip = require('./components/tooltip')
|
||||||
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
@ -50,7 +51,7 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
// Sender Profile
|
// Sender Profile
|
||||||
//
|
//
|
||||||
|
|
||||||
h('.account-data-subsection.flex-column.flex-grow', {
|
h('.account-data-subsection.flex-row.flex-grow', {
|
||||||
style: {
|
style: {
|
||||||
margin: '0 20px',
|
margin: '0 20px',
|
||||||
},
|
},
|
||||||
@ -59,10 +60,9 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
// header - identicon + nav
|
// header - identicon + nav
|
||||||
h('.flex-row.flex-space-between', {
|
h('.flex-row.flex-space-between', {
|
||||||
style: {
|
style: {
|
||||||
marginTop: 28,
|
marginTop: '15px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
|
||||||
onClick: this.back.bind(this),
|
onClick: this.back.bind(this),
|
||||||
@ -77,42 +77,53 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
// invisible place holder
|
// invisible place holder
|
||||||
h('i.fa.fa-users.fa-lg.invisible'),
|
h('i.fa.fa-users.fa-lg.invisible', {
|
||||||
|
|
||||||
]),
|
|
||||||
|
|
||||||
// account label
|
|
||||||
h('h2.font-medium.color-forest.flex-center', {
|
|
||||||
style: {
|
|
||||||
paddingTop: 8,
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
}, identity && identity.name),
|
|
||||||
|
|
||||||
// address and getter actions
|
|
||||||
h('.flex-row.flex-center', {
|
|
||||||
style: {
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
|
|
||||||
h('div', {
|
|
||||||
style: {
|
style: {
|
||||||
lineHeight: '16px',
|
marginTop: '28px',
|
||||||
},
|
},
|
||||||
}, addressSummary(address)),
|
|
||||||
|
|
||||||
]),
|
|
||||||
|
|
||||||
// balance
|
|
||||||
h('.flex-row.flex-center', [
|
|
||||||
|
|
||||||
h(EthBalance, {
|
|
||||||
value: account && account.balance,
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// account label
|
||||||
|
|
||||||
|
h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
marginTop: '10px',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h2.font-medium.color-forest.flex-center', {
|
||||||
|
style: {
|
||||||
|
paddingTop: '8px',
|
||||||
|
marginBottom: '8px',
|
||||||
|
},
|
||||||
|
}, identity && identity.name),
|
||||||
|
|
||||||
|
// address and getter actions
|
||||||
|
h('.flex-row.flex-center', {
|
||||||
|
style: {
|
||||||
|
marginBottom: '8px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
lineHeight: '16px',
|
||||||
|
},
|
||||||
|
}, addressSummary(address)),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
// balance
|
||||||
|
h('.flex-row.flex-center', [
|
||||||
|
|
||||||
|
h(EthBalance, {
|
||||||
|
value: account && account.balance,
|
||||||
|
}),
|
||||||
|
|
||||||
|
]),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -123,8 +134,8 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
style: {
|
style: {
|
||||||
background: '#EBEBEB',
|
background: '#EBEBEB',
|
||||||
color: '#AEAEAE',
|
color: '#AEAEAE',
|
||||||
marginTop: 32,
|
marginTop: '15px',
|
||||||
marginBottom: 16,
|
marginBottom: '16px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
'Send Transaction',
|
'Send Transaction',
|
||||||
@ -152,7 +163,7 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
placeholder: 'Amount',
|
placeholder: 'Amount',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
style: {
|
style: {
|
||||||
marginRight: 6,
|
marginRight: '6px',
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
persistentFormId: 'tx-amount',
|
persistentFormId: 'tx-amount',
|
||||||
@ -171,20 +182,19 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
//
|
//
|
||||||
// Optional Fields
|
// Optional Fields
|
||||||
//
|
//
|
||||||
|
|
||||||
h('h3.flex-center.text-transform-uppercase', {
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
style: {
|
style: {
|
||||||
background: '#EBEBEB',
|
background: '#EBEBEB',
|
||||||
color: '#AEAEAE',
|
color: '#AEAEAE',
|
||||||
marginTop: 16,
|
marginTop: '16px',
|
||||||
marginBottom: 16,
|
marginBottom: '16px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
'Transactional Data (optional)',
|
'Transactional Data (optional)',
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// 'data' field
|
// 'data' field
|
||||||
h('section.flex-row.flex-center', [
|
h('section.flex-column.flex-center', [
|
||||||
h('input.large-input', {
|
h('input.large-input', {
|
||||||
name: 'txData',
|
name: 'txData',
|
||||||
placeholder: '0x01234',
|
placeholder: '0x01234',
|
||||||
@ -197,6 +207,73 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
|
// custom gasPrice field
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: '5px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Transaction Fee (optional)',
|
||||||
|
h(Tooltip, {
|
||||||
|
title: `
|
||||||
|
This is used to set the transaction's gas price.
|
||||||
|
Setting it to 100% will use the full recommended value. `,
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-question-circle', {
|
||||||
|
style: {
|
||||||
|
marginLeft: '5px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('section.flex-column.flex-center', [
|
||||||
|
h('.flex-row', [
|
||||||
|
h(RangeSlider, {
|
||||||
|
name: 'gasInput',
|
||||||
|
options: {
|
||||||
|
mirrorInput: true,
|
||||||
|
defaultValue: 100,
|
||||||
|
min: 80,
|
||||||
|
max: 220,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
container: {
|
||||||
|
marginBottom: '16px',
|
||||||
|
},
|
||||||
|
range: {
|
||||||
|
width: '68vw',
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
width: '5em',
|
||||||
|
marginLeft: '5px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
fontSize: '12px',
|
||||||
|
paddingTop: '8px',
|
||||||
|
paddingLeft: '5px',
|
||||||
|
},
|
||||||
|
}, '%'),
|
||||||
|
]),
|
||||||
|
h('.flex-row', {
|
||||||
|
style: {
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '243px',
|
||||||
|
position: 'relative',
|
||||||
|
fontSize: '12px',
|
||||||
|
right: '42px',
|
||||||
|
bottom: '30px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('span', 'Cheaper'), h('span', 'Faster'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -211,11 +288,12 @@ SendTransactionScreen.prototype.back = function () {
|
|||||||
this.props.dispatch(actions.backToAccountDetail(address))
|
this.props.dispatch(actions.backToAccountDetail(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTransactionScreen.prototype.onSubmit = function () {
|
SendTransactionScreen.prototype.onSubmit = function (gasPrice) {
|
||||||
const recipient = document.querySelector('input[name="address"]').value
|
const recipient = document.querySelector('input[name="address"]').value
|
||||||
const input = document.querySelector('input[name="amount"]').value
|
const input = document.querySelector('input[name="amount"]').value
|
||||||
const value = util.normalizeEthStringToWei(input)
|
const value = util.normalizeEthStringToWei(input)
|
||||||
const txData = document.querySelector('input[name="txData"]').value
|
const txData = document.querySelector('input[name="txData"]').value
|
||||||
|
const gasMultiplier = document.querySelector('input[name="gasInput"]').value
|
||||||
const balance = this.props.balance
|
const balance = this.props.balance
|
||||||
let message
|
let message
|
||||||
|
|
||||||
@ -239,6 +317,7 @@ SendTransactionScreen.prototype.onSubmit = function () {
|
|||||||
var txParams = {
|
var txParams = {
|
||||||
from: this.props.address,
|
from: this.props.address,
|
||||||
value: '0x' + value.toString(16),
|
value: '0x' + value.toString(16),
|
||||||
|
gasMultiplier: gasMultiplier * 0.01,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
|
if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
|
||||||
|
@ -8,7 +8,7 @@ module.exports = launchApp
|
|||||||
|
|
||||||
function launchApp (opts) {
|
function launchApp (opts) {
|
||||||
var accountManager = opts.accountManager
|
var accountManager = opts.accountManager
|
||||||
actions._setAccountManager(accountManager)
|
actions._setKeyringController(accountManager)
|
||||||
|
|
||||||
// check if we are unlocked first
|
// check if we are unlocked first
|
||||||
accountManager.getState(function (err, metamaskState) {
|
accountManager.getState(function (err, metamaskState) {
|
||||||
|
Loading…
Reference in New Issue
Block a user