mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix merge conflicts from uat-next
This commit is contained in:
commit
4f1fe1da62
10
CHANGELOG.md
10
CHANGELOG.md
@ -2,6 +2,16 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
## 3.13.7 2018-1-22
|
||||
|
||||
- Add ability to bypass gas estimation loading indicator.
|
||||
- Forward failed transactions to Sentry error reporting service
|
||||
- Re-add changes from 3.13.5
|
||||
|
||||
## 3.13.6 2017-1-18
|
||||
|
||||
- Roll back changes to 3.13.4 to fix some issues with the new Infura REST provider.
|
||||
|
||||
## 3.13.5 2018-1-16
|
||||
|
||||
- Estimating gas limit for simple ether sends now faster & cheaper, by avoiding VM usage on recipients with no code.
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "MetaMask",
|
||||
"short_name": "Metamask",
|
||||
"version": "4.0.9",
|
||||
"version": "3.13.7",
|
||||
"manifest_version": 2,
|
||||
"author": "https://metamask.io",
|
||||
"description": "Ethereum Browser Extension",
|
||||
|
@ -13,6 +13,7 @@ const PortStream = require('./lib/port-stream.js')
|
||||
const NotificationManager = require('./lib/notification-manager.js')
|
||||
const MetamaskController = require('./metamask-controller')
|
||||
const firstTimeState = require('./first-time-state')
|
||||
const setupRaven = require('./setupRaven')
|
||||
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
|
||||
@ -24,6 +25,10 @@ const platform = new ExtensionPlatform()
|
||||
const notificationManager = new NotificationManager()
|
||||
global.METAMASK_NOTIFIER = notificationManager
|
||||
|
||||
// setup sentry error reporting
|
||||
const release = platform.getVersion()
|
||||
const raven = setupRaven({ release })
|
||||
|
||||
let popupIsOpen = false
|
||||
|
||||
// state persistence
|
||||
@ -72,6 +77,16 @@ function setupController (initState) {
|
||||
})
|
||||
global.metamaskController = controller
|
||||
|
||||
// report failed transactions to Sentry
|
||||
controller.txController.on(`tx:status-update`, (txId, status) => {
|
||||
if (status !== 'failed') return
|
||||
const txMeta = controller.txController.txStateManager.getTx(txId)
|
||||
raven.captureMessage('Transaction Failed', {
|
||||
// "extra" key is required by Sentry
|
||||
extra: txMeta,
|
||||
})
|
||||
})
|
||||
|
||||
// setup state persistence
|
||||
pump(
|
||||
asStream(controller.store),
|
||||
|
@ -43,6 +43,28 @@ module.exports = class TransactionController extends EventEmitter {
|
||||
txHistoryLimit: opts.txHistoryLimit,
|
||||
getNetwork: this.getNetwork.bind(this),
|
||||
})
|
||||
|
||||
this.txStateManager.getFilteredTxList({
|
||||
status: 'unapproved',
|
||||
loadingDefaults: true,
|
||||
}).forEach((tx) => {
|
||||
this.addTxDefaults(tx)
|
||||
.then((txMeta) => {
|
||||
txMeta.loadingDefaults = false
|
||||
this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot')
|
||||
}).catch((error) => {
|
||||
this.txStateManager.setTxStatusFailed(tx.id, error)
|
||||
})
|
||||
})
|
||||
|
||||
this.txStateManager.getFilteredTxList({
|
||||
status: 'approved',
|
||||
}).forEach((txMeta) => {
|
||||
const txSignError = new Error('Transaction found as "approved" during boot - possibly stuck during signing')
|
||||
this.txStateManager.setTxStatusFailed(txMeta.id, txSignError)
|
||||
})
|
||||
|
||||
|
||||
this.store = this.txStateManager.store
|
||||
this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update'))
|
||||
this.nonceTracker = new NonceTracker({
|
||||
@ -171,11 +193,17 @@ module.exports = class TransactionController extends EventEmitter {
|
||||
this.addTx(txMeta)
|
||||
this.emit('newUnapprovedTx', txMeta)
|
||||
// add default tx params
|
||||
await this.addTxDefaults(txMeta)
|
||||
|
||||
try {
|
||||
await this.addTxDefaults(txMeta)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
this.txStateManager.setTxStatusFailed(txMeta.id, error)
|
||||
throw error
|
||||
}
|
||||
txMeta.loadingDefaults = false
|
||||
// save txMeta
|
||||
this.txStateManager.updateTx(txMeta)
|
||||
|
||||
return txMeta
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ its passed ethquery
|
||||
and used to do things like calculate gas of a tx.
|
||||
*/
|
||||
|
||||
module.exports = class txProvideUtil {
|
||||
module.exports = class TxGasUtil {
|
||||
|
||||
constructor (provider) {
|
||||
this.query = new EthQuery(provider)
|
||||
}
|
||||
|
@ -8,10 +8,19 @@ const extension = require('extensionizer')
|
||||
const ExtensionPlatform = require('./platforms/extension')
|
||||
const NotificationManager = require('./lib/notification-manager')
|
||||
const notificationManager = new NotificationManager()
|
||||
const setupRaven = require('./setupRaven')
|
||||
|
||||
// create platform global
|
||||
global.platform = new ExtensionPlatform()
|
||||
|
||||
// setup sentry error reporting
|
||||
const release = global.platform.getVersion()
|
||||
setupRaven({ release })
|
||||
|
||||
// inject css
|
||||
// const css = MetaMaskUiCss()
|
||||
// injectCss(css)
|
||||
|
||||
// identify window type (popup, notification)
|
||||
const windowType = isPopupOrNotification()
|
||||
global.METAMASK_UI_TYPE = windowType
|
||||
|
26
app/scripts/setupRaven.js
Normal file
26
app/scripts/setupRaven.js
Normal file
@ -0,0 +1,26 @@
|
||||
const Raven = require('./vendor/raven.min.js')
|
||||
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
|
||||
const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
|
||||
const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
|
||||
|
||||
module.exports = setupRaven
|
||||
|
||||
// Setup raven / sentry remote error reporting
|
||||
function setupRaven(opts) {
|
||||
const { release } = opts
|
||||
let ravenTarget
|
||||
|
||||
if (METAMASK_DEBUG) {
|
||||
console.log('Setting up Sentry Remote Error Reporting: DEV')
|
||||
ravenTarget = DEV
|
||||
} else {
|
||||
console.log('Setting up Sentry Remote Error Reporting: PROD')
|
||||
ravenTarget = PROD
|
||||
}
|
||||
|
||||
Raven.config(ravenTarget, {
|
||||
release,
|
||||
}).install()
|
||||
|
||||
return Raven
|
||||
}
|
3
app/scripts/vendor/raven.min.js
vendored
Normal file
3
app/scripts/vendor/raven.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -37,3 +37,8 @@ apis.forEach(function (api) {
|
||||
|
||||
extension.runtime.reload = noop
|
||||
extension.tabs.create = noop
|
||||
extension.runtime.getManifest = function () {
|
||||
return {
|
||||
version: 'development'
|
||||
}
|
||||
}
|
154
development/states/confirm-new-ui.json
Normal file
154
development/states/confirm-new-ui.json
Normal file
@ -0,0 +1,154 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"featureFlags": {"betaUI": true},
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"name": "Send Account 1"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"name": "Send Account 2"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"name": "Send Account 3"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"name": "Send Account 4"
|
||||
}
|
||||
},
|
||||
"unapprovedTxs": {},
|
||||
"currentCurrency": "USD",
|
||||
"conversionRate": 1200.88200327,
|
||||
"conversionDate": 1489013762,
|
||||
"noActiveNotices": true,
|
||||
"frequentRpcList": [],
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"code": "0x",
|
||||
"balance": "0x47c9d71831c76efe",
|
||||
"nonce": "0x1b",
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"code": "0x",
|
||||
"balance": "0x37452b1315889f80",
|
||||
"nonce": "0xa",
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"code": "0x",
|
||||
"balance": "0x30c9d71831c76efe",
|
||||
"nonce": "0x1c",
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
}
|
||||
},
|
||||
"addressBook": [
|
||||
{
|
||||
"address": "0x06195827297c7a80a443b6894d3bdb8824b43896",
|
||||
"name": "Address Book Account 1"
|
||||
}
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"unapprovedTxs": {
|
||||
"4768706228115573": {
|
||||
"id": 4768706228115573,
|
||||
"time": 1487363153561,
|
||||
"status": "unapproved",
|
||||
"gasMultiplier": 1,
|
||||
"metamaskNetworkId": "3",
|
||||
"txParams": {
|
||||
"from": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"value": "0x1bc16d674ec80000",
|
||||
"metamaskId": 4768706228115573,
|
||||
"metamaskNetworkId": "3",
|
||||
"gas": "0xea60",
|
||||
"gasPrice": "0xba43b7400"
|
||||
}
|
||||
}
|
||||
},
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
"unapprovedPersonalMsgCount": 0,
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"fdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"c5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": [
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"currentCurrency": "USD",
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"shapeShiftTxList": [],
|
||||
"lostAccounts": [],
|
||||
"send": {
|
||||
"gasLimit": "0xea60",
|
||||
"gasPrice": "0xba43b7400",
|
||||
"gasTotal": "0xb451dc41b578",
|
||||
"tokenBalance": null,
|
||||
"from": {
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"balance": "0x37452b1315889f80"
|
||||
},
|
||||
"to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"amount": "0x1bc16d674ec80000",
|
||||
"memo": "",
|
||||
"errors": {},
|
||||
"maxModeOn": false,
|
||||
"editingTransactionId": null
|
||||
}
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "confTx",
|
||||
"detailView": null,
|
||||
"context": 0
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
"scrollToBottom": false,
|
||||
"forgottenPassword": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
154
development/states/send-edit.json
Normal file
154
development/states/send-edit.json
Normal file
@ -0,0 +1,154 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"featureFlags": {"betaUI": true},
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"name": "Send Account 1"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"name": "Send Account 2"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"name": "Send Account 3"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"name": "Send Account 4"
|
||||
}
|
||||
},
|
||||
"unapprovedTxs": {},
|
||||
"currentCurrency": "USD",
|
||||
"conversionRate": 1200.88200327,
|
||||
"conversionDate": 1489013762,
|
||||
"noActiveNotices": true,
|
||||
"frequentRpcList": [],
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"code": "0x",
|
||||
"balance": "0x47c9d71831c76efe",
|
||||
"nonce": "0x1b",
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"code": "0x",
|
||||
"balance": "0x37452b1315889f80",
|
||||
"nonce": "0xa",
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"code": "0x",
|
||||
"balance": "0x30c9d71831c76efe",
|
||||
"nonce": "0x1c",
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
}
|
||||
},
|
||||
"addressBook": [
|
||||
{
|
||||
"address": "0x06195827297c7a80a443b6894d3bdb8824b43896",
|
||||
"name": "Address Book Account 1"
|
||||
}
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"unapprovedTxs": {
|
||||
"4768706228115573": {
|
||||
"id": 4768706228115573,
|
||||
"time": 1487363153561,
|
||||
"status": "unapproved",
|
||||
"gasMultiplier": 1,
|
||||
"metamaskNetworkId": "3",
|
||||
"txParams": {
|
||||
"from": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"value": "0x1bc16d674ec80000",
|
||||
"metamaskId": 4768706228115573,
|
||||
"metamaskNetworkId": "3",
|
||||
"gas": "0xea60",
|
||||
"gasPrice": "0xba43b7400"
|
||||
}
|
||||
}
|
||||
},
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
"unapprovedPersonalMsgCount": 0,
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"fdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"c5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": [
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"currentCurrency": "USD",
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"shapeShiftTxList": [],
|
||||
"lostAccounts": [],
|
||||
"send": {
|
||||
"gasLimit": "0xea60",
|
||||
"gasPrice": "0xba43b7400",
|
||||
"gasTotal": "0xb451dc41b578",
|
||||
"tokenBalance": null,
|
||||
"from": {
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"balance": "0x37452b1315889f80"
|
||||
},
|
||||
"to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"amount": "0x1bc16d674ec80000",
|
||||
"memo": "",
|
||||
"errors": {},
|
||||
"maxModeOn": false,
|
||||
"editingTransactionId": null
|
||||
}
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "confTx",
|
||||
"detailView": null,
|
||||
"context": 0
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
"scrollToBottom": false,
|
||||
"forgottenPassword": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
133
development/states/send-new-ui.json
Normal file
133
development/states/send-new-ui.json
Normal file
@ -0,0 +1,133 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"featureFlags": {"betaUI": true},
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"name": "Send Account 1"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"name": "Send Account 2"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||
"name": "Send Account 3"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"name": "Send Account 4"
|
||||
}
|
||||
},
|
||||
"unapprovedTxs": {},
|
||||
"currentCurrency": "USD",
|
||||
"conversionRate": 1200.88200327,
|
||||
"conversionDate": 1489013762,
|
||||
"noActiveNotices": true,
|
||||
"frequentRpcList": [],
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||
"code": "0x",
|
||||
"balance": "0x47c9d71831c76efe",
|
||||
"nonce": "0x1b",
|
||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
||||
},
|
||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||
"code": "0x",
|
||||
"balance": "0x37452b1315889f80",
|
||||
"nonce": "0xa",
|
||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"
|
||||
},
|
||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||
"code": "0x",
|
||||
"balance": "0x30c9d71831c76efe",
|
||||
"nonce": "0x1c",
|
||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
},
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
}
|
||||
},
|
||||
"addressBook": [
|
||||
{
|
||||
"address": "0x06195827297c7a80a443b6894d3bdb8824b43896",
|
||||
"name": "Address Book Account 1"
|
||||
}
|
||||
],
|
||||
"tokens": [],
|
||||
"transactions": {},
|
||||
"selectedAddressTxList": [],
|
||||
"unapprovedMsgs": {},
|
||||
"unapprovedMsgCount": 0,
|
||||
"unapprovedPersonalMsgs": {},
|
||||
"unapprovedPersonalMsgCount": 0,
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"fdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||
"c5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||
"2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": [
|
||||
"0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||
"currentCurrency": "USD",
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"shapeShiftTxList": [],
|
||||
"lostAccounts": [],
|
||||
"send": {
|
||||
"gasLimit": null,
|
||||
"gasPrice": null,
|
||||
"gasTotal": "0xb451dc41b578",
|
||||
"tokenBalance": null,
|
||||
"from": "",
|
||||
"to": "",
|
||||
"amount": "0x0",
|
||||
"memo": "",
|
||||
"errors": {},
|
||||
"maxModeOn": false,
|
||||
"editingTransactionId": null
|
||||
}
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "accountDetail",
|
||||
"detailView": null,
|
||||
"context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
"scrollToBottom": false,
|
||||
"forgottenPassword": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
@ -179,7 +179,7 @@ gulp.task('deps', function (cb) {
|
||||
|
||||
gulp.task('lint', function () {
|
||||
// Ignoring node_modules, dist/firefox, and docs folders:
|
||||
return gulp.src(['app/**/*.js', 'ui/**/*.js', 'mascara/src/*.js', 'mascara/server/*.js', '!node_modules/**', '!dist/firefox/**', '!docs/**', '!app/scripts/chromereload.js', '!mascara/test/jquery-3.1.0.min.js'])
|
||||
return gulp.src(['app/**/*.js', '!app/scripts/vendor/**/*.js', 'ui/**/*.js', 'mascara/src/*.js', 'mascara/server/*.js', '!node_modules/**', '!dist/firefox/**', '!docs/**', '!app/scripts/chromereload.js', '!mascara/test/jquery-3.1.0.min.js'])
|
||||
.pipe(eslint(fs.readFileSync(path.join(__dirname, '.eslintrc'))))
|
||||
// eslint.format() outputs the lint results to the console.
|
||||
// Alternatively use eslint.formatEach() (see Docs).
|
||||
|
@ -23,6 +23,7 @@ const states = require('./development/states')
|
||||
const Selector = require('./development/selector')
|
||||
const MetamaskController = require('./app/scripts/metamask-controller')
|
||||
const firstTimeState = require('./app/scripts/first-time-state')
|
||||
const ExtensionPlatform = require('./app/scripts/platforms/extension')
|
||||
const extension = require('./development/mockExtension')
|
||||
const noop = function () {}
|
||||
|
||||
@ -67,6 +68,7 @@ const controller = new MetamaskController({
|
||||
initState: firstTimeState,
|
||||
})
|
||||
global.metamaskController = controller
|
||||
global.platform = new ExtensionPlatform
|
||||
|
||||
//
|
||||
// User Interface
|
||||
|
@ -11,7 +11,7 @@ function LoadingIndicator () {
|
||||
}
|
||||
|
||||
LoadingIndicator.prototype.render = function () {
|
||||
const { isLoading, loadingMessage } = this.props
|
||||
const { isLoading, loadingMessage, canBypass, bypass } = this.props
|
||||
|
||||
return (
|
||||
isLoading ? h('.full-flex-height', {
|
||||
@ -28,6 +28,16 @@ LoadingIndicator.prototype.render = function () {
|
||||
background: 'rgba(255, 255, 255, 0.8)',
|
||||
},
|
||||
}, [
|
||||
canBypass ? h( 'i.fa.fa-close.cursor-pointer.close-loading', {
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: '1px',
|
||||
right: '15px',
|
||||
color: '#AEAEAE',
|
||||
},
|
||||
onClick: bypass,
|
||||
}) : null,
|
||||
|
||||
h('img', {
|
||||
src: 'images/loading.svg',
|
||||
}),
|
||||
|
@ -62,8 +62,12 @@ ConfirmTxScreen.prototype.render = function () {
|
||||
h('.flex-column.flex-grow', [
|
||||
|
||||
h(LoadingIndicator, {
|
||||
isLoading: txData.loadingDefaults,
|
||||
isLoading: this.state ? !this.state.bypassLoadingScreen : txData.loadingDefaults,
|
||||
loadingMessage: 'Estimating transaction cost…',
|
||||
canBypass: true,
|
||||
bypass: () => {
|
||||
this.setState({bypassLoadingScreen: true})
|
||||
},
|
||||
}),
|
||||
|
||||
// subtitle and nav
|
||||
|
12
package.json
12
package.json
@ -76,9 +76,9 @@
|
||||
"ensnare": "^1.0.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eth-bin-to-ops": "^1.0.1",
|
||||
"eth-block-tracker": "^2.2.0",
|
||||
"eth-block-tracker": "^2.3.0",
|
||||
"eth-json-rpc-filters": "^1.2.5",
|
||||
"eth-json-rpc-infura": "^2.0.5",
|
||||
"eth-json-rpc-infura": "^2.0.11",
|
||||
"eth-keyring-controller": "^2.1.4",
|
||||
"eth-contract-metadata": "^1.1.5",
|
||||
"eth-hd-keyring": "^1.2.1",
|
||||
@ -113,7 +113,7 @@
|
||||
"iframe-stream": "^3.0.0",
|
||||
"inject-css": "^0.1.1",
|
||||
"jazzicon": "^1.2.0",
|
||||
"json-rpc-engine": "3.2.0",
|
||||
"json-rpc-engine": "^3.6.1",
|
||||
"json-rpc-middleware-stream": "^1.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.memoize": "^4.1.2",
|
||||
@ -150,6 +150,7 @@
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-select": "^1.0.0",
|
||||
"react-simple-file-input": "^2.0.0",
|
||||
"react-tippy": "^1.2.2",
|
||||
"react-toggle-button": "^2.2.0",
|
||||
"react-tooltip-component": "^0.3.0",
|
||||
"react-transition-group": "^2.2.1",
|
||||
@ -171,7 +172,7 @@
|
||||
"valid-url": "^1.0.9",
|
||||
"vreme": "^3.0.2",
|
||||
"web3": "^0.20.1",
|
||||
"web3-provider-engine": "^13.5.0",
|
||||
"web3-provider-engine": "^13.5.6",
|
||||
"web3-stream-provider": "^3.0.1",
|
||||
"xtend": "^4.0.1"
|
||||
},
|
||||
@ -189,6 +190,7 @@
|
||||
"brfs": "^1.4.3",
|
||||
"browserify": "^14.4.0",
|
||||
"chai": "^4.1.0",
|
||||
"compression": "^1.7.1",
|
||||
"coveralls": "^3.0.0",
|
||||
"deep-freeze-strict": "^1.1.1",
|
||||
"del": "^3.0.0",
|
||||
@ -200,7 +202,7 @@
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eth-json-rpc-middleware": "^1.2.7",
|
||||
"fs-promise": "^2.0.3",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp": "github:gulpjs/gulp#6d71a658c61edb3090221579d8f97dbe086ba2ed",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"gulp-if": "^2.0.2",
|
||||
"gulp-json-editor": "^2.2.1",
|
||||
|
@ -39,9 +39,8 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
await timeout()
|
||||
|
||||
// Scroll through terms
|
||||
const title = app.find('h1').text()
|
||||
// TODO Find where Metamask is getting added twice in the title
|
||||
assert.equal(title, 'MetaMaskMetaMask', 'title screen')
|
||||
const title = app.find('h1')[1]
|
||||
assert.equal(title.textContent, 'MetaMask', 'title screen')
|
||||
|
||||
// enter password
|
||||
const pwBox = app.find('#password-box')[0]
|
||||
@ -67,19 +66,19 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const detail = app.find('.wallet-view')[0]
|
||||
const detail = app.find('.account-detail-section')[0]
|
||||
assert.ok(detail, 'Account detail section loaded.')
|
||||
|
||||
await timeout(1000)
|
||||
const sandwich = app.find('.sandwich-expando')[0]
|
||||
sandwich.click()
|
||||
|
||||
const menu = app.find('.account-menu__icon')[0]
|
||||
menu.click()
|
||||
await timeout()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const lock = app.find('.account-menu__logout-button')[0]
|
||||
assert.ok(lock, 'Lock menu item found')
|
||||
lock.click()
|
||||
const menu = app.find('.menu-droppo')[0]
|
||||
const children = menu.children
|
||||
const logout = children[2]
|
||||
assert.ok(logout, 'Lock menu item found')
|
||||
logout.click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
@ -91,30 +90,36 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const detail2 = app.find('.wallet-view')[0]
|
||||
const detail2 = app.find('.account-detail-section')[0]
|
||||
assert.ok(detail2, 'Account detail section loaded again.')
|
||||
|
||||
await timeout()
|
||||
|
||||
// open account settings dropdown
|
||||
const qrButton = app.find('.wallet-view__details-button')[0]
|
||||
const qrButton = app.find('.fa.fa-ellipsis-h')[0]
|
||||
qrButton.click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const qrHeader = app.find('.editable-label__value')[0]
|
||||
const qrContainer = app.find('.qr-wrapper')[0]
|
||||
// qr code item
|
||||
const qrButton2 = app.find('.dropdown-menu-item')[1]
|
||||
qrButton2.click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const qrHeader = app.find('.qr-header')[0]
|
||||
const qrContainer = app.find('#qr-container')[0]
|
||||
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
||||
assert.ok(qrContainer, 'QR Container found')
|
||||
|
||||
await timeout()
|
||||
|
||||
const networkMenu = app.find('.network-component')[0]
|
||||
const networkMenu = app.find('.network-indicator')[0]
|
||||
networkMenu.click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const networkMenu2 = app.find('.menu-droppo')[0]
|
||||
const networkMenu2 = app.find('.network-indicator')[0]
|
||||
const children2 = networkMenu2.children
|
||||
children2.length[3]
|
||||
assert.ok(children2, 'All network options present')
|
||||
|
229
test/integration/lib/send-new-ui.js
Normal file
229
test/integration/lib/send-new-ui.js
Normal file
@ -0,0 +1,229 @@
|
||||
const reactTriggerChange = require('react-trigger-change')
|
||||
|
||||
const PASSWORD = 'password123'
|
||||
|
||||
QUnit.module('new ui send flow')
|
||||
|
||||
QUnit.test('successful send flow', (assert) => {
|
||||
const done = assert.async()
|
||||
runSendFlowTest(assert).then(done).catch((err) => {
|
||||
assert.notOk(err, `Error was thrown: ${err.stack}`)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
global.ethQuery = {
|
||||
sendTransaction: () => {},
|
||||
}
|
||||
|
||||
async function runSendFlowTest(assert, done) {
|
||||
console.log('*** start runSendFlowTest')
|
||||
const selectState = $('select')
|
||||
selectState.val('send new ui')
|
||||
reactTriggerChange(selectState[0])
|
||||
|
||||
await timeout(2000)
|
||||
|
||||
const sendScreenButton = $('button.btn-clear.hero-balance-button')
|
||||
assert.ok(sendScreenButton[1], 'send screen button present')
|
||||
sendScreenButton[1].click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const sendContainer = $('.send-v2__container')
|
||||
assert.ok(sendContainer[0], 'send container renders')
|
||||
|
||||
const sendHeader = $('.send-v2__send-header-icon')
|
||||
assert.ok(sendHeader[0], 'send screen has a header icon')
|
||||
|
||||
const sendTitle = $('.send-v2__title')
|
||||
assert.equal(sendTitle[0].textContent, 'Send Funds', 'Send screen title is correct')
|
||||
|
||||
const sendCopy = $('.send-v2__copy')
|
||||
assert.equal(sendCopy[0].textContent, 'Only send ETH to an Ethereum address.', 'Send screen has copy')
|
||||
|
||||
const sendFromField = $('.send-v2__form-field')
|
||||
assert.ok(sendFromField[0], 'send screen has a from field')
|
||||
|
||||
let sendFromFieldItemAddress = $('.account-list-item__account-name')
|
||||
assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 4', 'send from field shows correct account name')
|
||||
|
||||
const sendFromFieldItem = $('.account-list-item')
|
||||
sendFromFieldItem[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendFromDropdownList = $('.send-v2__from-dropdown__list')
|
||||
assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts')
|
||||
console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromDropdownList.children()[1]`, sendFromDropdownList.children()[1]);
|
||||
sendFromDropdownList.children()[1].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
sendFromFieldItemAddress = $('.account-list-item__account-name')
|
||||
console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromFieldItemAddress[0]`, sendFromFieldItemAddress[0]);
|
||||
assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name')
|
||||
|
||||
let sendToFieldInput = $('.send-v2__to-autocomplete__input')
|
||||
sendToFieldInput[0].focus()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendToDropdownList = $('.send-v2__from-dropdown__list')
|
||||
assert.equal(sendToDropdownList.children().length, 5, 'send to dropdown shows all accounts and address book accounts')
|
||||
|
||||
sendToDropdownList.children()[2].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendToAccountAddress = sendToFieldInput.val()
|
||||
assert.equal(sendToAccountAddress, '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', 'send to dropdown selects the correct address')
|
||||
|
||||
const sendAmountField = $('.send-v2__form-row:eq(2)')
|
||||
sendAmountField.find('.currency-display')[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendAmountFieldInput = sendAmountField.find('input:text')
|
||||
sendAmountFieldInput.val('5.1')
|
||||
reactTriggerChange(sendAmountField.find('input')[0])
|
||||
|
||||
await timeout()
|
||||
|
||||
let errorMessage = $('.send-v2__error')
|
||||
assert.equal(errorMessage[0].textContent, 'Insufficient funds.', 'send should render an insufficient fund error message')
|
||||
|
||||
sendAmountFieldInput.val('2.0')
|
||||
reactTriggerChange(sendAmountFieldInput[0])
|
||||
|
||||
await timeout()
|
||||
errorMessage = $('.send-v2__error')
|
||||
assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected')
|
||||
|
||||
const sendGasField = $('.send-v2__gas-fee-display')
|
||||
assert.equal(
|
||||
sendGasField.find('.currency-display__input-wrapper > input').val(),
|
||||
'0.000198',
|
||||
'send gas field should show estimated gas total'
|
||||
)
|
||||
assert.equal(
|
||||
sendGasField.find('.currency-display__converted-value')[0].textContent,
|
||||
'0.24 USD',
|
||||
'send gas field should show estimated gas total converted to USD'
|
||||
)
|
||||
|
||||
const sendGasOpenCustomizeModalButton = $('.send-v2__sliders-icon-container'
|
||||
)
|
||||
sendGasOpenCustomizeModalButton[0].click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const customizeGasModal = $('.send-v2__customize-gas')
|
||||
assert.ok(customizeGasModal[0], 'should render the customize gas modal')
|
||||
|
||||
const customizeGasPriceInput = $('.send-v2__gas-modal-card').first().find('input')
|
||||
customizeGasPriceInput.val(50)
|
||||
reactTriggerChange(customizeGasPriceInput[0])
|
||||
const customizeGasLimitInput = $('.send-v2__gas-modal-card').last().find('input')
|
||||
customizeGasLimitInput.val(60000)
|
||||
reactTriggerChange(customizeGasLimitInput[0])
|
||||
|
||||
await timeout()
|
||||
|
||||
const customizeGasSaveButton = $('.send-v2__customize-gas__save')
|
||||
customizeGasSaveButton[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
assert.equal(
|
||||
sendGasField.find('.currency-display__input-wrapper > input').val(),
|
||||
'0.003',
|
||||
'send gas field should show customized gas total'
|
||||
)
|
||||
assert.equal(
|
||||
sendGasField.find('.currency-display__converted-value')[0].textContent,
|
||||
'3.60 USD',
|
||||
'send gas field should show customized gas total converted to USD'
|
||||
)
|
||||
|
||||
const sendButton = $('.send-v2__next-btn')
|
||||
sendButton[0].click()
|
||||
|
||||
await timeout(2000)
|
||||
|
||||
selectState.val('send edit')
|
||||
reactTriggerChange(selectState[0])
|
||||
|
||||
await timeout(2000)
|
||||
|
||||
const confirmFromName = $('.confirm-screen-account-name').first()
|
||||
assert.equal(confirmFromName[0].textContent, 'Send Account 2', 'confirm screen should show correct from name')
|
||||
|
||||
const confirmToName = $('.confirm-screen-account-name').last()
|
||||
assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name')
|
||||
|
||||
const confirmScreenRows = $('.confirm-screen-rows')
|
||||
const confirmScreenGas = confirmScreenRows.find('.confirm-screen-row-info')[2]
|
||||
assert.equal(confirmScreenGas.textContent, '3.6 USD', 'confirm screen should show correct gas')
|
||||
const confirmScreenTotal = confirmScreenRows.find('.confirm-screen-row-info')[3]
|
||||
assert.equal(confirmScreenTotal.textContent, '2405.36 USD', 'confirm screen should show correct total')
|
||||
|
||||
const confirmScreenBackButton = $('.confirm-screen-back-button')
|
||||
confirmScreenBackButton[0].click()
|
||||
|
||||
await timeout(1000)
|
||||
|
||||
const sendFromFieldItemInEdit = $('.account-list-item')
|
||||
sendFromFieldItemInEdit[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendFromDropdownListInEdit = $('.send-v2__from-dropdown__list')
|
||||
sendFromDropdownListInEdit.children()[2].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendToFieldInputInEdit = $('.send-v2__to-autocomplete__input')
|
||||
sendToFieldInputInEdit[0].focus()
|
||||
sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb')
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendAmountFieldInEdit = $('.send-v2__form-row:eq(2)')
|
||||
sendAmountFieldInEdit.find('.currency-display')[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('input:text')
|
||||
sendAmountFieldInputInEdit.val('1.0')
|
||||
reactTriggerChange(sendAmountFieldInputInEdit[0])
|
||||
|
||||
await timeout()
|
||||
|
||||
const sendButtonInEdit = $('.send-v2__next-btn')
|
||||
sendButtonInEdit[0].click()
|
||||
|
||||
await timeout()
|
||||
|
||||
// TODO: Need a way to mock background so that we can test correct transition from editing to confirm
|
||||
selectState.val('confirm new ui')
|
||||
reactTriggerChange(selectState[0])
|
||||
|
||||
await timeout(2000)
|
||||
const confirmScreenConfirmButton = $('.confirm-screen-confirm-button')
|
||||
console.log(`+++++++++++++++++++++++++++++++= confirmScreenConfirmButton[0]`, confirmScreenConfirmButton[0]);
|
||||
confirmScreenConfirmButton[0].click()
|
||||
|
||||
await timeout(2000)
|
||||
|
||||
const txView = $('.tx-view')
|
||||
console.log(`++++++++++++++++++++++++++++++++ txView[0]`, txView[0]);
|
||||
|
||||
assert.ok(txView[0], 'Should return to the account details screen after confirming')
|
||||
}
|
||||
|
||||
function timeout (time) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, time || 1500)
|
||||
})
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
const JsonRpcEngine = require('json-rpc-engine')
|
||||
const scaffoldMiddleware = require('eth-json-rpc-middleware/scaffold')
|
||||
const TestBlockchain = require('eth-block-tracker/test/util/testBlockMiddleware')
|
||||
|
||||
module.exports = {
|
||||
createEngineForTestData,
|
||||
providerFromEngine,
|
||||
scaffoldMiddleware,
|
||||
createEthJsQueryStub,
|
||||
createStubedProvider,
|
||||
createTestProviderTools,
|
||||
}
|
||||
|
||||
|
||||
@ -19,20 +19,13 @@ function providerFromEngine (engine) {
|
||||
return provider
|
||||
}
|
||||
|
||||
function createEthJsQueryStub (stubProvider) {
|
||||
return new Proxy({}, {
|
||||
get: (obj, method) => {
|
||||
return (...params) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
stubProvider.sendAsync({ method: `eth_${method}`, params }, (err, ress) => resolve(ress.result))
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function createStubedProvider (resultStub) {
|
||||
function createTestProviderTools (opts = {}) {
|
||||
const engine = createEngineForTestData()
|
||||
engine.push(scaffoldMiddleware(resultStub))
|
||||
return providerFromEngine(engine)
|
||||
const testBlockchain = new TestBlockchain()
|
||||
// handle provided hooks
|
||||
engine.push(scaffoldMiddleware(opts.scaffold || {}))
|
||||
// handle block tracker methods
|
||||
engine.push(testBlockchain.createMiddleware())
|
||||
const provider = providerFromEngine(engine)
|
||||
return { provider, engine, testBlockchain }
|
||||
}
|
@ -3,7 +3,7 @@ const ethUtil = require('ethereumjs-util')
|
||||
const EthTx = require('ethereumjs-tx')
|
||||
const ObservableStore = require('obs-store')
|
||||
const clone = require('clone')
|
||||
const { createStubedProvider } = require('../stub/provider')
|
||||
const { createTestProviderTools } = require('../stub/provider')
|
||||
const PendingTransactionTracker = require('../../app/scripts/lib/pending-tx-tracker')
|
||||
const MockTxGen = require('../lib/mock-tx-gen')
|
||||
const sinon = require('sinon')
|
||||
@ -40,7 +40,7 @@ describe('PendingTransactionTracker', function () {
|
||||
txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'},
|
||||
}
|
||||
providerResultStub = {}
|
||||
provider = createStubedProvider(providerResultStub)
|
||||
provider = createTestProviderTools({ scaffold: providerResultStub }).provider
|
||||
|
||||
pendingTxTracker = new PendingTransactionTracker({
|
||||
provider,
|
||||
|
@ -1,11 +1,12 @@
|
||||
const assert = require('assert')
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const EthTx = require('ethereumjs-tx')
|
||||
const EthjsQuery = require('ethjs-query')
|
||||
const ObservableStore = require('obs-store')
|
||||
const sinon = require('sinon')
|
||||
const TransactionController = require('../../app/scripts/controllers/transactions')
|
||||
const TxGasUtils = require('../../app/scripts/lib/tx-gas-utils')
|
||||
const { createStubedProvider, createEthJsQueryStub } = require('../stub/provider')
|
||||
const { createTestProviderTools } = require('../stub/provider')
|
||||
|
||||
const noop = () => true
|
||||
const currentNetworkId = 42
|
||||
@ -14,11 +15,18 @@ const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f3
|
||||
|
||||
|
||||
describe('Transaction Controller', function () {
|
||||
let txController, provider, providerResultStub
|
||||
let txController, provider, providerResultStub, testBlockchain
|
||||
|
||||
beforeEach(function () {
|
||||
providerResultStub = {}
|
||||
provider = createStubedProvider(providerResultStub)
|
||||
providerResultStub = {
|
||||
// 1 gwei
|
||||
eth_gasPrice: '0x0de0b6b3a7640000',
|
||||
// by default, all accounts are external accounts (not contracts)
|
||||
eth_getCode: '0x',
|
||||
}
|
||||
const providerTools = createTestProviderTools({ scaffold: providerResultStub })
|
||||
provider = providerTools.provider
|
||||
testBlockchain = providerTools.testBlockchain
|
||||
|
||||
txController = new TransactionController({
|
||||
provider,
|
||||
@ -30,10 +38,7 @@ describe('Transaction Controller', function () {
|
||||
resolve()
|
||||
}),
|
||||
})
|
||||
txController.query = createEthJsQueryStub(provider)
|
||||
txController.txGasUtil.query = createEthJsQueryStub(provider)
|
||||
txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop })
|
||||
txController.txProviderUtils = new TxGasUtils(txController.provider)
|
||||
})
|
||||
|
||||
describe('#getState', function () {
|
||||
@ -155,15 +160,6 @@ describe('Transaction Controller', function () {
|
||||
})
|
||||
|
||||
describe('#addUnapprovedTransaction', function () {
|
||||
let addTxDefaults
|
||||
beforeEach(() => {
|
||||
addTxDefaults = txController.addTxDefaults
|
||||
txController.addTxDefaults = function addTxDefaultsStub () { return Promise.resolve() }
|
||||
|
||||
})
|
||||
afterEach(() => {
|
||||
txController.addTxDefaults = addTxDefaults
|
||||
})
|
||||
|
||||
it('should add an unapproved transaction and return a valid txMeta', function (done) {
|
||||
txController.addUnapprovedTransaction({})
|
||||
@ -219,7 +215,7 @@ describe('Transaction Controller', function () {
|
||||
var sample = {
|
||||
value: '0x01',
|
||||
}
|
||||
txController.txProviderUtils.validateTxParams(sample).then(() => {
|
||||
txController.txGasUtil.validateTxParams(sample).then(() => {
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
@ -228,7 +224,7 @@ describe('Transaction Controller', function () {
|
||||
var sample = {
|
||||
value: '-0x01',
|
||||
}
|
||||
txController.txProviderUtils.validateTxParams(sample)
|
||||
txController.txGasUtil.validateTxParams(sample)
|
||||
.then(() => done('expected to thrown on negativity values but didn\'t'))
|
||||
.catch((err) => {
|
||||
assert.ok(err, 'error')
|
||||
|
@ -1,12 +1,12 @@
|
||||
const assert = require('assert')
|
||||
const TxGasUtils = require('../../app/scripts/lib/tx-gas-utils')
|
||||
const { createStubedProvider } = require('../stub/provider')
|
||||
const { createTestProviderTools } = require('../stub/provider')
|
||||
|
||||
describe('Tx Gas Util', function () {
|
||||
let txGasUtil, provider, providerResultStub
|
||||
beforeEach(function () {
|
||||
providerResultStub = {}
|
||||
provider = createStubedProvider(providerResultStub)
|
||||
provider = createTestProviderTools({ scaffold: providerResultStub }).provider
|
||||
txGasUtil = new TxGasUtils({
|
||||
provider,
|
||||
})
|
||||
|
@ -55,6 +55,7 @@ var actions = {
|
||||
SET_NEW_ACCOUNT_FORM: 'SET_NEW_ACCOUNT_FORM',
|
||||
unlockMetamask: unlockMetamask,
|
||||
unlockFailed: unlockFailed,
|
||||
unlockSucceeded,
|
||||
showCreateVault: showCreateVault,
|
||||
showRestoreVault: showRestoreVault,
|
||||
showInitializeMenu: showInitializeMenu,
|
||||
@ -78,6 +79,7 @@ var actions = {
|
||||
// unlock screen
|
||||
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
||||
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
||||
UNLOCK_SUCCEEDED: 'UNLOCK_SUCCEEDED',
|
||||
UNLOCK_METAMASK: 'UNLOCK_METAMASK',
|
||||
LOCK_METAMASK: 'LOCK_METAMASK',
|
||||
tryUnlockMetamask: tryUnlockMetamask,
|
||||
@ -281,12 +283,14 @@ function tryUnlockMetamask (password) {
|
||||
log.debug(`background.submitPassword`)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
background.submitPassword(password, err => {
|
||||
background.submitPassword(password, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
|
||||
if (err) {
|
||||
dispatch(actions.unlockFailed(err.message))
|
||||
reject(err)
|
||||
} else {
|
||||
dispatch(actions.unlockSucceeded())
|
||||
dispatch(actions.transitionForward())
|
||||
return forceUpdateMetamaskState(dispatch).then(resolve)
|
||||
}
|
||||
@ -967,6 +971,13 @@ function unlockFailed (message) {
|
||||
}
|
||||
}
|
||||
|
||||
function unlockSucceeded (message) {
|
||||
return {
|
||||
type: actions.UNLOCK_SUCCEEDED,
|
||||
value: message,
|
||||
}
|
||||
}
|
||||
|
||||
function unlockMetamask (account) {
|
||||
return {
|
||||
type: actions.UNLOCK_METAMASK,
|
||||
|
@ -24,7 +24,7 @@ Network.prototype.render = function () {
|
||||
let iconName, hoverText
|
||||
|
||||
if (networkNumber === 'loading') {
|
||||
return h('span.pointer', {
|
||||
return h('span.pointer.network-indicator', {
|
||||
style: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
@ -43,7 +43,6 @@ function mapStateToProps (state) {
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
goHome: () => dispatch(actions.goHome()),
|
||||
addTokens: tokens => dispatch(actions.addTokens(tokens)),
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ AccountImportSubview.prototype.render = function () {
|
||||
|
||||
h('div.new-account-import-form__select-section', [
|
||||
|
||||
h('div.new-account-import-form__select-label', 'SELECT TYPE'),
|
||||
h('div.new-account-import-form__select-label', 'Select Type'),
|
||||
|
||||
h(Select, {
|
||||
className: 'new-account-import-form__select',
|
||||
|
@ -37,15 +37,20 @@ PrivateKeyImportView.prototype.render = function () {
|
||||
|
||||
return (
|
||||
h('div.new-account-import-form__private-key', [
|
||||
h('span.new-account-create-form__instruction', 'Paste your private key string here:'),
|
||||
|
||||
h('input.new-account-import-form__input-password', {
|
||||
type: 'password',
|
||||
id: 'private-key-box',
|
||||
onKeyPress: () => this.createKeyringOnEnter(),
|
||||
}),
|
||||
h('div.new-account-import-form__private-key-password-container', [
|
||||
|
||||
h('div.new-account-create-form__buttons', {}, [
|
||||
h('span.new-account-import-form__instruction', 'Paste your private key string here:'),
|
||||
|
||||
h('input.new-account-import-form__input-password', {
|
||||
type: 'password',
|
||||
id: 'private-key-box',
|
||||
onKeyPress: () => this.createKeyringOnEnter(),
|
||||
}),
|
||||
|
||||
]),
|
||||
|
||||
h('div.new-account-import-form__buttons', {}, [
|
||||
|
||||
h('button.new-account-create-form__button-cancel', {
|
||||
onClick: () => this.props.history.push(DEFAULT_ROUTE),
|
||||
|
@ -8,16 +8,18 @@ const { DEFAULT_ROUTE } = require('../../../routes')
|
||||
class NewAccountCreateForm extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
const { numberOfExistingAccounts = 0 } = props
|
||||
const newAccountNumber = numberOfExistingAccounts + 1
|
||||
|
||||
this.state = {
|
||||
newAccountName: `Account ${newAccountNumber}`,
|
||||
newAccountName: '',
|
||||
defaultAccountName: `Account ${newAccountNumber}`,
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { newAccountName } = this.state
|
||||
const { newAccountName, defaultAccountName } = this.state
|
||||
const { history, createAccount } = this.props
|
||||
|
||||
return h('div.new-account-create-form', [
|
||||
@ -28,8 +30,8 @@ class NewAccountCreateForm extends Component {
|
||||
|
||||
h('div.new-account-create-form__input-wrapper', {}, [
|
||||
h('input.new-account-create-form__input', {
|
||||
value: this.state.newAccountName,
|
||||
placeholder: 'E.g. My new account',
|
||||
value: newAccountName,
|
||||
placeholder: defaultAccountName,
|
||||
onChange: event => this.setState({ newAccountName: event.target.value }),
|
||||
}, []),
|
||||
]),
|
||||
@ -44,7 +46,7 @@ class NewAccountCreateForm extends Component {
|
||||
|
||||
h('button.new-account-create-form__button-create', {
|
||||
onClick: () => {
|
||||
createAccount(newAccountName)
|
||||
createAccount(newAccountName || defaultAccountName)
|
||||
.then(() => history.push(DEFAULT_ROUTE))
|
||||
},
|
||||
}, [
|
||||
|
@ -83,7 +83,6 @@ function mapDispatchToProps (dispatch) {
|
||||
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
|
||||
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
|
||||
updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
|
||||
goHome: () => dispatch(actions.goHome()),
|
||||
clearSend: () => dispatch(actions.clearSend()),
|
||||
setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)),
|
||||
}
|
||||
|
31
ui/app/components/tooltip-v2.js
Normal file
31
ui/app/components/tooltip-v2.js
Normal file
@ -0,0 +1,31 @@
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const ReactTippy = require('react-tippy').Tooltip
|
||||
|
||||
module.exports = Tooltip
|
||||
|
||||
inherits(Tooltip, Component)
|
||||
function Tooltip () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
Tooltip.prototype.render = function () {
|
||||
const props = this.props
|
||||
const { position, title, children, wrapperClassName } = props
|
||||
|
||||
return h('div', {
|
||||
className: wrapperClassName,
|
||||
}, [
|
||||
|
||||
h(ReactTippy, {
|
||||
title,
|
||||
position: position || 'left',
|
||||
trigger: 'mouseenter',
|
||||
hideOnClick: false,
|
||||
size: 'small',
|
||||
arrow: true,
|
||||
}, children),
|
||||
|
||||
])
|
||||
}
|
@ -4,8 +4,10 @@ const h = require('react-hyperscript')
|
||||
const { withRouter } = require('react-router-dom')
|
||||
const { compose } = require('recompose')
|
||||
const inherits = require('util').inherits
|
||||
const classnames = require('classnames')
|
||||
const Identicon = require('./identicon')
|
||||
// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
|
||||
const Tooltip = require('./tooltip-v2.js')
|
||||
const copyToClipboard = require('copy-to-clipboard')
|
||||
const actions = require('../actions')
|
||||
const BalanceComponent = require('./balance-component')
|
||||
@ -51,6 +53,7 @@ function WalletView () {
|
||||
Component.call(this)
|
||||
this.state = {
|
||||
hasCopied: false,
|
||||
copyToClipboardPressed: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,17 +143,30 @@ WalletView.prototype.render = function () {
|
||||
]),
|
||||
]),
|
||||
|
||||
|
||||
h('div.wallet-view__address', {
|
||||
onClick: () => {
|
||||
copyToClipboard(selectedAddress)
|
||||
this.setState({ hasCopied: true })
|
||||
setTimeout(() => this.setState({ hasCopied: false }), 3000)
|
||||
},
|
||||
h(Tooltip, {
|
||||
position: 'bottom',
|
||||
title: this.state.hasCopied ? 'Copied!' : 'Copy to clipboard',
|
||||
wrapperClassName: 'wallet-view__tooltip',
|
||||
}, [
|
||||
this.state.hasCopied && 'Copied to Clipboard',
|
||||
!this.state.hasCopied && `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`,
|
||||
h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }),
|
||||
h('button.wallet-view__address', {
|
||||
className: classnames({
|
||||
'wallet-view__address__pressed': this.state.copyToClipboardPressed,
|
||||
}),
|
||||
onClick: () => {
|
||||
copyToClipboard(selectedAddress)
|
||||
this.setState({ hasCopied: true })
|
||||
setTimeout(() => this.setState({ hasCopied: false }), 3000)
|
||||
},
|
||||
onMouseDown: () => {
|
||||
this.setState({ copyToClipboardPressed: true })
|
||||
},
|
||||
onMouseUp: () => {
|
||||
this.setState({ copyToClipboardPressed: false })
|
||||
},
|
||||
}, [
|
||||
`${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`,
|
||||
h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }),
|
||||
]),
|
||||
]),
|
||||
|
||||
this.renderWalletBalance(),
|
||||
|
@ -126,7 +126,6 @@ ConfirmTxScreen.prototype.render = function () {
|
||||
cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
|
||||
cancelTypedMessage: this.cancelTypedMessage.bind(this, txData),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function currentTxView (opts) {
|
||||
|
@ -55,3 +55,5 @@
|
||||
@import './pages/index.scss';
|
||||
|
||||
@import './new-account.scss';
|
||||
|
||||
@import './tooltip.scss';
|
||||
|
@ -56,11 +56,17 @@
|
||||
}
|
||||
|
||||
.new-account-import-form {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
padding: 0 30px;
|
||||
|
||||
&__select-section {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 29px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__select-label {
|
||||
@ -92,19 +98,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__private-key-password-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__instruction {
|
||||
color: $scorpion;
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
align-self: flex-start;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
&__private-key {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
@ -127,6 +139,13 @@
|
||||
align-items: center;
|
||||
margin-top: 29px;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin-top: 39px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.new-account-create-form {
|
||||
|
@ -89,6 +89,12 @@ $wallet-view-bg: $alabaster;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
&__tooltip {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
&__address {
|
||||
border-radius: 3px;
|
||||
background-color: $alto;
|
||||
@ -96,10 +102,13 @@ $wallet-view-bg: $alabaster;
|
||||
font-size: 14px;
|
||||
line-height: 12px;
|
||||
padding: 4px 12px;
|
||||
margin: 24px auto;
|
||||
font-weight: 300;
|
||||
cursor: pointer;
|
||||
flex: 0 0 auto;
|
||||
|
||||
&__pressed {
|
||||
background-color: $manatee,
|
||||
}
|
||||
}
|
||||
|
||||
&__sidebar-close {
|
||||
|
7
ui/app/css/itcss/components/tooltip.scss
Normal file
7
ui/app/css/itcss/components/tooltip.scss
Normal file
File diff suppressed because one or more lines are too long
201
ui/app/info.js
201
ui/app/info.js
@ -15,134 +15,91 @@ function InfoScreen () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
InfoScreen.prototype.renderLogo = function () {
|
||||
return (
|
||||
h('div.settings__info-logo-wrapper', [
|
||||
h('img.settings__info-logo', { src: 'images/info-logo.png' }),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
InfoScreen.prototype.renderInfoLinks = function () {
|
||||
return (
|
||||
h('div.settings__content-item.settings__content-item--without-height', [
|
||||
h('div.settings__info-link-header', 'Links'),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/privacy.html',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Privacy Policy'),
|
||||
]),
|
||||
]),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/terms.html',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Terms of Use'),
|
||||
]),
|
||||
]),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/attributions.html',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Attributions'),
|
||||
]),
|
||||
]),
|
||||
h('hr.settings__info-separator'),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
href: 'https://support.metamask.io',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Visit our Support Center'),
|
||||
]),
|
||||
]),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Visit our web site'),
|
||||
]),
|
||||
]),
|
||||
h('div.settings__info-link-item', [
|
||||
h('a', {
|
||||
target: '_blank',
|
||||
href: 'mailto:help@metamask.io?subject=Feedback',
|
||||
}, [
|
||||
h('span.settings__info-link', 'Email us!'),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
InfoScreen.prototype.render = function () {
|
||||
const state = this.props
|
||||
const version = global.platform.getVersion()
|
||||
|
||||
return (
|
||||
h('.flex-column.flex-grow', {
|
||||
style: {
|
||||
maxWidth: '400px',
|
||||
},
|
||||
}, [
|
||||
|
||||
// subtitle and nav
|
||||
h('.section-title.flex-row.flex-center', [
|
||||
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
|
||||
onClick: (event) => {
|
||||
state.dispatch(actions.goHome())
|
||||
},
|
||||
}),
|
||||
h('h2.page-subtitle', 'Info'),
|
||||
]),
|
||||
|
||||
// main view
|
||||
h('.flex-column.flex-justify-center.flex-grow.select-none', [
|
||||
h('.flex-space-around', {
|
||||
style: {
|
||||
padding: '20px',
|
||||
},
|
||||
}, [
|
||||
// current version number
|
||||
|
||||
h('.info.info-gray', [
|
||||
h('div', 'Metamask'),
|
||||
h('div', {
|
||||
style: {
|
||||
marginBottom: '10px',
|
||||
},
|
||||
}, `Version: ${version}`),
|
||||
h('div.settings__content', [
|
||||
h('div.settings__content-row', [
|
||||
h('div.settings__content-item.settings__content-item--without-height', [
|
||||
this.renderLogo(),
|
||||
h('div.settings__info-item', [
|
||||
h('div.settings__info-version-header', 'MetaMask Version'),
|
||||
h('div.settings__info-version-number', `${version}`),
|
||||
]),
|
||||
h('div.settings__info-item', [
|
||||
h(
|
||||
'div.settings__info-about',
|
||||
'MetaMask is designed and built in California.'
|
||||
),
|
||||
]),
|
||||
|
||||
h('div', {
|
||||
style: {
|
||||
marginBottom: '5px',
|
||||
}},
|
||||
[
|
||||
h('div', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/privacy.html',
|
||||
target: '_blank',
|
||||
onClick (event) { this.navigateTo(event.target.href) },
|
||||
}, [
|
||||
h('div.info', 'Privacy Policy'),
|
||||
]),
|
||||
]),
|
||||
h('div', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/terms.html',
|
||||
target: '_blank',
|
||||
onClick (event) { this.navigateTo(event.target.href) },
|
||||
}, [
|
||||
h('div.info', 'Terms of Use'),
|
||||
]),
|
||||
]),
|
||||
h('div', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/attributions.html',
|
||||
target: '_blank',
|
||||
onClick (event) { this.navigateTo(event.target.href) },
|
||||
}, [
|
||||
h('div.info', 'Attributions'),
|
||||
]),
|
||||
]),
|
||||
]
|
||||
),
|
||||
|
||||
h('hr', {
|
||||
style: {
|
||||
margin: '10px 0 ',
|
||||
width: '7em',
|
||||
},
|
||||
}),
|
||||
|
||||
h('div', {
|
||||
style: {
|
||||
paddingLeft: '30px',
|
||||
}},
|
||||
[
|
||||
h('div.fa.fa-support', [
|
||||
h('a.info', {
|
||||
href: 'https://metamask.helpscoutdocs.com/',
|
||||
target: '_blank',
|
||||
}, 'Visit our Knowledge Base'),
|
||||
]),
|
||||
|
||||
h('div', [
|
||||
h('a', {
|
||||
href: 'https://metamask.io/',
|
||||
target: '_blank',
|
||||
}, [
|
||||
h('img.icon-size', {
|
||||
src: 'images/icon-128.png',
|
||||
style: {
|
||||
// IE6-9
|
||||
filter: 'grayscale(100%)',
|
||||
// Microsoft Edge and Firefox 35+
|
||||
WebkitFilter: 'grayscale(100%)',
|
||||
},
|
||||
}),
|
||||
h('div.info', 'Visit our web site'),
|
||||
]),
|
||||
]),
|
||||
|
||||
h('div', [
|
||||
h('.fa.fa-twitter', [
|
||||
h('a.info', {
|
||||
href: 'https://twitter.com/metamask_io',
|
||||
target: '_blank',
|
||||
}, 'Follow us on Twitter'),
|
||||
]),
|
||||
]),
|
||||
|
||||
h('div.fa.fa-envelope', [
|
||||
h('a.info', {
|
||||
target: '_blank',
|
||||
href: 'mailto:support@metamask.io?subject=MetaMask Support',
|
||||
}, 'Email us!'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
this.renderInfoLinks(),
|
||||
]),
|
||||
])
|
||||
)
|
||||
|
@ -484,6 +484,11 @@ function reduceApp (state, action) {
|
||||
warning: action.value || 'Incorrect password. Try again.',
|
||||
})
|
||||
|
||||
case actions.UNLOCK_SUCCEEDED:
|
||||
return extend(appState, {
|
||||
warning: '',
|
||||
})
|
||||
|
||||
case actions.SHOW_LOADING:
|
||||
return extend(appState, {
|
||||
isLoading: true,
|
||||
|
96
yarn.lock
96
yarn.lock
@ -2503,6 +2503,24 @@ component-inherit@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
||||
|
||||
compressible@~2.0.11:
|
||||
version "2.0.12"
|
||||
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66"
|
||||
dependencies:
|
||||
mime-db ">= 1.30.0 < 2"
|
||||
|
||||
compression@^1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db"
|
||||
dependencies:
|
||||
accepts "~1.3.4"
|
||||
bytes "3.0.0"
|
||||
compressible "~2.0.11"
|
||||
debug "2.6.9"
|
||||
on-headers "~1.0.1"
|
||||
safe-buffer "5.1.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@ -3805,7 +3823,18 @@ eth-block-tracker@^1.0.7:
|
||||
pify "^2.3.0"
|
||||
tape "^4.6.3"
|
||||
|
||||
eth-block-tracker@^2.1.2, eth-block-tracker@^2.2.0, eth-block-tracker@^2.2.2:
|
||||
eth-block-tracker@^2.1.2, eth-block-tracker@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.2.2.tgz#b3d72cd82ba5ee37471d22bac4f56387ee4137cf"
|
||||
dependencies:
|
||||
async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c
|
||||
babelify "^7.3.0"
|
||||
eth-query "^2.1.0"
|
||||
ethjs-util "^0.1.3"
|
||||
pify "^2.3.0"
|
||||
tape "^4.6.3"
|
||||
|
||||
eth-block-tracker@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.0.tgz#4cb782c8ef8fde2f5dc894921ae1f5c1077c35a4"
|
||||
dependencies:
|
||||
@ -3849,7 +3878,7 @@ eth-json-rpc-filters@^1.2.5:
|
||||
json-rpc-engine "^3.4.0"
|
||||
lodash.flatmap "^4.5.0"
|
||||
|
||||
eth-json-rpc-infura@^2.0.5:
|
||||
eth-json-rpc-infura@^2.0.11:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-2.0.11.tgz#134bf54ff15e96a9116424c0db9b66aa079bfbbe"
|
||||
dependencies:
|
||||
@ -6379,16 +6408,27 @@ json-parse-better-errors@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a"
|
||||
|
||||
json-rpc-engine@3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.2.0.tgz#d34dff106c8339c337a894da801f73b1f77b1bc8"
|
||||
json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0, json-rpc-engine@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.4.0.tgz#8a1647a7f2cc7018f4802f41ec8208d281f78bfc"
|
||||
dependencies:
|
||||
async "^2.0.1"
|
||||
babel-preset-env "^1.3.2"
|
||||
babelify "^7.3.0"
|
||||
json-rpc-error "^2.0.0"
|
||||
promise-to-callback "^1.0.0"
|
||||
|
||||
json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0, json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0:
|
||||
json-rpc-engine@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.0.tgz#0cc673dcb4b71103523fec81d1bba195a457f993"
|
||||
dependencies:
|
||||
async "^2.0.1"
|
||||
babel-preset-env "^1.3.2"
|
||||
babelify "^7.3.0"
|
||||
json-rpc-error "^2.0.0"
|
||||
promise-to-callback "^1.0.0"
|
||||
|
||||
json-rpc-engine@^3.6.1:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.1.tgz#f53084726dc6dedeead0e2c457eeb997135f1e25"
|
||||
dependencies:
|
||||
@ -7341,6 +7381,10 @@ miller-rabin@^4.0.0:
|
||||
bn.js "^4.0.0"
|
||||
brorand "^1.0.1"
|
||||
|
||||
"mime-db@>= 1.30.0 < 2":
|
||||
version "1.32.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414"
|
||||
|
||||
mime-db@~1.30.0:
|
||||
version "1.30.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
|
||||
@ -8040,6 +8084,10 @@ on-finished@~2.3.0:
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
on-headers@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -8479,6 +8527,10 @@ polyfill-crypto.getrandomvalues@^1.0.0:
|
||||
dependencies:
|
||||
mersenne-twister "^1.0.1"
|
||||
|
||||
popper.js@^1.11.1:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.13.0.tgz#e1e7ff65cc43f7cf9cf16f1510a75e81f84f4565"
|
||||
|
||||
portfinder@~0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-0.2.1.tgz#b2b9b0164f9e17fa3a9c7db2304d0a75140c71ad"
|
||||
@ -9040,6 +9092,12 @@ react-testutils-additions@^15.2.0:
|
||||
object-assign "3.0.0"
|
||||
sizzle "2.3.3"
|
||||
|
||||
react-tippy@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.2.2.tgz#061467d34d29e7a5a9421822d125c451d6bb5153"
|
||||
dependencies:
|
||||
popper.js "^1.11.1"
|
||||
|
||||
react-toggle-button@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-toggle-button/-/react-toggle-button-2.2.0.tgz#a1b92143aa0df414642fcb141f0879f545bc5a89"
|
||||
@ -11553,7 +11611,31 @@ weak@^1.0.0:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.0.5"
|
||||
|
||||
web3-provider-engine@^13.3.2, web3-provider-engine@^13.5.0:
|
||||
web3-provider-engine@^13.3.2:
|
||||
version "13.4.0"
|
||||
resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.4.0.tgz#78c2794ba926d0c5b94c6e8955abb994bb8e8854"
|
||||
dependencies:
|
||||
async "^2.5.0"
|
||||
clone "^2.0.0"
|
||||
eth-block-tracker "^2.2.2"
|
||||
eth-sig-util "^1.3.0"
|
||||
ethereumjs-block "^1.2.2"
|
||||
ethereumjs-tx "^1.2.0"
|
||||
ethereumjs-util "^5.1.1"
|
||||
ethereumjs-vm "^2.0.2"
|
||||
fetch-ponyfill "^4.0.0"
|
||||
json-rpc-error "^2.0.0"
|
||||
json-stable-stringify "^1.0.1"
|
||||
promise-to-callback "^1.0.0"
|
||||
readable-stream "^2.2.9"
|
||||
request "^2.67.0"
|
||||
semaphore "^1.0.3"
|
||||
solc "^0.4.2"
|
||||
tape "^4.4.0"
|
||||
xhr "^2.2.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
web3-provider-engine@^13.5.6:
|
||||
version "13.6.0"
|
||||
resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.6.0.tgz#836f51c4ee48bd7583acf3696033779c704c2214"
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user