mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge remote-tracking branch 'origin/develop' into sync-master
* origin/develop: (107 commits) Clear Account Details in AppState (#9238) Permit all-caps addresses (#9227) Send web3 usage metrics once per origin/property (#9237) Fix import/no-extraneous-dependencies issues (#9232) Remove unused buyEth fn from bg (#9236) Fix max-statements-per-line issues (#9218) Consolidate ESLint config files (#9231) Delete page-container.component.test.js (#9229) Tidy up getAccountLink (#9223) Tidy ConnectHardwareForm#checkIfUnlocked (#9224) Fix require-unicode-regexp issues (#9212) Fix no-negated-condition issues (#9222) Fix no-empty-function issues (#9216) Fix import/extensions issues (#9217) Dedupe glob-parent versions (#9220) Fix no-template-curly-in-string issues (#9221) Fix no-process-exit issues (#9219) Fix prefer-rest-params issues (#9215) Fix no-prototype-builtins issues (#9213) Fix no-nested-ternary issues (#9214) ...
This commit is contained in:
commit
52fd72feac
@ -3,14 +3,9 @@
|
||||
node_modules/**
|
||||
dist/**
|
||||
builds/**
|
||||
test-builds/**
|
||||
test-*/**
|
||||
docs/**
|
||||
coverage/
|
||||
|
||||
app/scripts/lib/extension-instance.js
|
||||
app/scripts/chromereload.js
|
||||
app/vendor/**
|
||||
|
||||
ui/lib/blockies.js
|
||||
|
||||
package-lock.json
|
||||
|
53
.eslintrc.js
53
.eslintrc.js
@ -44,8 +44,32 @@ module.exports = {
|
||||
/* TODO: Remove these when upgrading to `@metamask/eslint-config@2` */
|
||||
'array-callback-return': 'error',
|
||||
'callback-return': 'error',
|
||||
'consistent-return': 'error',
|
||||
'global-require': 'error',
|
||||
'guard-for-in': 'error',
|
||||
'implicit-arrow-linebreak': 'error',
|
||||
'import/extensions': ['error', 'never', { 'json': 'always' }],
|
||||
'import/no-extraneous-dependencies': 'error',
|
||||
'max-statements-per-line': ['error', { 'max': 1 }],
|
||||
'no-case-declarations': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
'no-dupe-else-if': 'error',
|
||||
'no-empty': 'error',
|
||||
'no-empty-function': 'error',
|
||||
'no-eq-null': 'error',
|
||||
'no-global-assign': 'error',
|
||||
'no-loop-func': 'error',
|
||||
'no-negated-condition': 'error',
|
||||
'no-nested-ternary': 'error',
|
||||
'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }],
|
||||
'no-process-exit': 'error',
|
||||
'no-prototype-builtins': 'error',
|
||||
'no-template-curly-in-string': 'error',
|
||||
'no-useless-catch': 'error',
|
||||
'no-useless-concat': 'error',
|
||||
'prefer-rest-params': 'error',
|
||||
'prefer-spread': 'error',
|
||||
'require-unicode-regexp': 'error',
|
||||
/* End v2 rules */
|
||||
'arrow-parens': 'error',
|
||||
'no-tabs': 'error',
|
||||
@ -95,11 +119,22 @@ module.exports = {
|
||||
'logical': 'parens-new-line',
|
||||
'prop': 'parens-new-line',
|
||||
}],
|
||||
|
||||
'no-invalid-this': 'off',
|
||||
'babel/no-invalid-this': 'error',
|
||||
|
||||
'babel/semi': ['error', 'never'],
|
||||
'mocha/no-setup-in-describe': 'off',
|
||||
},
|
||||
|
||||
overrides: [{
|
||||
files: [
|
||||
'test/e2e/**/*.js',
|
||||
],
|
||||
rules: {
|
||||
'mocha/no-hooks-for-single-case': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'app/scripts/migrations/*.js',
|
||||
'*.stories.js',
|
||||
@ -114,6 +149,24 @@ module.exports = {
|
||||
rules: {
|
||||
'global-require': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'test/**/*-test.js',
|
||||
'test/**/*.spec.js',
|
||||
],
|
||||
rules: {
|
||||
// Mocha will re-assign `this` in a test context
|
||||
'babel/no-invalid-this': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'development/**/*.js',
|
||||
'test/e2e/benchmark.js',
|
||||
'test/helper.js',
|
||||
],
|
||||
rules: {
|
||||
'no-process-exit': 'off',
|
||||
},
|
||||
}],
|
||||
|
||||
settings: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
stories: ['../ui/app/components/**/*.stories.js'],
|
||||
stories: ['../ui/app/**/*.stories.js'],
|
||||
addons: [
|
||||
'@storybook/addon-knobs',
|
||||
'@storybook/addon-actions',
|
||||
|
@ -29,11 +29,13 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'),
|
||||
to: path.join('fonts', 'fontawesome'),
|
||||
},
|
||||
]),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'),
|
||||
to: path.join('fonts', 'fontawesome'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
BIN
app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf
Normal file
Binary file not shown.
BIN
app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf
Normal file
Binary file not shown.
BIN
app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf
Normal file
Binary file not shown.
@ -8,7 +8,7 @@ const accountImporter = {
|
||||
importAccount (strategy, args) {
|
||||
try {
|
||||
const importer = this.strategies[strategy]
|
||||
const privateKeyHex = importer.apply(null, args)
|
||||
const privateKeyHex = importer(...args)
|
||||
return Promise.resolve(privateKeyHex)
|
||||
} catch (e) {
|
||||
return Promise.reject(e)
|
||||
|
@ -26,7 +26,7 @@ import Migrator from './lib/migrator'
|
||||
import migrations from './migrations'
|
||||
import PortStream from 'extension-port-stream'
|
||||
import createStreamSink from './lib/createStreamSink'
|
||||
import NotificationManager from './lib/notification-manager.js'
|
||||
import NotificationManager from './lib/notification-manager'
|
||||
import MetamaskController from './metamask-controller'
|
||||
import rawFirstTimeState from './first-time-state'
|
||||
import setupSentry from './lib/setupSentry'
|
||||
@ -327,7 +327,7 @@ function setupController (initState, initLangCode) {
|
||||
const isMetaMaskInternalProcess = metamaskInternalProcessHash[processName]
|
||||
|
||||
if (metamaskBlockedPorts.includes(remotePort.name)) {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
if (isMetaMaskInternalProcess) {
|
||||
|
@ -155,8 +155,8 @@ function doctypeCheck () {
|
||||
*/
|
||||
function suffixCheck () {
|
||||
const prohibitedTypes = [
|
||||
/\.xml$/,
|
||||
/\.pdf$/,
|
||||
/\.xml$/u,
|
||||
/\.pdf$/u,
|
||||
]
|
||||
const currentUrl = window.location.pathname
|
||||
for (let i = 0; i < prohibitedTypes.length; i++) {
|
||||
@ -202,7 +202,7 @@ function blockedDomainCheck () {
|
||||
let currentRegex
|
||||
for (let i = 0; i < blockedDomains.length; i++) {
|
||||
const blockedDomain = blockedDomains[i].replace('.', '\\.')
|
||||
currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`)
|
||||
currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`, 'u')
|
||||
if (!currentRegex.test(currentUrl)) {
|
||||
return true
|
||||
}
|
||||
@ -228,7 +228,7 @@ function redirectToPhishingWarning () {
|
||||
async function domIsReady () {
|
||||
// already loaded
|
||||
if (['interactive', 'complete'].includes(document.readyState)) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
// wait for load
|
||||
return new Promise((resolve) => window.addEventListener('DOMContentLoaded', resolve, { once: true }))
|
||||
|
@ -19,7 +19,7 @@ export default class AppStateController extends EventEmitter {
|
||||
|
||||
super()
|
||||
|
||||
this.onInactiveTimeout = onInactiveTimeout || (() => {})
|
||||
this.onInactiveTimeout = onInactiveTimeout || (() => undefined)
|
||||
this.store = new ObservableStore(Object.assign({
|
||||
timeoutMinutes: 0,
|
||||
connectedStatusPopoverHasBeenShown: true,
|
||||
|
@ -5,11 +5,13 @@ export function createPendingNonceMiddleware ({ getPendingNonce }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
const { method, params } = req
|
||||
if (method !== 'eth_getTransactionCount') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
const [param, blockRef] = params
|
||||
if (blockRef !== 'pending') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
res.result = await getPendingNonce(param)
|
||||
})
|
||||
@ -19,12 +21,14 @@ export function createPendingTxMiddleware ({ getPendingTransactionByHash }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
const { method, params } = req
|
||||
if (method !== 'eth_getTransactionByHash') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
const [hash] = params
|
||||
const txMeta = getPendingTransactionByHash(hash)
|
||||
if (!txMeta) {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
res.result = formatTxMetaForRpcResult(txMeta)
|
||||
})
|
||||
|
@ -93,7 +93,8 @@ export default class NetworkController extends EventEmitter {
|
||||
|
||||
setNetworkState (network, type) {
|
||||
if (network === 'loading') {
|
||||
return this.networkStore.putState(network)
|
||||
this.networkStore.putState(network)
|
||||
return
|
||||
}
|
||||
|
||||
// type must be defined
|
||||
@ -101,7 +102,7 @@ export default class NetworkController extends EventEmitter {
|
||||
return
|
||||
}
|
||||
network = networks.networkList[type]?.chainId || network
|
||||
return this.networkStore.putState(network)
|
||||
this.networkStore.putState(network)
|
||||
}
|
||||
|
||||
isNetworkLoading () {
|
||||
@ -111,7 +112,8 @@ export default class NetworkController extends EventEmitter {
|
||||
lookupNetwork () {
|
||||
// Prevent firing when provider is not defined.
|
||||
if (!this._provider) {
|
||||
return log.warn('NetworkController - lookupNetwork aborted due to missing provider')
|
||||
log.warn('NetworkController - lookupNetwork aborted due to missing provider')
|
||||
return
|
||||
}
|
||||
const { type } = this.providerStore.getState()
|
||||
const ethQuery = new EthQuery(this._provider)
|
||||
@ -120,7 +122,8 @@ export default class NetworkController extends EventEmitter {
|
||||
const currentNetwork = this.getNetworkState()
|
||||
if (initialNetwork === currentNetwork) {
|
||||
if (err) {
|
||||
return this.setNetworkState('loading')
|
||||
this.setNetworkState('loading')
|
||||
return
|
||||
}
|
||||
log.info('web3.getNetwork returned ' + network)
|
||||
this.setNetworkState(network, type)
|
||||
|
@ -132,7 +132,7 @@ export class PermissionsController {
|
||||
const req = { method: 'eth_accounts' }
|
||||
const res = {}
|
||||
this.permissions.providerMiddlewareFunction(
|
||||
{ origin }, req, res, () => {}, _end,
|
||||
{ origin }, req, res, () => undefined, _end,
|
||||
)
|
||||
|
||||
function _end () {
|
||||
@ -187,7 +187,7 @@ export class PermissionsController {
|
||||
const res = {}
|
||||
|
||||
this.permissions.providerMiddlewareFunction(
|
||||
domain, req, res, () => {}, _end,
|
||||
domain, req, res, () => undefined, _end,
|
||||
)
|
||||
|
||||
function _end (_err) {
|
||||
|
@ -116,7 +116,8 @@ export default class PermissionsLogController {
|
||||
requestedMethods = [ 'eth_accounts' ]
|
||||
} else {
|
||||
// no-op
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
// call next with a return handler for capturing the response
|
||||
|
@ -24,12 +24,13 @@ export default function createPermissionsMethodMiddleware ({
|
||||
// Intercepting eth_accounts requests for backwards compatibility:
|
||||
// The getAccounts call below wraps the rpc-cap middleware, and returns
|
||||
// an empty array in case of errors (such as 4100:unauthorized)
|
||||
case 'eth_accounts':
|
||||
case 'eth_accounts': {
|
||||
|
||||
res.result = await getAccounts()
|
||||
return
|
||||
}
|
||||
|
||||
case 'eth_requestAccounts':
|
||||
case 'eth_requestAccounts': {
|
||||
|
||||
if (isProcessingRequestAccounts) {
|
||||
res.error = ethErrors.rpc.resourceUnavailable(
|
||||
@ -73,19 +74,21 @@ export default function createPermissionsMethodMiddleware ({
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// custom method for getting metadata from the requesting domain,
|
||||
// sent automatically by the inpage provider when it's initialized
|
||||
case 'wallet_sendDomainMetadata':
|
||||
case 'wallet_sendDomainMetadata': {
|
||||
|
||||
if (typeof req.domainMetadata?.name === 'string') {
|
||||
addDomainMetadata(req.origin, req.domainMetadata)
|
||||
}
|
||||
res.result = true
|
||||
return
|
||||
}
|
||||
|
||||
// register return handler to send accountsChanged notification
|
||||
case 'wallet_requestPermissions':
|
||||
case 'wallet_requestPermissions': {
|
||||
|
||||
if ('eth_accounts' in req.params?.[0]) {
|
||||
|
||||
@ -101,6 +104,7 @@ export default function createPermissionsMethodMiddleware ({
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
|
@ -198,7 +198,7 @@ export default class PreferencesController {
|
||||
) {
|
||||
const { type, options } = req.params
|
||||
switch (type) {
|
||||
case 'ERC20':
|
||||
case 'ERC20': {
|
||||
const result = await this._handleWatchAssetERC20(options)
|
||||
if (result instanceof Error) {
|
||||
end(result)
|
||||
@ -207,6 +207,7 @@ export default class PreferencesController {
|
||||
end()
|
||||
}
|
||||
return
|
||||
}
|
||||
default:
|
||||
end(new Error(`Asset of type ${type} not supported`))
|
||||
return
|
||||
|
@ -123,7 +123,7 @@ export default class ThreeBoxController {
|
||||
const threeBoxConfig = await Box.getConfig(this.address)
|
||||
backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask
|
||||
} catch (e) {
|
||||
if (e.message.match(/^Error: Invalid response \(404\)/)) {
|
||||
if (e.message.match(/^Error: Invalid response \(404\)/u)) {
|
||||
backupExists = false
|
||||
} else {
|
||||
throw e
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
SEND_ETHER_ACTION_KEY,
|
||||
DEPLOY_CONTRACT_ACTION_KEY,
|
||||
CONTRACT_INTERACTION_KEY,
|
||||
} from '../../../../ui/app/helpers/constants/transactions.js'
|
||||
} from '../../../../ui/app/helpers/constants/transactions'
|
||||
|
||||
import TransactionStateManager from './tx-state-manager'
|
||||
import TxGasUtil from './tx-gas-utils'
|
||||
@ -287,11 +287,11 @@ export default class TransactionController extends EventEmitter {
|
||||
/**
|
||||
* Gets default gas price, or returns `undefined` if gas price is already set
|
||||
* @param {Object} txMeta - The txMeta object
|
||||
* @returns {Promise<string>} The default gas price
|
||||
* @returns {Promise<string|undefined>} The default gas price
|
||||
*/
|
||||
async _getDefaultGasPrice (txMeta) {
|
||||
if (txMeta.txParams.gasPrice) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
const gasPrice = await this.query.gasPrice()
|
||||
|
||||
@ -560,9 +560,9 @@ export default class TransactionController extends EventEmitter {
|
||||
|
||||
// It seems that sometimes the numerical values being returned from
|
||||
// this.query.getTransactionReceipt are BN instances and not strings.
|
||||
const gasUsed = typeof txReceipt.gasUsed !== 'string'
|
||||
? txReceipt.gasUsed.toString(16)
|
||||
: txReceipt.gasUsed
|
||||
const gasUsed = typeof txReceipt.gasUsed === 'string'
|
||||
? txReceipt.gasUsed
|
||||
: txReceipt.gasUsed.toString(16)
|
||||
|
||||
txMeta.txReceipt = {
|
||||
...txReceipt,
|
||||
@ -684,7 +684,7 @@ export default class TransactionController extends EventEmitter {
|
||||
if (!('retryCount' in txMeta)) {
|
||||
txMeta.retryCount = 0
|
||||
}
|
||||
txMeta.retryCount++
|
||||
txMeta.retryCount += 1
|
||||
this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry')
|
||||
})
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
|
||||
// Exponential backoff to limit retries at publishing
|
||||
if (txBlockDistance <= Math.pow(2, retryCount) - 1) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Only auto-submit already-signed txs:
|
||||
@ -239,11 +239,11 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
async _checkIfNonceIsTaken (txMeta) {
|
||||
const address = txMeta.txParams.from
|
||||
const completed = this.getCompletedTransactions(address)
|
||||
return completed.some((other) =>
|
||||
return completed.some(
|
||||
// This is called while the transaction is in-flight, so it is possible that the
|
||||
// list of completed transactions now includes the transaction we were looking at
|
||||
// and if that is the case, don't consider the transaction to have taken its own nonce
|
||||
!(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce,
|
||||
(other) => !(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -164,10 +164,10 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams)
|
||||
}
|
||||
|
||||
this.once(`${txMeta.id}:signed`, function () {
|
||||
this.once(`${txMeta.id}:signed`, () => {
|
||||
this.removeAllListeners(`${txMeta.id}:rejected`)
|
||||
})
|
||||
this.once(`${txMeta.id}:rejected`, function () {
|
||||
this.once(`${txMeta.id}:rejected`, () => {
|
||||
this.removeAllListeners(`${txMeta.id}:signed`)
|
||||
})
|
||||
// initialize history
|
||||
@ -424,7 +424,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
@param {erroObject} err - error object
|
||||
*/
|
||||
setTxStatusFailed (txId, err) {
|
||||
const error = !err ? new Error('Internal metamask failure') : err
|
||||
const error = err || new Error('Internal metamask failure')
|
||||
|
||||
const txMeta = this.getTx(txId)
|
||||
txMeta.err = {
|
||||
|
@ -35,7 +35,7 @@ import LocalMessageDuplexStream from 'post-message-stream'
|
||||
import { initProvider } from '@metamask/inpage-provider'
|
||||
|
||||
// TODO:deprecate:2020
|
||||
import setupWeb3 from './lib/setupWeb3.js'
|
||||
import setupWeb3 from './lib/setupWeb3'
|
||||
|
||||
restoreContextAfterImports()
|
||||
|
||||
|
@ -25,7 +25,7 @@ export default class ComposableObservableStore extends ObservableStore {
|
||||
this.config = config
|
||||
this.removeAllListeners()
|
||||
for (const key in config) {
|
||||
if (config.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(config, key)) {
|
||||
config[key].subscribe((state) => {
|
||||
this.updateState({ [key]: state })
|
||||
})
|
||||
@ -42,7 +42,7 @@ export default class ComposableObservableStore extends ObservableStore {
|
||||
getFlatState () {
|
||||
let flatState = {}
|
||||
for (const key in this.config) {
|
||||
if (this.config.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.config, key)) {
|
||||
const controller = this.config[key]
|
||||
const state = controller.getState ? controller.getState() : controller.state
|
||||
flatState = { ...flatState, ...state }
|
||||
|
@ -256,7 +256,8 @@ export default class AccountTracker {
|
||||
ethContract.balances(addresses, ethBalance, (error, result) => {
|
||||
if (error) {
|
||||
log.warn(`MetaMask - Account Tracker single call balance fetch failed`, error)
|
||||
return Promise.all(addresses.map(this._updateAccount.bind(this)))
|
||||
Promise.all(addresses.map(this._updateAccount.bind(this)))
|
||||
return
|
||||
}
|
||||
addresses.forEach((address, index) => {
|
||||
const balance = bnToHex(result[index])
|
||||
|
@ -2,9 +2,6 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors'
|
||||
import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util'
|
||||
|
||||
export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) {
|
||||
|
||||
eventData.eventOpts['category'] = 'Background'
|
||||
|
||||
const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState })
|
||||
if (stateEventData.participateInMetaMetrics) {
|
||||
sendMetaMetricsEvent({
|
||||
|
@ -14,7 +14,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) {
|
||||
return function methodMiddleware (req, res, next, end) {
|
||||
switch (req.method) {
|
||||
|
||||
case 'metamask_logInjectedWeb3Usage':
|
||||
case 'metamask_logInjectedWeb3Usage': {
|
||||
|
||||
const { action, name } = req.params[0]
|
||||
|
||||
@ -32,6 +32,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) {
|
||||
|
||||
res.result = true
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
return next()
|
||||
|
@ -5,7 +5,7 @@ import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
const hexRe = /^[0-9A-Fa-f]+$/ug
|
||||
import log from 'loglevel'
|
||||
|
||||
/**
|
||||
@ -65,7 +65,8 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -82,19 +83,24 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
return reject(new Error('MetaMask Decryption: from field is required.'))
|
||||
reject(new Error('MetaMask Decryption: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'decrypted':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.'))
|
||||
return
|
||||
case 'errored':
|
||||
return reject(new Error('This message cannot be decrypted'))
|
||||
reject(new Error('This message cannot be decrypted'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -248,7 +254,7 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('DecryptMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`DecryptMessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -62,7 +62,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -79,17 +80,21 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (address, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!address) {
|
||||
return reject(new Error('MetaMask Message: address field is required.'))
|
||||
reject(new Error('MetaMask Message: address field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(address, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'received':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||
reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -243,7 +248,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('EncryptionPublicKeyManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`EncryptionPublicKeyManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import urlUtil from 'url'
|
||||
import extension from 'extensionizer'
|
||||
import resolveEnsToIpfsContentId from './resolver.js'
|
||||
import resolveEnsToIpfsContentId from './resolver'
|
||||
|
||||
const supportedTopLevelDomains = ['eth']
|
||||
|
||||
|
@ -30,11 +30,11 @@ function freeze (target, key, value, enumerable = true) {
|
||||
configurable: false, writable: false,
|
||||
}
|
||||
|
||||
if (value !== undefined) {
|
||||
if (value === undefined) {
|
||||
target[key] = deepFreeze(target[key])
|
||||
} else {
|
||||
opts.value = deepFreeze(value)
|
||||
opts.enumerable = enumerable
|
||||
} else {
|
||||
target[key] = deepFreeze(target[key])
|
||||
}
|
||||
|
||||
Object.defineProperty(target, key, opts)
|
||||
|
@ -40,7 +40,7 @@ export default async function getFirstPreferredLangCode () {
|
||||
|
||||
const firstPreferredLangCode = userPreferredLocaleCodes
|
||||
.map((code) => code.toLowerCase().replace('_', '-'))
|
||||
.find((code) => existingLocaleCodes.hasOwnProperty(code))
|
||||
.find((code) => Object.prototype.hasOwnProperty.call(existingLocaleCodes, code))
|
||||
|
||||
return existingLocaleCodes[firstPreferredLangCode] || 'en'
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ export default class MessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ export default class MessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('MessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`MessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -15,9 +15,7 @@ const callbackNoop = function (err) {
|
||||
*
|
||||
*/
|
||||
export default function nodeify (fn, context) {
|
||||
return function () {
|
||||
// parse arguments
|
||||
const args = [].slice.call(arguments)
|
||||
return function (...args) {
|
||||
const lastArg = args[args.length - 1]
|
||||
const lastArgIsCallback = typeof lastArg === 'function'
|
||||
let callback
|
||||
|
@ -5,7 +5,7 @@ import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
const hexRe = /^[0-9A-Fa-f]+$/ug
|
||||
import log from 'loglevel'
|
||||
|
||||
/**
|
||||
@ -68,7 +68,8 @@ export default class PersonalMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -85,17 +86,21 @@ export default class PersonalMessageManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
return reject(new Error('MetaMask Message Signature: from field is required.'))
|
||||
reject(new Error('MetaMask Message Signature: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'signed':
|
||||
return resolve(data.rawSig)
|
||||
resolve(data.rawSig)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -3,5 +3,6 @@ const MAX = Number.MAX_SAFE_INTEGER
|
||||
let idCounter = Math.round(Math.random() * MAX)
|
||||
export default function createRandomId () {
|
||||
idCounter = idCounter % MAX
|
||||
// eslint-disable-next-line no-plusplus
|
||||
return idCounter++
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export default function setupSentry ({ release, getState }) {
|
||||
let sentryTarget
|
||||
|
||||
if (METAMASK_DEBUG) {
|
||||
return
|
||||
return undefined
|
||||
} else if (METAMASK_ENVIRONMENT === 'production') {
|
||||
if (!process.env.SENTRY_DSN) {
|
||||
throw new Error(`Missing SENTRY_DSN environment variable in production environment`)
|
||||
|
@ -3,7 +3,7 @@
|
||||
// TODO:deprecate:2020
|
||||
// Delete this file
|
||||
|
||||
import 'web3/dist/web3.min.js'
|
||||
import 'web3/dist/web3.min'
|
||||
|
||||
const shouldLogUsage = !([
|
||||
'docs.metamask.io',
|
||||
|
@ -61,7 +61,8 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -154,7 +155,7 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
}, 'Signing data must be valid EIP-712 typed data.')
|
||||
break
|
||||
case 'V3':
|
||||
case 'V4':
|
||||
case 'V4': {
|
||||
assert.equal(typeof params.data, 'string', '"params.data" must be a string.')
|
||||
let data
|
||||
assert.doesNotThrow(() => {
|
||||
@ -167,6 +168,7 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
const activeChainId = parseInt(this.networkController.getNetworkState())
|
||||
chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
assert.fail(`Unknown typed data version "${params.version}"`)
|
||||
}
|
||||
@ -291,7 +293,7 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('TypedMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`TypedMessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -55,19 +55,19 @@ const getEnvironmentType = (url = window.location.href) => getEnvironmentTypeMem
|
||||
*/
|
||||
const getPlatform = (_) => {
|
||||
const ua = window.navigator.userAgent
|
||||
if (ua.search('Firefox') !== -1) {
|
||||
return PLATFORM_FIREFOX
|
||||
} else {
|
||||
if (ua.search('Firefox') === -1) {
|
||||
if (window && window.chrome && window.chrome.ipcRenderer) {
|
||||
return PLATFORM_BRAVE
|
||||
} else if (ua.search('Edge') !== -1) {
|
||||
return PLATFORM_EDGE
|
||||
} else if (ua.search('OPR') !== -1) {
|
||||
return PLATFORM_OPERA
|
||||
} else {
|
||||
return PLATFORM_CHROME
|
||||
}
|
||||
if (ua.search('Edge') !== -1) {
|
||||
return PLATFORM_EDGE
|
||||
}
|
||||
if (ua.search('OPR') !== -1) {
|
||||
return PLATFORM_OPERA
|
||||
}
|
||||
return PLATFORM_CHROME
|
||||
}
|
||||
return PLATFORM_FIREFOX
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,12 +135,12 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) {
|
||||
/**
|
||||
* Returns an Error if extension.runtime.lastError is present
|
||||
* this is a workaround for the non-standard error object that's used
|
||||
* @returns {Error}
|
||||
* @returns {Error|undefined}
|
||||
*/
|
||||
function checkForError () {
|
||||
const lastError = extension.runtime.lastError
|
||||
if (!lastError) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
// if it quacks like an Error, its an Error
|
||||
if (lastError.stack && lastError.message) {
|
||||
|
@ -24,7 +24,7 @@ import createOriginMiddleware from './lib/createOriginMiddleware'
|
||||
import createTabIdMiddleware from './lib/createTabIdMiddleware'
|
||||
import createOnboardingMiddleware from './lib/createOnboardingMiddleware'
|
||||
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'
|
||||
import { setupMultiplex } from './lib/stream-utils.js'
|
||||
import { setupMultiplex } from './lib/stream-utils'
|
||||
import KeyringController from 'eth-keyring-controller'
|
||||
import EnsController from './controllers/ens'
|
||||
import NetworkController from './controllers/network'
|
||||
@ -47,7 +47,6 @@ import { PermissionsController } from './controllers/permissions'
|
||||
import getRestrictedMethods from './controllers/permissions/restrictedMethods'
|
||||
import nodeify from './lib/nodeify'
|
||||
import accountImporter from './account-import-strategies'
|
||||
import getBuyEthUrl from './lib/buy-eth-url'
|
||||
import selectChainId from './lib/select-chain-id'
|
||||
import { Mutex } from 'await-semaphore'
|
||||
import { version } from '../manifest/_base.json'
|
||||
@ -449,7 +448,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
setCurrentLocale: this.setCurrentLocale.bind(this),
|
||||
markPasswordForgotten: this.markPasswordForgotten.bind(this),
|
||||
unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
|
||||
buyEth: this.buyEth.bind(this),
|
||||
safelistPhishingDomain: this.safelistPhishingDomain.bind(this),
|
||||
getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()),
|
||||
getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()),
|
||||
@ -601,8 +599,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.selectFirstIdentity()
|
||||
}
|
||||
return vault
|
||||
} catch (err) {
|
||||
throw err
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
@ -658,8 +654,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
return vault
|
||||
} catch (err) {
|
||||
throw err
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
@ -714,15 +708,16 @@ export default class MetamaskController extends EventEmitter {
|
||||
Object.keys(accountTokens).forEach((address) => {
|
||||
const checksummedAddress = ethUtil.toChecksumAddress(address)
|
||||
filteredAccountTokens[checksummedAddress] = {}
|
||||
Object.keys(accountTokens[address]).forEach(
|
||||
(networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ?
|
||||
accountTokens[address][networkType] :
|
||||
accountTokens[address][networkType].filter(({ address }) => {
|
||||
const tokenAddress = ethUtil.toChecksumAddress(address)
|
||||
return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true
|
||||
})
|
||||
),
|
||||
)
|
||||
Object.keys(accountTokens[address]).forEach((networkType) => {
|
||||
filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet'
|
||||
? (
|
||||
accountTokens[address][networkType].filter(({ address }) => {
|
||||
const tokenAddress = ethUtil.toChecksumAddress(address)
|
||||
return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true
|
||||
})
|
||||
)
|
||||
: accountTokens[address][networkType]
|
||||
})
|
||||
})
|
||||
|
||||
const preferences = {
|
||||
@ -1349,7 +1344,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
* Triggers the callback in newUnsignedTypedMessage.
|
||||
*
|
||||
* @param {Object} msgParams - The params passed to eth_signTypedData.
|
||||
* @returns {Object} - Full state update.
|
||||
* @returns {Object|undefined} - Full state update.
|
||||
*/
|
||||
async signTypedMessage (msgParams) {
|
||||
log.info('MetaMaskController - eth_signTypedData')
|
||||
@ -1372,6 +1367,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
} catch (error) {
|
||||
log.info('MetaMaskController - eth_signTypedData failed.', error)
|
||||
this.typedMessageManager.errorMessage(msgId, error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
@ -1401,13 +1397,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
* @returns {Object} - MetaMask state
|
||||
*/
|
||||
async createCancelTransaction (originalTxId, customGasPrice) {
|
||||
try {
|
||||
await this.txController.createCancelTransaction(originalTxId, customGasPrice)
|
||||
const state = await this.getState()
|
||||
return state
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
await this.txController.createCancelTransaction(originalTxId, customGasPrice)
|
||||
const state = await this.getState()
|
||||
return state
|
||||
}
|
||||
|
||||
async createSpeedUpTransaction (originalTxId, customGasPrice, customGasLimit) {
|
||||
@ -1526,7 +1518,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
const api = this.getApi()
|
||||
const dnode = Dnode(api)
|
||||
// report new active controller connection
|
||||
this.activeControllerConnections++
|
||||
this.activeControllerConnections += 1
|
||||
this.emit('controllerConnectionChanged', this.activeControllerConnections)
|
||||
// connect dnode api to remote connection
|
||||
pump(
|
||||
@ -1535,7 +1527,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
outStream,
|
||||
(err) => {
|
||||
// report new active controller connection
|
||||
this.activeControllerConnections--
|
||||
this.activeControllerConnections -= 1
|
||||
this.emit('controllerConnectionChanged', this.activeControllerConnections)
|
||||
// report any error
|
||||
if (err) {
|
||||
@ -1850,6 +1842,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
customVariables,
|
||||
eventOpts: {
|
||||
action,
|
||||
category: 'Background',
|
||||
name,
|
||||
},
|
||||
},
|
||||
@ -1884,24 +1877,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method for forwarding the user to the easiest way to obtain ether,
|
||||
* or the network "gas" currency, for the current selected network.
|
||||
*
|
||||
* @param {string} address - The address to fund.
|
||||
* @param {string} amount - The amount of ether desired, as a base 10 string.
|
||||
*/
|
||||
buyEth (address, amount) {
|
||||
if (!amount) {
|
||||
amount = '5'
|
||||
}
|
||||
const network = this.networkController.getNetworkState()
|
||||
const url = getBuyEthUrl({ network, address, amount })
|
||||
if (url) {
|
||||
this.platform.openTab({ url })
|
||||
}
|
||||
}
|
||||
|
||||
// network
|
||||
/**
|
||||
* A method for selecting a custom URL for an ethereum RPC provider and updating it
|
||||
|
@ -14,7 +14,9 @@ export default {
|
||||
versionedData.data.config.provider.type = 'rpc'
|
||||
versionedData.data.config.provider.rpcTarget = 'https://rpc.metamask.io/'
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ export default {
|
||||
if (versionedData.data.config.provider.rpcTarget === oldTestRpc) {
|
||||
versionedData.data.config.provider.rpcTarget = newTestRpc
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
@ -25,7 +25,9 @@ export default {
|
||||
break
|
||||
// No default
|
||||
}
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(safeVersionedData)
|
||||
},
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ function getHighestContinuousFrom (txList, startPoint) {
|
||||
|
||||
let highest = startPoint
|
||||
while (nonces.includes(highest)) {
|
||||
highest++
|
||||
highest += 1
|
||||
}
|
||||
|
||||
return highest
|
||||
|
@ -3,7 +3,7 @@ import dnode from 'dnode'
|
||||
import { EventEmitter } from 'events'
|
||||
import PortStream from 'extension-port-stream'
|
||||
import extension from 'extensionizer'
|
||||
import { setupMultiplex } from './lib/stream-utils.js'
|
||||
import { setupMultiplex } from './lib/stream-utils'
|
||||
import { getEnvironmentType } from './lib/util'
|
||||
import ExtensionPlatform from './platforms/extension'
|
||||
|
||||
|
@ -24,7 +24,7 @@ import Eth from 'ethjs'
|
||||
import EthQuery from 'eth-query'
|
||||
import launchMetaMaskUi from '../../ui'
|
||||
import StreamProvider from 'web3-stream-provider'
|
||||
import { setupMultiplex } from './lib/stream-utils.js'
|
||||
import { setupMultiplex } from './lib/stream-utils'
|
||||
import log from 'loglevel'
|
||||
|
||||
start().catch(log.error)
|
||||
@ -62,7 +62,8 @@ async function start () {
|
||||
const container = document.getElementById('app-content')
|
||||
initializeUi(tab, container, connectionStream, (err, store) => {
|
||||
if (err) {
|
||||
return displayCriticalError(container, err)
|
||||
displayCriticalError(container, err)
|
||||
return
|
||||
}
|
||||
|
||||
const state = store.getState()
|
||||
@ -102,7 +103,8 @@ async function queryCurrentActiveTab (windowType) {
|
||||
function initializeUi (activeTab, container, connectionStream, cb) {
|
||||
connectToAccountManager(connectionStream, (err, backgroundConnection) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
cb(err)
|
||||
return
|
||||
}
|
||||
|
||||
launchMetaMaskUi({
|
||||
|
@ -25,7 +25,7 @@ module.exports = createScriptTasks
|
||||
|
||||
const dependencies = Object.keys((packageJSON && packageJSON.dependencies) || {})
|
||||
const materialUIDependencies = ['@material-ui/core']
|
||||
const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/))
|
||||
const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u))
|
||||
const d3Dependencies = ['c3', 'd3']
|
||||
|
||||
const externalDependenciesMap = {
|
||||
@ -365,7 +365,7 @@ function getEnvironment ({ devMode, test }) {
|
||||
return 'testing'
|
||||
} else if (process.env.CIRCLE_BRANCH === 'master') {
|
||||
return 'production'
|
||||
} else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) {
|
||||
} else if (/^Version-v(\d+)[.](\d+)[.](\d+)/u.test(process.env.CIRCLE_BRANCH)) {
|
||||
return 'release-candidate'
|
||||
} else if (process.env.CIRCLE_BRANCH === 'develop') {
|
||||
return 'staging'
|
||||
|
@ -81,10 +81,7 @@ async function start () {
|
||||
const summaryPlatform = 'chrome'
|
||||
const summaryPage = 'home'
|
||||
let commentBody
|
||||
if (!benchmarkResults[summaryPlatform]) {
|
||||
console.log(`No results for ${summaryPlatform} found; skipping benchmark`)
|
||||
commentBody = artifactsBody
|
||||
} else {
|
||||
if (benchmarkResults[summaryPlatform]) {
|
||||
try {
|
||||
const summaryPageLoad = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].average.load))
|
||||
const summaryPageLoadMarginOfError = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].marginOfError.load))
|
||||
@ -147,6 +144,9 @@ async function start () {
|
||||
console.error(`Error constructing benchmark results: '${error}'`)
|
||||
commentBody = artifactsBody
|
||||
}
|
||||
} else {
|
||||
console.log(`No results for ${summaryPlatform} found; skipping benchmark`)
|
||||
commentBody = artifactsBody
|
||||
}
|
||||
|
||||
const JSON_PAYLOAD = JSON.stringify({ body: commentBody })
|
||||
|
@ -50,7 +50,7 @@ class Mock3Box {
|
||||
},
|
||||
}
|
||||
},
|
||||
logout: () => {},
|
||||
logout: () => undefined,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,14 @@ async function start () {
|
||||
|
||||
// check if version has artifacts or not
|
||||
const versionHasArtifacts = versionAlreadyExists && await checkIfVersionHasArtifacts()
|
||||
if (!versionHasArtifacts) {
|
||||
// upload sentry source and sourcemaps
|
||||
await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`)
|
||||
} else {
|
||||
if (versionHasArtifacts) {
|
||||
console.log(`Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`)
|
||||
return
|
||||
}
|
||||
|
||||
// upload sentry source and sourcemaps
|
||||
await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`)
|
||||
|
||||
}
|
||||
|
||||
async function checkIfAuthWorks () {
|
||||
|
@ -49,7 +49,9 @@ async function validateSourcemapForFile ({ buildName }) {
|
||||
try {
|
||||
const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}`)
|
||||
rawBuild = await fsAsync.readFile(filePath, 'utf8')
|
||||
} catch (err) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
if (!rawBuild) {
|
||||
throw new Error(`SourcemapValidator - failed to load source file for "${buildName}"`)
|
||||
}
|
||||
@ -58,12 +60,16 @@ async function validateSourcemapForFile ({ buildName }) {
|
||||
try {
|
||||
const filePath = path.join(__dirname, `/../dist/sourcemaps/`, `${buildName}.map`)
|
||||
rawSourceMap = await fsAsync.readFile(filePath, 'utf8')
|
||||
} catch (err) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
// attempt to load in dev mode
|
||||
try {
|
||||
const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}.map`)
|
||||
rawSourceMap = await fsAsync.readFile(filePath, 'utf8')
|
||||
} catch (err) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
if (!rawSourceMap) {
|
||||
throw new Error(`SourcemapValidator - failed to load sourcemaps for "${buildName}"`)
|
||||
}
|
||||
@ -85,7 +91,7 @@ async function validateSourcemapForFile ({ buildName }) {
|
||||
const matchesPerLine = buildLines.map((line) => indicesOf(targetString, line))
|
||||
matchesPerLine.forEach((matchIndices, lineIndex) => {
|
||||
matchIndices.forEach((matchColumn) => {
|
||||
sampleCount++
|
||||
sampleCount += 1
|
||||
const position = { line: lineIndex + 1, column: matchColumn }
|
||||
const result = consumer.originalPositionFor(position)
|
||||
// warn if source content is missing
|
||||
|
@ -61,7 +61,7 @@ const main = async () => {
|
||||
}
|
||||
|
||||
while (args.length) {
|
||||
if (/^(--port|-p)$/i.test(args[0])) {
|
||||
if (/^(--port|-p)$/u.test(args[0])) {
|
||||
if (args[1] === undefined) {
|
||||
throw new Error('Missing port argument')
|
||||
}
|
||||
|
@ -97,6 +97,7 @@ async function getLocale (code) {
|
||||
log.error(`Error opening your locale ("${code}") file: `, e)
|
||||
}
|
||||
process.exit(1)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +112,7 @@ async function writeLocale (code, locale) {
|
||||
log.error(`Error writing your locale ("${code}") file: `, e)
|
||||
}
|
||||
process.exit(1)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +158,8 @@ async function verifyLocale (code, fix = false) {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
async function verifyEnglishLocale (fix = false) {
|
||||
@ -165,11 +169,11 @@ async function verifyEnglishLocale (fix = false) {
|
||||
// match "t(`...`)" because constructing message keys from template strings
|
||||
// prevents this script from finding the messages, and then inappropriately
|
||||
// deletes them
|
||||
const templateStringRegex = /\bt\(`.*`\)/g
|
||||
const templateStringRegex = /\bt\(`.*`\)/ug
|
||||
const templateUsage = []
|
||||
|
||||
// match the keys from the locale file
|
||||
const keyRegex = /'(\w+)'|"(\w+)"/g
|
||||
const keyRegex = /'(\w+)'|"(\w+)"/ug
|
||||
const usedMessages = new Set()
|
||||
for await (const fileContents of getFileContents(javascriptFiles)) {
|
||||
for (const match of matchAll.call(fileContents, keyRegex)) {
|
||||
|
@ -202,7 +202,7 @@
|
||||
"chalk": "^3.0.0",
|
||||
"chromedriver": "^79.0.0",
|
||||
"concurrently": "^5.2.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"copy-webpack-plugin": "^6.0.3",
|
||||
"coveralls": "^3.0.0",
|
||||
"css-loader": "^2.1.1",
|
||||
"del": "^3.0.0",
|
||||
|
@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
rules: {
|
||||
'mocha/no-hooks-for-single-case': 'off',
|
||||
},
|
||||
}
|
@ -152,7 +152,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('balance renders', async function () {
|
||||
const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/))
|
||||
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -202,7 +202,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -239,7 +239,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -92,7 +92,7 @@ async function isWritable (directory) {
|
||||
}
|
||||
|
||||
async function getFirstParentDirectoryThatExists (directory) {
|
||||
while (true) {
|
||||
for (;;) {
|
||||
try {
|
||||
await fs.access(directory, fsConstants.F_OK)
|
||||
return directory
|
||||
@ -117,7 +117,7 @@ async function main () {
|
||||
let existingParentDirectory
|
||||
|
||||
while (args.length) {
|
||||
if (/^(--pages|-p)$/i.test(args[0])) {
|
||||
if (/^(--pages|-p)$/u.test(args[0])) {
|
||||
if (args[1] === undefined) {
|
||||
throw new Error('Missing pages argument')
|
||||
}
|
||||
@ -128,7 +128,7 @@ async function main () {
|
||||
}
|
||||
}
|
||||
args.splice(0, 2)
|
||||
} else if (/^(--samples|-s)$/i.test(args[0])) {
|
||||
} else if (/^(--samples|-s)$/u.test(args[0])) {
|
||||
if (args[1] === undefined) {
|
||||
throw new Error('Missing number of samples')
|
||||
}
|
||||
@ -137,7 +137,7 @@ async function main () {
|
||||
throw new Error(`Invalid 'samples' argument given: '${args[1]}'`)
|
||||
}
|
||||
args.splice(0, 2)
|
||||
} else if (/^(--out|-o)$/i.test(args[0])) {
|
||||
} else if (/^(--out|-o)$/u.test(args[0])) {
|
||||
if (args[1] === undefined) {
|
||||
throw new Error('Missing output filename')
|
||||
}
|
||||
|
@ -89,11 +89,11 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('gets the current accounts address', async function () {
|
||||
const addressInput = await driver.findElement(By.css('.qr-ellip-address'))
|
||||
const addressInput = await driver.findElement(By.css('.readonly-input__input'))
|
||||
publicAddress = await addressInput.getAttribute('value')
|
||||
const accountModal = await driver.findElement(By.css('span .modal'))
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
|
||||
await driver.wait(until.stalenessOf(accountModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
@ -44,7 +44,7 @@ class FixtureServer {
|
||||
return
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
this._server.close()
|
||||
this._server.once('error', reject)
|
||||
this._server.once('close', resolve)
|
||||
|
@ -99,24 +99,24 @@ describe('Using MetaMask with an existing account', function () {
|
||||
it('shows the correct account address', async function () {
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu-button"]'))
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]'))
|
||||
await driver.findVisibleElement(By.css('.qr-wrapper'))
|
||||
await driver.findVisibleElement(By.css('.qr-code__wrapper'))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
const [address] = await driver.findElements(By.css('input.qr-ellip-address'))
|
||||
const [address] = await driver.findElements(By.css('.readonly-input__input'))
|
||||
assert.equal(await address.getAttribute('value'), testAddress)
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
await driver.delay(largeDelayMs)
|
||||
})
|
||||
|
||||
it('shows a QR code for the account', async function () {
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu-button"]'))
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]'))
|
||||
await driver.findVisibleElement(By.css('.qr-wrapper'))
|
||||
await driver.findVisibleElement(By.css('.qr-code__wrapper'))
|
||||
const detailModal = await driver.findElement(By.css('span .modal'))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
await driver.wait(until.stalenessOf(detailModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
@ -223,7 +223,7 @@ describe('Using MetaMask with an existing account', function () {
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
assert.equal(txValues.length, 1)
|
||||
assert.ok(/-1\s*ETH/.test(await txValues[0].getText()))
|
||||
assert.ok(/-1\s*ETH/u.test(await txValues[0].getText()))
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -95,12 +95,12 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('gets the current accounts address', async function () {
|
||||
const addressInput = await driver.findElement(By.css('.qr-ellip-address'))
|
||||
const addressInput = await driver.findElement(By.css('.readonly-input__input'))
|
||||
publicAddress = await addressInput.getAttribute('value')
|
||||
|
||||
const accountModal = await driver.findElement(By.css('span .modal'))
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
|
||||
await driver.wait(until.stalenessOf(accountModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
@ -127,7 +127,7 @@ describe('MetaMask', function () {
|
||||
await driver.clickElement(By.css('#send'))
|
||||
|
||||
const txStatus = await driver.findElement(By.css('#success'))
|
||||
await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000)
|
||||
await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000)
|
||||
})
|
||||
|
||||
it('switches back to MetaMask', async function () {
|
||||
@ -136,7 +136,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('should have the correct amount of eth', async function () {
|
||||
const balances = await driver.findElements(By.css('.currency-display-component__text'))
|
||||
await driver.wait(until.elementTextMatches(balances[0], /1/), 15000)
|
||||
await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000)
|
||||
const balance = await balances[0].getText()
|
||||
|
||||
assert.equal(balance, '1')
|
||||
@ -193,7 +193,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('should have the correct amount of eth', async function () {
|
||||
const balances = await driver.findElements(By.css('.currency-display-component__text'))
|
||||
await driver.wait(until.elementTextMatches(balances[0], /1/), 15000)
|
||||
await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000)
|
||||
const balance = await balances[0].getText()
|
||||
|
||||
assert.equal(balance, '1')
|
||||
|
@ -167,7 +167,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('balance renders', async function () {
|
||||
const balance = await driver.findElement(By.css('[data-testid="eth-overview__primary-currency"]'))
|
||||
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/))
|
||||
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -218,7 +218,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -121,11 +121,11 @@ describe('MetaMask', function () {
|
||||
it('shows the QR code for the account', async function () {
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu-button"]'))
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]'))
|
||||
await driver.findVisibleElement(By.css('.qr-wrapper'))
|
||||
await driver.findVisibleElement(By.css('.qr-code__wrapper'))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
const accountModal = await driver.findElement(By.css('span .modal'))
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
|
||||
await driver.wait(until.stalenessOf(accountModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
@ -208,7 +208,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('balance renders', async function () {
|
||||
const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/))
|
||||
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -273,7 +273,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -312,7 +312,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -360,7 +360,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -463,7 +463,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/u), 10000)
|
||||
})
|
||||
|
||||
it('the transaction has the expected gas price', async function () {
|
||||
@ -471,7 +471,7 @@ describe('MetaMask', function () {
|
||||
await txValue.click()
|
||||
const popoverCloseButton = await driver.findClickableElement(By.css('.popover-header__button'))
|
||||
const txGasPrice = await driver.findElement(By.css('[data-testid="transaction-breakdown__gas-price"]'))
|
||||
await driver.wait(until.elementTextMatches(txGasPrice, /^10$/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txGasPrice, /^10$/u), 10000)
|
||||
await popoverCloseButton.click()
|
||||
})
|
||||
})
|
||||
@ -654,7 +654,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txAction = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/u), 10000)
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
|
||||
@ -663,20 +663,20 @@ describe('MetaMask', function () {
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
let contractStatus = await driver.findElement(By.css('#contractStatus'))
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000)
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deployed/u), 15000)
|
||||
|
||||
await driver.clickElement(By.css('#depositButton'))
|
||||
await driver.delay(largeDelayMs)
|
||||
|
||||
contractStatus = await driver.findElement(By.css('#contractStatus'))
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000)
|
||||
await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/u), 10000)
|
||||
|
||||
await driver.switchToWindow(extension)
|
||||
await driver.delay(largeDelayMs * 2)
|
||||
|
||||
await driver.findElements(By.css('.transaction-list-item'))
|
||||
const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/u), 10000)
|
||||
await txListValue.click()
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
@ -718,7 +718,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/u), 10000)
|
||||
})
|
||||
|
||||
it('calls and confirms a contract method where ETH is received', async function () {
|
||||
@ -743,7 +743,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/u), 10000)
|
||||
|
||||
await driver.closeAllWindowHandlesExcept([extension, dapp])
|
||||
await driver.switchToWindow(extension)
|
||||
@ -752,9 +752,9 @@ describe('MetaMask', function () {
|
||||
it('renders the correct ETH balance', async function () {
|
||||
const balance = await driver.findElement(By.css('[data-testid="eth-overview__primary-currency"]'))
|
||||
await driver.delay(regularDelayMs)
|
||||
await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000)
|
||||
await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/u), 10000)
|
||||
const tokenAmount = await balance.getText()
|
||||
assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount))
|
||||
assert.ok(/^87.*\s*ETH.*$/u.test(tokenAmount))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -797,7 +797,7 @@ describe('MetaMask', function () {
|
||||
await driver.delay(tinyDelayMs)
|
||||
|
||||
const tokenContractAddress = await driver.findElement(By.css('#tokenAddress'))
|
||||
await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/))
|
||||
await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/u))
|
||||
tokenAddress = await tokenContractAddress.getText()
|
||||
|
||||
await driver.delay(regularDelayMs)
|
||||
@ -830,9 +830,9 @@ describe('MetaMask', function () {
|
||||
|
||||
it('renders the balance for the new token', async function () {
|
||||
const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/))
|
||||
await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u))
|
||||
const tokenAmount = await balance.getText()
|
||||
assert.ok(/^10\s*TST\s*$/.test(tokenAmount))
|
||||
assert.ok(/^10\s*TST\s*$/u.test(tokenAmount))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -887,7 +887,7 @@ describe('MetaMask', function () {
|
||||
const confirmDataText = await confirmDataDiv.getText()
|
||||
|
||||
await driver.delay(regularDelayMs)
|
||||
assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/))
|
||||
assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/u))
|
||||
|
||||
await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`))
|
||||
await driver.delay(regularDelayMs)
|
||||
@ -906,10 +906,10 @@ describe('MetaMask', function () {
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
assert.equal(txValues.length, 1)
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/u), 10000)
|
||||
|
||||
const txStatuses = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/i), 10000)
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -931,7 +931,7 @@ describe('MetaMask', function () {
|
||||
|
||||
await driver.findElements(By.css('.transaction-list__pending-transactions'))
|
||||
const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u), 10000)
|
||||
await txListValue.click()
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
@ -987,12 +987,12 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/))
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u))
|
||||
const txStatuses = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/), 10000)
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000)
|
||||
|
||||
const tokenBalanceAmount = await driver.findElements(By.css('.token-overview__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/), 10000)
|
||||
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/u), 10000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -1019,7 +1019,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/))
|
||||
await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u))
|
||||
await driver.clickElement(By.css('.transaction-list-item'))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
@ -1034,7 +1034,7 @@ describe('MetaMask', function () {
|
||||
|
||||
const confirmDataDiv = await driver.findElement(By.css('.confirm-approve-content__data__data-block'))
|
||||
const confirmDataText = await confirmDataDiv.getText()
|
||||
assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/))
|
||||
assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u))
|
||||
})
|
||||
|
||||
it('opens the gas edit modal', async function () {
|
||||
@ -1105,7 +1105,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txStatuses = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u))
|
||||
})
|
||||
})
|
||||
|
||||
@ -1130,7 +1130,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const [txListValue] = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/))
|
||||
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u))
|
||||
await driver.clickElement(By.css('.transaction-list-item'))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
@ -1148,9 +1148,9 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/))
|
||||
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u))
|
||||
const txStatuses = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/u))
|
||||
})
|
||||
})
|
||||
|
||||
@ -1176,7 +1176,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/))
|
||||
await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u))
|
||||
await driver.clickElement(By.css('.transaction-list-item'))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
@ -1203,7 +1203,7 @@ describe('MetaMask', function () {
|
||||
}, 10000)
|
||||
|
||||
const txStatuses = await driver.findElements(By.css('.list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/))
|
||||
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u))
|
||||
})
|
||||
})
|
||||
|
||||
@ -1244,7 +1244,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('renders the balance for the chosen token', async function () {
|
||||
const balance = await driver.findElement(By.css('.token-overview__primary-balance'))
|
||||
await driver.wait(until.elementTextMatches(balance, /0\s*BAT/))
|
||||
await driver.wait(until.elementTextMatches(balance, /0\s*BAT/u))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
|
@ -32,6 +32,7 @@ const server = http.createServer(requestHandler)
|
||||
|
||||
server.listen(port, (err) => {
|
||||
if (err) {
|
||||
return console.log('mock 3box server error: ', err)
|
||||
console.log('mock 3box server error: ', err)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
@ -90,11 +90,11 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('gets the current accounts address', async function () {
|
||||
const addressInput = await driver.findElement(By.css('.qr-ellip-address'))
|
||||
const addressInput = await driver.findElement(By.css('.readonly-input__input'))
|
||||
publicAddress = await addressInput.getAttribute('value')
|
||||
const accountModal = await driver.findElement(By.css('span .modal'))
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
|
||||
await driver.wait(until.stalenessOf(accountModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
@ -205,7 +205,7 @@ describe('Using MetaMask with an existing account', function () {
|
||||
|
||||
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
|
||||
assert.equal(txValues.length, 1)
|
||||
assert.ok(/-2.2\s*ETH/.test(await txValues[0].getText()))
|
||||
assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText()))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -124,11 +124,11 @@ describe('MetaMask', function () {
|
||||
await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]'))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
||||
const addressInput = await driver.findElement(By.css('.qr-ellip-address'))
|
||||
const addressInput = await driver.findElement(By.css('.readonly-input__input'))
|
||||
const newPublicAddress = await addressInput.getAttribute('value')
|
||||
const accountModal = await driver.findElement(By.css('span .modal'))
|
||||
|
||||
await driver.clickElement(By.css('.account-modal-close'))
|
||||
await driver.clickElement(By.css('.account-modal__close'))
|
||||
|
||||
await driver.wait(until.stalenessOf(accountModal))
|
||||
await driver.delay(regularDelayMs)
|
||||
|
@ -20,7 +20,7 @@ describe('Localization', function () {
|
||||
await passwordField.sendKeys(Key.ENTER)
|
||||
const secondaryBalance = await driver.findElement(By.css('[data-testid="eth-overview__secondary-currency"]'))
|
||||
const secondaryBalanceText = await secondaryBalance.getText()
|
||||
const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/)
|
||||
const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/u)
|
||||
assert.ok(fiatAmount.startsWith('₱'))
|
||||
assert.equal(fiatUnit, 'PHP')
|
||||
},
|
||||
|
@ -97,7 +97,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('balance renders', async function () {
|
||||
const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
|
||||
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/))
|
||||
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u))
|
||||
await driver.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
@ -203,7 +203,7 @@ describe('MetaMask', function () {
|
||||
|
||||
it('balance renders', async function () {
|
||||
const balance = await driver2.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
|
||||
await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/))
|
||||
await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/u))
|
||||
await driver2.delay(regularDelayMs)
|
||||
})
|
||||
})
|
||||
|
@ -180,7 +180,9 @@ class Driver {
|
||||
await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' })
|
||||
const htmlSource = await this.driver.getPageSource()
|
||||
await fs.writeFile(`${filepathBase}-dom.html`, htmlSource)
|
||||
const uiState = await this.driver.executeScript(() => window.getCleanAppState())
|
||||
const uiState = await this.driver.executeScript(
|
||||
() => window.getCleanAppState && window.getCleanAppState(),
|
||||
)
|
||||
await fs.writeFile(`${filepathBase}-state.json`, JSON.stringify(uiState, null, 2))
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ async function setupFetchMocking (driver) {
|
||||
return { json: async () => clone(fetchMockResponses.ethGasBasic) }
|
||||
} else if (url.match(/http(s?):\/\/ethgasstation\.info\/json\/predictTable.*/u)) {
|
||||
return { json: async () => clone(fetchMockResponses.ethGasPredictTable) }
|
||||
} else if (url.match(/chromeextensionmm/)) {
|
||||
} else if (url.match(/chromeextensionmm/u)) {
|
||||
return { json: async () => clone(fetchMockResponses.metametrics) }
|
||||
}
|
||||
return window.origFetch(...args)
|
||||
|
@ -80,7 +80,7 @@ require('abortcontroller-polyfill/dist/polyfill-patch-fetch')
|
||||
window.localStorage = {}
|
||||
|
||||
// override metamask-logo
|
||||
window.requestAnimationFrame = () => {}
|
||||
window.requestAnimationFrame = () => undefined
|
||||
|
||||
// crypto.getRandomValues
|
||||
if (!window.crypto) {
|
||||
|
@ -27,7 +27,7 @@ export function mountWithRouter (component, store = {}, pathname = '/') {
|
||||
context: {
|
||||
router,
|
||||
t: (str) => str,
|
||||
metricsEvent: () => {},
|
||||
metricsEvent: () => undefined,
|
||||
store,
|
||||
},
|
||||
childContextTypes: {
|
||||
|
@ -1,7 +1,3 @@
|
||||
|
||||
/* eslint-disable no-native-reassign */
|
||||
|
||||
// this is what we're testing
|
||||
import '../../app/scripts/lib/freezeGlobals'
|
||||
|
||||
import assert from 'assert'
|
||||
@ -10,6 +6,7 @@ describe('Promise global is immutable', function () {
|
||||
|
||||
it('throws when reassinging promise (syntax 1)', function () {
|
||||
try {
|
||||
// eslint-disable-next-line no-global-assign,no-native-reassign
|
||||
Promise = {}
|
||||
assert.fail('did not throw error')
|
||||
} catch (err) {
|
||||
@ -28,7 +25,7 @@ describe('Promise global is immutable', function () {
|
||||
|
||||
it('throws when mutating existing Promise property', function () {
|
||||
try {
|
||||
Promise.all = () => {}
|
||||
Promise.all = () => undefined
|
||||
assert.fail('did not throw error')
|
||||
} catch (err) {
|
||||
assert.ok(err, 'did throw error')
|
||||
|
@ -9,7 +9,7 @@ describe('CachedBalancesController', function () {
|
||||
getNetwork: () => Promise.resolve(17),
|
||||
accountTracker: {
|
||||
store: {
|
||||
subscribe: () => {},
|
||||
subscribe: () => undefined,
|
||||
},
|
||||
},
|
||||
initState: {
|
||||
@ -32,7 +32,7 @@ describe('CachedBalancesController', function () {
|
||||
const controller = new CachedBalancesController({
|
||||
accountTracker: {
|
||||
store: {
|
||||
subscribe: () => {},
|
||||
subscribe: () => undefined,
|
||||
},
|
||||
},
|
||||
initState: {
|
||||
@ -75,7 +75,7 @@ describe('CachedBalancesController', function () {
|
||||
const controller = new CachedBalancesController({
|
||||
accountTracker: {
|
||||
store: {
|
||||
subscribe: () => {},
|
||||
subscribe: () => undefined,
|
||||
},
|
||||
},
|
||||
initState: {
|
||||
|
@ -14,7 +14,7 @@ describe('DetectTokensController', function () {
|
||||
const sandbox = sinon.createSandbox()
|
||||
let keyringMemStore, network, preferences
|
||||
|
||||
const noop = () => {}
|
||||
const noop = () => undefined
|
||||
|
||||
const networkControllerProviderConfig = {
|
||||
getAccounts: noop,
|
||||
@ -24,7 +24,7 @@ describe('DetectTokensController', function () {
|
||||
|
||||
|
||||
nock('https://api.infura.io')
|
||||
.get(/.*/)
|
||||
.get(/.*/u)
|
||||
.reply(200)
|
||||
|
||||
keyringMemStore = new ObservableStore({ isUnlocked: false })
|
||||
|
@ -1,7 +1,6 @@
|
||||
import assert from 'assert'
|
||||
import sinon from 'sinon'
|
||||
import ObservableStore from 'obs-store'
|
||||
import HttpProvider from 'ethjs-provider-http'
|
||||
import EnsController from '../../../../app/scripts/controllers/ens'
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
@ -10,11 +9,10 @@ const ZERO_X_ERROR_ADDRESS = '0x'
|
||||
describe('EnsController', function () {
|
||||
describe('#constructor', function () {
|
||||
it('should construct the controller given a provider and a network', async function () {
|
||||
const provider = new HttpProvider('https://ropsten.infura.io')
|
||||
const currentNetworkId = '3'
|
||||
const networkStore = new ObservableStore(currentNetworkId)
|
||||
const ens = new EnsController({
|
||||
provider,
|
||||
provider: { },
|
||||
networkStore,
|
||||
})
|
||||
|
||||
|
@ -19,7 +19,7 @@ import proxyquire from 'proxyquire'
|
||||
class ThreeBoxControllerMock {
|
||||
constructor () {
|
||||
this.store = {
|
||||
subscribe: () => {},
|
||||
subscribe: () => undefined,
|
||||
getState: () => ({}),
|
||||
}
|
||||
this.init = threeBoxSpies.init
|
||||
@ -78,7 +78,7 @@ const CUSTOM_RPC_URL = 'http://localhost:8545'
|
||||
describe('MetaMaskController', function () {
|
||||
let metamaskController
|
||||
const sandbox = sinon.createSandbox()
|
||||
const noop = () => {}
|
||||
const noop = () => undefined
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
@ -92,12 +92,12 @@ describe('MetaMaskController', function () {
|
||||
|
||||
nock('https://api.infura.io')
|
||||
.persist()
|
||||
.get(/.*/)
|
||||
.get(/.*/u)
|
||||
.reply(200)
|
||||
|
||||
nock('https://min-api.cryptocompare.com')
|
||||
.persist()
|
||||
.get(/.*/)
|
||||
.get(/.*/u)
|
||||
.reply(200, '{"JPY":12415.9}')
|
||||
|
||||
metamaskController = new MetaMaskController({
|
||||
@ -113,7 +113,7 @@ describe('MetaMaskController', function () {
|
||||
},
|
||||
},
|
||||
initState: cloneDeep(firstTimeState),
|
||||
platform: { showTransactionNotification: () => {} },
|
||||
platform: { showTransactionNotification: () => undefined },
|
||||
})
|
||||
// disable diagnostics
|
||||
metamaskController.diagnostics = null
|
||||
@ -819,7 +819,8 @@ describe('MetaMaskController', function () {
|
||||
const { promise, resolve } = deferredPromise()
|
||||
const streamTest = createThoughStream((chunk, _, cb) => {
|
||||
if (chunk.name !== 'phishing') {
|
||||
return cb()
|
||||
cb()
|
||||
return
|
||||
}
|
||||
assert.equal(chunk.data.hostname, (new URL(phishingMessageSender.url)).hostname)
|
||||
resolve()
|
||||
|
@ -6,7 +6,7 @@ import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/ne
|
||||
describe('NetworkController', function () {
|
||||
describe('controller', function () {
|
||||
let networkController
|
||||
const noop = () => {}
|
||||
const noop = () => undefined
|
||||
const networkControllerProviderConfig = {
|
||||
getAccounts: noop,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
* - Immutable mock values like Ethereum accounts and expected states
|
||||
*/
|
||||
|
||||
export const noop = () => {}
|
||||
export const noop = () => undefined
|
||||
|
||||
/**
|
||||
* Mock Permissions Controller and Middleware
|
||||
|
@ -372,7 +372,7 @@ describe('preferences controller', function () {
|
||||
beforeEach(function () {
|
||||
req = { params: {} }
|
||||
res = {}
|
||||
asy = { next: () => {}, end: () => {} }
|
||||
asy = { next: () => undefined, end: () => undefined }
|
||||
stubNext = sandbox.stub(asy, 'next')
|
||||
stubEnd = sandbox.stub(asy, 'end').returns(0)
|
||||
stubHandleWatchAssetERC20 = sandbox.stub(preferencesController, '_handleWatchAssetERC20')
|
||||
@ -382,7 +382,7 @@ describe('preferences controller', function () {
|
||||
})
|
||||
|
||||
it('shouldn not do anything if method not corresponds', async function () {
|
||||
const asy = { next: () => {}, end: () => {} }
|
||||
const asy = { next: () => undefined, end: () => undefined }
|
||||
const stubNext = sandbox.stub(asy, 'next')
|
||||
const stubEnd = sandbox.stub(asy, 'end').returns(0)
|
||||
req.method = 'metamask'
|
||||
@ -391,7 +391,7 @@ describe('preferences controller', function () {
|
||||
sandbox.assert.called(stubNext)
|
||||
})
|
||||
it('should do something if method is supported', async function () {
|
||||
const asy = { next: () => {}, end: () => {} }
|
||||
const asy = { next: () => undefined, end: () => undefined }
|
||||
const stubNext = sandbox.stub(asy, 'next')
|
||||
const stubEnd = sandbox.stub(asy, 'end').returns(0)
|
||||
req.method = 'metamask_watchAsset'
|
||||
@ -415,7 +415,7 @@ describe('preferences controller', function () {
|
||||
assert.deepEqual(res, {})
|
||||
})
|
||||
it('should trigger handle add asset if type supported', async function () {
|
||||
const asy = { next: () => {}, end: () => {} }
|
||||
const asy = { next: () => undefined, end: () => undefined }
|
||||
req.method = 'metamask_watchAsset'
|
||||
req.params.type = 'ERC20'
|
||||
await preferencesController.requestWatchAsset(req, res, asy.next, asy.end)
|
||||
@ -442,7 +442,7 @@ describe('preferences controller', function () {
|
||||
req.params.options = { address, symbol, decimals, image }
|
||||
|
||||
sandbox.stub(preferencesController, '_validateERC20AssetParams').returns(true)
|
||||
preferencesController.openPopup = async () => {}
|
||||
preferencesController.openPopup = async () => undefined
|
||||
|
||||
await preferencesController._handleWatchAssetERC20(req.params.options)
|
||||
const suggested = preferencesController.getSuggestedTokens()
|
||||
@ -478,46 +478,16 @@ describe('preferences controller', function () {
|
||||
assert.ok(assetImages[address], `set image correctly`)
|
||||
})
|
||||
it('should validate ERC20 asset correctly', async function () {
|
||||
const validateSpy = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpy({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpy.threw(), false, 'correct options object')
|
||||
const validateSpyAddress = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyAddress({ symbol: 'ABC', decimals: 0 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyAddress.threw(), true, 'options object with no address')
|
||||
const validateSpySymbol = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpySymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpySymbol.threw(), true, 'options object with no symbol')
|
||||
const validateSpyDecimals = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyDecimals({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC' })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyDecimals.threw(), true, 'options object with no decimals')
|
||||
const validateSpyInvalidSymbol = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyInvalidSymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyInvalidSymbol.threw(), true, 'options object with invalid symbol')
|
||||
const validateSpyInvalidDecimals1 = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyInvalidDecimals1({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: -1 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyInvalidDecimals1.threw(), true, 'options object with decimals less than zero')
|
||||
const validateSpyInvalidDecimals2 = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyInvalidDecimals2({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 38 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyInvalidDecimals2.threw(), true, 'options object with decimals more than 36')
|
||||
const validateSpyInvalidAddress = sandbox.spy(preferencesController._validateERC20AssetParams)
|
||||
try {
|
||||
validateSpyInvalidAddress({ rawAddress: '0x123', symbol: 'ABC', decimals: 0 })
|
||||
} catch (e) {}
|
||||
assert.equal(validateSpyInvalidAddress.threw(), true, 'options object with address invalid')
|
||||
const validate = preferencesController._validateERC20AssetParams
|
||||
|
||||
assert.doesNotThrow(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0 }))
|
||||
assert.throws(() => validate({ symbol: 'ABC', decimals: 0 }), 'missing address should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0 }), 'missing symbol should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC' }), 'missing decimals should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0 }), 'invalid symbol should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: -1 }), 'decimals < 0 should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 38 }), 'decimals > 36 should fail')
|
||||
assert.throws(() => validate({ rawAddress: '0x123', symbol: 'ABC', decimals: 0 }), 'invalid address should fail')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -147,15 +147,15 @@ describe('PendingTransactionTracker', function () {
|
||||
},
|
||||
nonceTracker: {
|
||||
getGlobalLock: async () => {
|
||||
return { releaseLock: () => {} }
|
||||
return { releaseLock: () => undefined }
|
||||
},
|
||||
},
|
||||
getPendingTransactions: () => txList,
|
||||
getCompletedTransactions: () => {
|
||||
return []
|
||||
},
|
||||
publishTransaction: () => {},
|
||||
confirmTransaction: () => {},
|
||||
publishTransaction: () => undefined,
|
||||
confirmTransaction: () => undefined,
|
||||
})
|
||||
|
||||
const checkPendingTxStub = sinon.stub(pendingTxTracker, '_checkPendingTx').resolves()
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
SEND_ETHER_ACTION_KEY,
|
||||
DEPLOY_CONTRACT_ACTION_KEY,
|
||||
CONTRACT_INTERACTION_KEY,
|
||||
} from '../../../../../ui/app/helpers/constants/transactions.js'
|
||||
} from '../../../../../ui/app/helpers/constants/transactions'
|
||||
|
||||
import { createTestProviderTools, getTestAccounts } from '../../../../stub/provider'
|
||||
|
||||
@ -47,7 +47,7 @@ describe('Transaction Controller', function () {
|
||||
ethTx.sign(fromAccount.key)
|
||||
resolve()
|
||||
}),
|
||||
getPermittedAccounts: () => {},
|
||||
getPermittedAccounts: () => undefined,
|
||||
})
|
||||
txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop })
|
||||
})
|
||||
|
@ -9,7 +9,7 @@ describe('txUtils', function () {
|
||||
before(function () {
|
||||
txUtils = new TxUtils(new Proxy({}, {
|
||||
get: () => {
|
||||
return () => {}
|
||||
return () => undefined
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
@ -14,9 +14,6 @@ describe('Message Manager', function () {
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 0)
|
||||
})
|
||||
it('should also return transactions from local storage if any', function () {
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addMsg', function () {
|
||||
|
@ -16,9 +16,10 @@ describe('nodeify', function () {
|
||||
if (!err) {
|
||||
assert.equal(res, 'barbaz')
|
||||
done()
|
||||
} else {
|
||||
done(new Error(err.toString()))
|
||||
return
|
||||
}
|
||||
|
||||
done(new Error(err.toString()))
|
||||
})
|
||||
})
|
||||
|
||||
@ -37,7 +38,8 @@ describe('nodeify', function () {
|
||||
try {
|
||||
nodified((err, result) => {
|
||||
if (err) {
|
||||
return done(new Error(`should not have thrown any error: ${err.message}`))
|
||||
done(new Error(`should not have thrown any error: ${err.message}`))
|
||||
return
|
||||
}
|
||||
assert.equal(42, result, 'got expected result')
|
||||
})
|
||||
@ -54,7 +56,8 @@ describe('nodeify', function () {
|
||||
try {
|
||||
nodified((err, result) => {
|
||||
if (result) {
|
||||
return done(new Error('should not have returned any result'))
|
||||
done(new Error('should not have returned any result'))
|
||||
return
|
||||
}
|
||||
assert.ok(err, 'got expected error')
|
||||
assert.ok(err.message.includes('boom!'), 'got expected error message')
|
||||
|
@ -14,9 +14,6 @@ describe('Personal Message Manager', function () {
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 0)
|
||||
})
|
||||
it('should also return transactions from local storage if any', function () {
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addMsg', function () {
|
||||
|
@ -38,8 +38,10 @@ let nonDeletableCount = 0
|
||||
let status
|
||||
while (transactions.length <= 100) {
|
||||
status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))]
|
||||
// This is an old migration, let's allow it
|
||||
// eslint-disable-next-line no-loop-func
|
||||
if (!deletableTxStates.find((s) => s === status)) {
|
||||
nonDeletableCount++
|
||||
nonDeletableCount += 1
|
||||
}
|
||||
transactions.push({ status })
|
||||
}
|
||||
@ -65,7 +67,7 @@ describe('storage is migrated successfully and the proper transactions are remov
|
||||
const migratedTransactions = migratedData.data.TransactionController.transactions
|
||||
migratedTransactions.forEach((tx) => {
|
||||
if (!deletableTxStates.find((s) => s === tx.status)) {
|
||||
leftoverNonDeletableTxCount++
|
||||
leftoverNonDeletableTxCount += 1
|
||||
}
|
||||
})
|
||||
assert.equal(leftoverNonDeletableTxCount, nonDeletableCount, "migration shouldn't delete transactions we want to keep")
|
||||
|
@ -1,5 +1,5 @@
|
||||
import assert from 'assert'
|
||||
import migrationTemplate from '../../../app/scripts/migrations/030.js'
|
||||
import migrationTemplate from '../../../app/scripts/migrations/030'
|
||||
|
||||
const storage = {
|
||||
meta: {},
|
||||
|
@ -50,7 +50,7 @@ describe('migrations', function () {
|
||||
migrationNumbers = fileNames
|
||||
.reduce((acc, filename) => {
|
||||
const name = filename.split('.')[0]
|
||||
if (/^\d+$/.test(name)) {
|
||||
if (/^\d+$/u.test(name)) {
|
||||
acc.push(name)
|
||||
}
|
||||
return acc
|
||||
@ -70,7 +70,7 @@ describe('migrations', function () {
|
||||
const testNumbers = fileNames
|
||||
.reduce((acc, filename) => {
|
||||
const name = filename.split('-test.')[0]
|
||||
if (/^\d+$/.test(name)) {
|
||||
if (/^\d+$/u.test(name)) {
|
||||
acc.push(name)
|
||||
}
|
||||
return acc
|
||||
|
@ -19,7 +19,7 @@ const mockStore = (state = defaultState) => configureStore(middleware)(state)
|
||||
|
||||
describe('Actions', function () {
|
||||
|
||||
const noop = () => {}
|
||||
const noop = () => undefined
|
||||
|
||||
const currentNetworkId = '42'
|
||||
|
||||
|
@ -167,6 +167,23 @@ describe('App State', function () {
|
||||
|
||||
})
|
||||
|
||||
it('clears account details', function () {
|
||||
const exportPrivKeyModal = {
|
||||
accountDetail: {
|
||||
subview: 'export',
|
||||
accountExport: 'completed',
|
||||
privateKey: 'a-priv-key',
|
||||
},
|
||||
}
|
||||
|
||||
const state = { ...metamaskState, appState: { ...exportPrivKeyModal } }
|
||||
const newState = reduceApp(state, {
|
||||
type: actions.CLEAR_ACCOUNT_DETAILS,
|
||||
})
|
||||
|
||||
assert.deepStrictEqual(newState.accountDetail, {})
|
||||
})
|
||||
|
||||
it('shoes account page', function () {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.SHOW_ACCOUNTS_PAGE,
|
||||
|
51
ui/app/components/app/account-list-item/account-list-item.js
Normal file
51
ui/app/components/app/account-list-item/account-list-item.js
Normal file
@ -0,0 +1,51 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { checksumAddress } from '../../../helpers/utils/util'
|
||||
import Identicon from '../../ui/identicon'
|
||||
import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'
|
||||
|
||||
export default function AccountListItem ({
|
||||
account,
|
||||
className,
|
||||
displayAddress = false,
|
||||
handleClick,
|
||||
icon = null,
|
||||
}) {
|
||||
const { name, address, balance } = account || {}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`account-list-item ${className}`}
|
||||
onClick={() => handleClick && handleClick({ name, address, balance })}
|
||||
>
|
||||
|
||||
<div className="account-list-item__top-row">
|
||||
<Identicon
|
||||
address={address}
|
||||
className="account-list-item__identicon"
|
||||
diameter={18}
|
||||
/>
|
||||
|
||||
<div className="account-list-item__account-name">{ name || address }</div>
|
||||
|
||||
{icon && <div className="account-list-item__icon">{ icon }</div>}
|
||||
|
||||
<AccountMismatchWarning address={address} />
|
||||
</div>
|
||||
|
||||
{displayAddress && name && (
|
||||
<div className="account-list-item__account-address">
|
||||
{ checksumAddress(address) }
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
AccountListItem.propTypes = {
|
||||
account: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
displayAddress: PropTypes.bool,
|
||||
handleClick: PropTypes.func,
|
||||
icon: PropTypes.node,
|
||||
}
|
1
ui/app/components/app/account-list-item/index.js
Normal file
1
ui/app/components/app/account-list-item/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './account-list-item'
|
26
ui/app/components/app/account-list-item/index.scss
Normal file
26
ui/app/components/app/account-list-item/index.scss
Normal file
@ -0,0 +1,26 @@
|
||||
.account-list-item {
|
||||
&__top-row {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
margin-left: 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__account-name {
|
||||
font-size: 16px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
&__account-address {
|
||||
margin-left: 35px;
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
@ -3,9 +3,8 @@ import assert from 'assert'
|
||||
import { shallow } from 'enzyme'
|
||||
import sinon from 'sinon'
|
||||
import * as utils from '../../../../helpers/utils/util'
|
||||
import Identicon from '../../../../components/ui/identicon'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'
|
||||
import AccountListItem from '../account-list-item.component'
|
||||
import Identicon from '../../../ui/identicon'
|
||||
import AccountListItem from '../account-list-item'
|
||||
|
||||
describe('AccountListItem Component', function () {
|
||||
let wrapper, propsMethodSpies, checksumAddressStub
|
||||
@ -22,11 +21,7 @@ describe('AccountListItem Component', function () {
|
||||
<AccountListItem
|
||||
account={ { address: 'mockAddress', name: 'mockName', balance: 'mockBalance' } }
|
||||
className="mockClassName"
|
||||
conversionRate={4}
|
||||
currentCurrency="mockCurrentyCurrency"
|
||||
nativeCurrency="ETH"
|
||||
displayAddress={false}
|
||||
displayBalance={false}
|
||||
handleClick={propsMethodSpies.handleClick}
|
||||
icon={<i className="mockIcon" />}
|
||||
/>
|
||||
@ -113,36 +108,5 @@ describe('AccountListItem Component', function () {
|
||||
wrapper.setProps({ account: { address: 'someAddressButNoName' } })
|
||||
assert.equal(wrapper.find('.account-list-item__account-address').length, 0)
|
||||
})
|
||||
|
||||
it('should render a CurrencyDisplay with the correct props if displayBalance is true', function () {
|
||||
wrapper.setProps({ displayBalance: true })
|
||||
assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2)
|
||||
assert.deepEqual(
|
||||
wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(),
|
||||
{
|
||||
type: 'PRIMARY',
|
||||
value: 'mockBalance',
|
||||
hideTitle: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it('should only render one CurrencyDisplay if showFiat is false', function () {
|
||||
wrapper.setProps({ showFiat: false, displayBalance: true })
|
||||
assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 1)
|
||||
assert.deepEqual(
|
||||
wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(),
|
||||
{
|
||||
type: 'PRIMARY',
|
||||
value: 'mockBalance',
|
||||
hideTitle: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it('should not render a CurrencyDisplay if displayBalance is false', function () {
|
||||
wrapper.setProps({ displayBalance: false })
|
||||
assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 0)
|
||||
})
|
||||
})
|
||||
})
|
@ -1,63 +0,0 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import Identicon from '../ui/identicon'
|
||||
import { addressSummary, formatBalance } from '../../helpers/utils/util'
|
||||
|
||||
export default class AccountPanel extends Component {
|
||||
static propTypes = {
|
||||
identity: PropTypes.object,
|
||||
account: PropTypes.object,
|
||||
isFauceting: PropTypes.bool,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
identity: {},
|
||||
account: {},
|
||||
isFauceting: false,
|
||||
}
|
||||
|
||||
render () {
|
||||
const { identity, account, isFauceting } = this.props
|
||||
|
||||
const panelState = {
|
||||
key: `accountPanel${identity.address}`,
|
||||
identiconKey: identity.address,
|
||||
identiconLabel: identity.name || '',
|
||||
attributes: [
|
||||
{
|
||||
key: 'ADDRESS',
|
||||
value: addressSummary(identity.address),
|
||||
},
|
||||
balanceOrFaucetingIndication(account, isFauceting),
|
||||
],
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="identity-panel flex-row flex-space-between"
|
||||
style={{ flex: '1 0 auto', cursor: panelState.onClick ? 'pointer' : undefined }}
|
||||
onClick={panelState.onClick}
|
||||
>
|
||||
<div className="identicon-wrapper flex-column select-none">
|
||||
<Identicon address={panelState.identiconKey} />
|
||||
<span className="font-small">{panelState.identiconLabel.substring(0, 7) + '...'}</span>
|
||||
</div>
|
||||
<div className="identity-data flex-column flex-justify-center flex-grow select-none">
|
||||
{panelState.attributes.map((attr, index) => (
|
||||
<div className="flex-row flex-space-between" key={index}>
|
||||
<label className="font-small no-select">{attr.key}</label>
|
||||
<span className="font-small">{attr.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function balanceOrFaucetingIndication (account) {
|
||||
return {
|
||||
key: 'BALANCE',
|
||||
value: formatBalance(account.balance),
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ describe('App Header', function () {
|
||||
<AppHeader.WrappedComponent {...props} />, {
|
||||
context: {
|
||||
t: (str) => str,
|
||||
metricsEvent: () => {},
|
||||
metricsEvent: () => undefined,
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -54,8 +54,8 @@ describe('App Header', function () {
|
||||
const network = wrapper.find({ network: 'test' })
|
||||
|
||||
network.simulate('click', {
|
||||
preventDefault: () => {},
|
||||
stopPropagation: () => {},
|
||||
preventDefault: () => undefined,
|
||||
stopPropagation: () => undefined,
|
||||
})
|
||||
|
||||
assert(props.showNetworkDropdown.calledOnce)
|
||||
@ -66,8 +66,8 @@ describe('App Header', function () {
|
||||
const network = wrapper.find({ network: 'test' })
|
||||
|
||||
network.simulate('click', {
|
||||
preventDefault: () => {},
|
||||
stopPropagation: () => {},
|
||||
preventDefault: () => undefined,
|
||||
stopPropagation: () => undefined,
|
||||
})
|
||||
|
||||
assert(props.hideNetworkDropdown.calledOnce)
|
||||
|
@ -60,7 +60,7 @@ const AssetListItem = ({
|
||||
: null
|
||||
|
||||
const sendTokenButton = useMemo(() => {
|
||||
if (tokenAddress == null) {
|
||||
if (tokenAddress === null || tokenAddress === undefined) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
|
@ -1 +1 @@
|
||||
export { default } from './asset-list.js'
|
||||
export { default } from './asset-list'
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user