Merge pull request #9054 from MetaMask/Version-v8.0.6

Version v8.0.6 RC
feature/default_network_editable
Mark Stacey 4 years ago committed by GitHub
commit b3304ca35e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      .eslintrc.js
  2. 9
      CHANGELOG.md
  3. 4
      app/_locales/en/messages.json
  4. 2
      app/manifest/_base.json
  5. 3
      app/scripts/controllers/detect-tokens.js
  6. 1
      app/scripts/controllers/permissions/methodMiddleware.js
  7. 12
      app/scripts/controllers/preferences.js
  8. 2
      app/scripts/controllers/transactions/README.md
  9. 2
      app/scripts/controllers/transactions/lib/tx-state-history-helpers.js
  10. 2
      app/scripts/controllers/transactions/tx-gas-utils.js
  11. 10
      app/scripts/controllers/transactions/tx-state-manager.js
  12. 4
      app/scripts/lib/ComposableObservableStore.js
  13. 2
      app/scripts/lib/createStreamSink.js
  14. 4
      app/scripts/lib/decrypt-message-manager.js
  15. 4
      app/scripts/lib/message-manager.js
  16. 3
      app/scripts/lib/migrator/index.js
  17. 2
      app/scripts/lib/notification-manager.js
  18. 2
      app/scripts/lib/personal-message-manager.js
  19. 3
      app/scripts/lib/setupSentry.js
  20. 2
      app/scripts/lib/util.js
  21. 25
      app/scripts/metamask-controller.js
  22. 4
      app/scripts/migrations/028.js
  23. 6
      app/scripts/migrations/037.js
  24. 1
      app/scripts/platforms/extension.js
  25. 6
      development/build/display.js
  26. 1
      development/run-ganache
  27. 2
      docs/add-to-firefox.md
  28. 6
      package.json
  29. 2
      test/e2e/benchmark.js
  30. 3
      test/e2e/helpers.js
  31. 24
      test/e2e/metamask-ui.spec.js
  32. 2
      test/e2e/signature-request.spec.js
  33. 2
      test/e2e/webdriver/index.js
  34. 5
      test/helper.js
  35. 6
      test/unit/app/controllers/detect-tokens-test.js
  36. 12
      test/unit/app/controllers/metamask-controller-test.js
  37. 14
      test/unit/app/controllers/transactions/tx-state-manager-test.js
  38. 10
      test/unit/migrations/023-test.js
  39. 3
      test/unit/migrations/026-test.js
  40. 3
      test/unit/migrations/027-test.js
  41. 3
      test/unit/migrations/028-test.js
  42. 1
      test/unit/ui/app/reducers/metamask.spec.js
  43. 4
      ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss
  44. 2
      ui/app/components/app/confirm-page-container/confirm-detail-row/index.scss
  45. 6
      ui/app/components/app/connected-accounts-list/index.scss
  46. 2
      ui/app/components/app/contact-list/contact-list.component.js
  47. 2
      ui/app/components/app/contact-list/recipient-group/recipient-group.component.js
  48. 2
      ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js
  49. 4
      ui/app/components/app/gas-customization/gas-modal-page-container/index.scss
  50. 8
      ui/app/components/app/gas-customization/gas-price-button-group/index.scss
  51. 2
      ui/app/components/app/gas-customization/gas-slider/index.scss
  52. 2
      ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js
  53. 6
      ui/app/components/app/modals/edit-approval-permission/index.scss
  54. 8
      ui/app/components/app/modals/fade-modal.js
  55. 1
      ui/app/components/app/multiple-notifications/index.scss
  56. 4
      ui/app/components/app/permission-page-container/index.scss
  57. 2
      ui/app/components/app/permissions-connect-footer/index.scss
  58. 1
      ui/app/components/app/sidebars/sidebar-content.scss
  59. 4
      ui/app/components/app/signature-request/signature-request-footer/index.scss
  60. 2
      ui/app/components/app/transaction-activity-log/index.scss
  61. 2
      ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js
  62. 2
      ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js
  63. 4
      ui/app/components/app/transaction-list-item/transaction-list-item.component.js
  64. 12
      ui/app/components/ui/alert-circle-icon/index.scss
  65. 7
      ui/app/components/ui/button/buttons.scss
  66. 4
      ui/app/components/ui/check-box/index.scss
  67. 2
      ui/app/components/ui/export-text-container/index.scss
  68. 8
      ui/app/components/ui/icon/index.scss
  69. 2
      ui/app/components/ui/identicon/index.scss
  70. 2
      ui/app/components/ui/tabs/tab/index.scss
  71. 2
      ui/app/components/ui/unit-input/tests/unit-input.component.test.js
  72. 13
      ui/app/css/index.scss
  73. 2
      ui/app/css/itcss/components/account-dropdown.scss
  74. 2
      ui/app/css/itcss/components/confirm.scss
  75. 2
      ui/app/css/itcss/components/modal.scss
  76. 4
      ui/app/css/itcss/components/new-account.scss
  77. 2
      ui/app/css/itcss/components/pages/permission-approval.scss
  78. 2
      ui/app/css/itcss/components/request-signature.scss
  79. 16
      ui/app/css/itcss/components/send.scss
  80. 69
      ui/app/css/itcss/settings/variables.scss
  81. 76
      ui/app/css/variables/colors.scss
  82. 1
      ui/app/css/variables/index.scss
  83. 1
      ui/app/helpers/higher-order-components/with-method-data/index.js
  84. 65
      ui/app/helpers/higher-order-components/with-method-data/with-method-data.component.js
  85. 4
      ui/app/helpers/utils/util.js
  86. 4
      ui/app/helpers/utils/util.test.js
  87. 2
      ui/app/hooks/tests/useCancelTransaction.test.js
  88. 2
      ui/app/hooks/useTransactionDisplayData.js
  89. 2
      ui/app/pages/add-token/index.scss
  90. 8
      ui/app/pages/confirm-approve/confirm-approve-content/index.scss
  91. 2
      ui/app/pages/connected-accounts/index.scss
  92. 2
      ui/app/pages/connected-sites/index.scss
  93. 2
      ui/app/pages/first-time-flow/index.scss
  94. 2
      ui/app/pages/first-time-flow/onboarding-initiator-util.js
  95. 2
      ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss
  96. 4
      ui/app/pages/permissions-connect/choose-account/index.scss
  97. 2
      ui/app/pages/send/send-footer/tests/send-footer-component.test.js
  98. 2
      ui/app/pages/send/send-header/tests/send-header-component.test.js
  99. 8
      ui/app/pages/send/tests/send-utils.test.js
  100. 32
      ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -41,6 +41,12 @@ module.exports = {
}, },
rules: { rules: {
/* TODO: Remove these when upgrading to `@metamask/eslint-config@2` */
'array-callback-return': 'error',
'callback-return': 'error',
'global-require': 'error',
'guard-for-in': 'error',
/* End v2 rules */
'arrow-parens': 'error', 'arrow-parens': 'error',
'no-tabs': 'error', 'no-tabs': 'error',
'no-mixed-operators': 'error', 'no-mixed-operators': 'error',
@ -101,6 +107,13 @@ module.exports = {
rules: { rules: {
'import/no-anonymous-default-export': ['error', { 'allowObject': true }], 'import/no-anonymous-default-export': ['error', { 'allowObject': true }],
}, },
}, {
files: [
'app/scripts/migrations/*.js',
],
rules: {
'global-require': 'off',
},
}], }],
settings: { settings: {

@ -2,6 +2,15 @@
## Current Develop Branch ## Current Develop Branch
## 8.0.6 Wed Jul 22 2020
- [#9030](https://github.com/MetaMask/metamask-extension/pull/9030): Hide "delete" button when editing contact of wallet account
- [#9031](https://github.com/MetaMask/metamask-extension/pull/9031): Fix crash upon removing contact
- [#9032](https://github.com/MetaMask/metamask-extension/pull/9032): Do not show spend limit for approvals
- [#9046](https://github.com/MetaMask/metamask-extension/pull/9046): Update @metamask/inpage-provider@6.1.0
- [#9048](https://github.com/MetaMask/metamask-extension/pull/9048): Skip attempts to resolve 0x contract prefix
- [#9051](https://github.com/MetaMask/metamask-extension/pull/9051): Use content-hash@2.5.2
- [#9056](https://github.com/MetaMask/metamask-extension/pull/9056): Display at least one significant digit of small non-zero token balances
## 8.0.5 Thu Jul 16 2020 ## 8.0.5 Thu Jul 16 2020
- [#8942](https://github.com/MetaMask/metamask-extension/pull/8942): Fix display of incoming transactions (#8942) - [#8942](https://github.com/MetaMask/metamask-extension/pull/8942): Fix display of incoming transactions (#8942)
- [#8998](https://github.com/MetaMask/metamask-extension/pull/8998): Fix `web3_clientVersion` method (#8998) - [#8998](https://github.com/MetaMask/metamask-extension/pull/8998): Fix `web3_clientVersion` method (#8998)

@ -224,6 +224,10 @@
"approve": { "approve": {
"message": "Approve spend limit" "message": "Approve spend limit"
}, },
"approveSpendLimit": {
"message": "Approve $1 spend limit",
"description": "The token symbol that is being approved"
},
"approved": { "approved": {
"message": "Approved" "message": "Approved"
}, },

@ -1,7 +1,7 @@
{ {
"name": "__MSG_appName__", "name": "__MSG_appName__",
"short_name": "__MSG_appName__", "short_name": "__MSG_appName__",
"version": "8.0.5", "version": "8.0.6",
"manifest_version": 2, "manifest_version": 2,
"author": "https://metamask.io", "author": "https://metamask.io",
"description": "__MSG_appDescription__", "description": "__MSG_appDescription__",

@ -25,8 +25,7 @@ export default class DetectTokensController {
} }
/** /**
* For each token in eth-contract-metada, find check selectedAddress balance. * For each token in eth-contract-metadata, find check selectedAddress balance.
*
*/ */
async detectNewTokens () { async detectNewTokens () {
if (!this.isActive) { if (!this.isActive) {

@ -107,6 +107,7 @@ export default function createMethodMiddleware ({
} }
// when this promise resolves, the response is on its way back // when this promise resolves, the response is on its way back
// eslint-disable-next-line callback-return
await next() await next()
if (responseHandler) { if (responseHandler) {

@ -206,13 +206,15 @@ export default class PreferencesController {
res.result = result res.result = result
end() end()
} }
break return
default: default:
end(new Error(`Asset of type ${type} not supported`)) end(new Error(`Asset of type ${type} not supported`))
return
} }
} else {
next()
} }
next()
return
} }
/** /**
@ -335,9 +337,9 @@ export default class PreferencesController {
} }
// store lost accounts // store lost accounts
for (const key in newlyLost) { Object.keys(newlyLost).forEach((key) => {
lostIdentities[key] = newlyLost[key] lostIdentities[key] = newlyLost[key]
} })
} }
this.store.updateState({ identities, lostIdentities }) this.store.updateState({ identities, lostIdentities })

@ -31,7 +31,7 @@ txMeta = {
"time": 1524094064821, // time of creation "time": 1524094064821, // time of creation
"status": "confirmed", "status": "confirmed",
"metamaskNetworkId": "1524091532133", //the network id for the transaction "metamaskNetworkId": "1524091532133", //the network id for the transaction
"loadingDefaults": false, // used to tell the ui when we are done calculatyig gass defaults "loadingDefaults": false, // used to tell the ui when we are done calculating gas defaults
"txParams": { // the txParams object "txParams": { // the txParams object
"from": "0x8acce2391c0d510a6c5e5d8f819a678f79b7e675", "from": "0x8acce2391c0d510a6c5e5d8f819a678f79b7e675",
"to": "0x8acce2391c0d510a6c5e5d8f819a678f79b7e675", "to": "0x8acce2391c0d510a6c5e5d8f819a678f79b7e675",

@ -23,7 +23,7 @@ export function migrateFromSnapshotsToDiffs (longHistory) {
Generates an array of history objects sense the previous state. Generates an array of history objects sense the previous state.
The object has the keys The object has the keys
op (the operation performed), op (the operation performed),
path (the key and if a nested object then each key will be seperated with a `/`) path (the key and if a nested object then each key will be separated with a `/`)
value value
with the first entry having the note and a timestamp when the change took place with the first entry having the note and a timestamp when the change took place
@param {Object} previousState - the previous state of the object @param {Object} previousState - the previous state of the object

@ -7,7 +7,7 @@ import log from 'loglevel'
* debug information for a failed analysis. * debug information for a failed analysis.
* @typedef {Object} GasAnalysisResult * @typedef {Object} GasAnalysisResult
* @property {string} blockGasLimit - The gas limit of the block used for the analysis * @property {string} blockGasLimit - The gas limit of the block used for the analysis
* @property {string} estimatedGasHex - The estimated gas, in hexidecimal * @property {string} estimatedGasHex - The estimated gas, in hexadecimal
* @property {Object} simulationFails - Debug information about why an analysis failed * @property {Object} simulationFails - Debug information about why an analysis failed
*/ */

@ -100,7 +100,7 @@ export default class TransactionStateManager extends EventEmitter {
} }
/** /**
@returns {array} - the tx list whos status is unapproved @returns {array} - the tx list whose status is unapproved
*/ */
getUnapprovedTxList () { getUnapprovedTxList () {
const txList = this.getTxsByMetaData('status', 'unapproved') const txList = this.getTxsByMetaData('status', 'unapproved')
@ -112,7 +112,7 @@ export default class TransactionStateManager extends EventEmitter {
/** /**
@param [address] {string} - hex prefixed address to sort the txMetas for [optional] @param [address] {string} - hex prefixed address to sort the txMetas for [optional]
@returns {array} - the tx list whos status is approved if no address is provide @returns {array} - the tx list whose status is approved if no address is provide
returns all txMetas who's status is approved for the current network returns all txMetas who's status is approved for the current network
*/ */
getApprovedTransactions (address) { getApprovedTransactions (address) {
@ -125,7 +125,7 @@ export default class TransactionStateManager extends EventEmitter {
/** /**
@param [address] {string} - hex prefixed address to sort the txMetas for [optional] @param [address] {string} - hex prefixed address to sort the txMetas for [optional]
@returns {array} - the tx list whos status is submitted if no address is provide @returns {array} - the tx list whose status is submitted if no address is provide
returns all txMetas who's status is submitted for the current network returns all txMetas who's status is submitted for the current network
*/ */
getPendingTransactions (address) { getPendingTransactions (address) {
@ -138,7 +138,7 @@ export default class TransactionStateManager extends EventEmitter {
/** /**
@param [address] {string} - hex prefixed address to sort the txMetas for [optional] @param [address] {string} - hex prefixed address to sort the txMetas for [optional]
@returns {array} - the tx list whos status is confirmed if no address is provide @returns {array} - the tx list whose status is confirmed if no address is provide
returns all txMetas who's status is confirmed for the current network returns all txMetas who's status is confirmed for the current network
*/ */
getConfirmedTransactions (address) { getConfirmedTransactions (address) {
@ -153,7 +153,7 @@ export default class TransactionStateManager extends EventEmitter {
Adds the txMeta to the list of transactions in the store. Adds the txMeta to the list of transactions in the store.
if the list is over txHistoryLimit it will remove a transaction that if the list is over txHistoryLimit it will remove a transaction that
is in its final state is in its final state
it will allso add the key `history` to the txMeta with the snap shot of the original it will also add the key `history` to the txMeta with the snap shot of the original
object object
@param {Object} txMeta @param {Object} txMeta
@returns {Object} - the txMeta @returns {Object} - the txMeta

@ -25,11 +25,13 @@ export default class ComposableObservableStore extends ObservableStore {
this.config = config this.config = config
this.removeAllListeners() this.removeAllListeners()
for (const key in config) { for (const key in config) {
if (config.hasOwnProperty(key)) {
config[key].subscribe((state) => { config[key].subscribe((state) => {
this.updateState({ [key]: state }) this.updateState({ [key]: state })
}) })
} }
} }
}
/** /**
* Merges all child store state into a single object rather than * Merges all child store state into a single object rather than
@ -40,10 +42,12 @@ export default class ComposableObservableStore extends ObservableStore {
getFlatState () { getFlatState () {
let flatState = {} let flatState = {}
for (const key in this.config) { for (const key in this.config) {
if (this.config.hasOwnProperty(key)) {
const controller = this.config[key] const controller = this.config[key]
const state = controller.getState ? controller.getState() : controller.state const state = controller.getState ? controller.getState() : controller.state
flatState = { ...flatState, ...state } flatState = { ...flatState, ...state }
} }
}
return flatState return flatState
} }
} }

@ -9,7 +9,7 @@ class AsyncWritableStream extends WritableStream {
this._asyncWriteFn = asyncWriteFn this._asyncWriteFn = asyncWriteFn
} }
// write from incomming stream to state // write from incoming stream to state
_write (chunk, encoding, callback) { _write (chunk, encoding, callback) {
promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback) promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback)
} }

@ -30,9 +30,9 @@ export default class DecryptMessageManager extends EventEmitter {
* Controller in charge of managing - storing, adding, removing, updating - DecryptMessage. * Controller in charge of managing - storing, adding, removing, updating - DecryptMessage.
* *
* @typedef {Object} DecryptMessageManager * @typedef {Object} DecryptMessageManager
* @property {Object} memStore The observable store where DecryptMessage are saved with persistance. * @property {Object} memStore The observable store where DecryptMessage are saved.
* @property {Object} memStore.unapprovedDecryptMsgs A collection of all DecryptMessages in the 'unapproved' state * @property {Object} memStore.unapprovedDecryptMsgs A collection of all DecryptMessages in the 'unapproved' state
* @property {number} memStore.unapprovedDecryptMsgCount The count of all DecryptMessages in this.memStore.unapprobedMsgs * @property {number} memStore.unapprovedDecryptMsgCount The count of all DecryptMessages in this.memStore.unapprovedDecryptMsgs
* @property {array} messages Holds all messages that have been created by this DecryptMessageManager * @property {array} messages Holds all messages that have been created by this DecryptMessageManager
* *
*/ */

@ -32,7 +32,7 @@ export default class MessageManager extends EventEmitter {
* @param {Object} opts @deprecated * @param {Object} opts @deprecated
* @property {Object} memStore The observable store where Messages are saved. * @property {Object} memStore The observable store where Messages are saved.
* @property {Object} memStore.unapprovedMsgs A collection of all Messages in the 'unapproved' state * @property {Object} memStore.unapprovedMsgs A collection of all Messages in the 'unapproved' state
* @property {number} memStore.unapprovedMsgCount The count of all Messages in this.memStore.unapprobedMsgs * @property {number} memStore.unapprovedMsgCount The count of all Messages in this.memStore.unapprovedMsgs
* @property {array} messages Holds all messages that have been created by this MessageManager * @property {array} messages Holds all messages that have been created by this MessageManager
* *
*/ */
@ -99,7 +99,7 @@ export default class MessageManager extends EventEmitter {
* new Message to this.messages, and to save the unapproved Messages from that list to this.memStore. * new Message to this.messages, and to save the unapproved Messages from that list to this.memStore.
* *
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
* @param {Object} req (optional) The original request object where the origin may be specificied * @param {Object} req (optional) The original request object where the origin may be specified
* @returns {number} - The id of the newly created message. * @returns {number} - The id of the newly created message.
* *
*/ */

@ -35,8 +35,7 @@ export default class Migrator extends EventEmitter {
const pendingMigrations = this.migrations.filter(migrationIsPending) const pendingMigrations = this.migrations.filter(migrationIsPending)
// perform each migration // perform each migration
for (const index in pendingMigrations) { for (const migration of pendingMigrations) {
const migration = pendingMigrations[index]
try { try {
// attempt migration and validate // attempt migration and validate
const migratedData = await migration.migrate(versionedData) const migratedData = await migration.migrate(versionedData)

@ -68,7 +68,7 @@ export default class NotificationManager {
* type 'popup') * type 'popup')
* *
* @private * @private
* @param {Function} cb - A node style callback that to whcih the found notification window will be passed. * @param {Function} cb - A node style callback that to which the found notification window will be passed.
* *
*/ */
async _getPopup () { async _getPopup () {

@ -33,7 +33,7 @@ export default class PersonalMessageManager extends EventEmitter {
* *
* @typedef {Object} PersonalMessageManager * @typedef {Object} PersonalMessageManager
* @param {Object} opts @deprecated * @param {Object} opts @deprecated
* @property {Object} memStore The observable store where PersonalMessage are saved with persistance. * @property {Object} memStore The observable store where PersonalMessage are saved.
* @property {Object} memStore.unapprovedPersonalMsgs A collection of all PersonalMessages in the 'unapproved' state * @property {Object} memStore.unapprovedPersonalMsgs A collection of all PersonalMessages in the 'unapproved' state
* @property {number} memStore.unapprovedPersonalMsgCount The count of all PersonalMessages in this.memStore.unapprobedMsgs * @property {number} memStore.unapprovedPersonalMsgCount The count of all PersonalMessages in this.memStore.unapprobedMsgs
* @property {array} messages Holds all messages that have been created by this PersonalMessageManager * @property {array} messages Holds all messages that have been created by this PersonalMessageManager

@ -101,6 +101,9 @@ export default function setupSentry ({ release, getState }) {
// append app state // append app state
if (getState) { if (getState) {
const appState = getState() const appState = getState()
if (!report.extra) {
report.extra = {}
}
report.extra.appState = appState report.extra.appState = appState
} }
} catch (err) { } catch (err) {

@ -134,7 +134,7 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) {
/** /**
* Returns an Error if extension.runtime.lastError is present * Returns an Error if extension.runtime.lastError is present
* this is a workaround for the non-standard error object thats used * this is a workaround for the non-standard error object that's used
* @returns {Error} * @returns {Error}
*/ */
function checkForError () { function checkForError () {

@ -1119,6 +1119,7 @@ export default class MetamaskController extends EventEmitter {
messageManager.rejectMsg(msgId) messageManager.rejectMsg(msgId)
if (cb && typeof cb === 'function') { if (cb && typeof cb === 'function') {
cb(null, this.getState()) cb(null, this.getState())
return
} }
} }
@ -1177,6 +1178,7 @@ export default class MetamaskController extends EventEmitter {
messageManager.rejectMsg(msgId) messageManager.rejectMsg(msgId)
if (cb && typeof cb === 'function') { if (cb && typeof cb === 'function') {
cb(null, this.getState()) cb(null, this.getState())
return
} }
} }
@ -1197,7 +1199,7 @@ export default class MetamaskController extends EventEmitter {
} }
/** /**
* Only decypt message and don't touch transaction state * Only decrypt message and don't touch transaction state
* *
* @param {Object} msgParams - The params of the message to decrypt. * @param {Object} msgParams - The params of the message to decrypt.
* @returns {Promise<Object>} - A full state update. * @returns {Promise<Object>} - A full state update.
@ -1261,6 +1263,7 @@ export default class MetamaskController extends EventEmitter {
messageManager.rejectMsg(msgId) messageManager.rejectMsg(msgId)
if (cb && typeof cb === 'function') { if (cb && typeof cb === 'function') {
cb(null, this.getState()) cb(null, this.getState())
return
} }
} }
@ -1318,6 +1321,7 @@ export default class MetamaskController extends EventEmitter {
messageManager.rejectMsg(msgId) messageManager.rejectMsg(msgId)
if (cb && typeof cb === 'function') { if (cb && typeof cb === 'function') {
cb(null, this.getState()) cb(null, this.getState())
return
} }
} }
@ -1377,6 +1381,7 @@ export default class MetamaskController extends EventEmitter {
messageManager.rejectMsg(msgId) messageManager.rejectMsg(msgId)
if (cb && typeof cb === 'function') { if (cb && typeof cb === 'function') {
cb(null, this.getState()) cb(null, this.getState())
return
} }
} }
@ -1843,8 +1848,10 @@ export default class MetamaskController extends EventEmitter {
this.currencyRateController.update(currencyState) this.currencyRateController.update(currencyState)
this.currencyRateController.configure(currencyState) this.currencyRateController.configure(currencyState)
cb(null, this.currencyRateController.state) cb(null, this.currencyRateController.state)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1925,8 +1932,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setUseBlockie(val) this.preferencesController.setUseBlockie(val)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1939,8 +1948,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setUseNonceField(val) this.preferencesController.setUseNonceField(val)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1953,8 +1964,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setUsePhishDetect(val) this.preferencesController.setUsePhishDetect(val)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1967,8 +1980,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setIpfsGateway(val) this.preferencesController.setIpfsGateway(val)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1981,8 +1996,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
const metaMetricsId = this.preferencesController.setParticipateInMetaMetrics(bool) const metaMetricsId = this.preferencesController.setParticipateInMetaMetrics(bool)
cb(null, metaMetricsId) cb(null, metaMetricsId)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -1990,8 +2007,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setMetaMetricsSendCount(val) this.preferencesController.setMetaMetricsSendCount(val)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -2004,8 +2023,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
this.preferencesController.setFirstTimeFlowType(type) this.preferencesController.setFirstTimeFlowType(type)
cb(null) cb(null)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }
@ -2019,8 +2040,10 @@ export default class MetamaskController extends EventEmitter {
try { try {
const direction = this.preferencesController.setCurrentLocale(key) const direction = this.preferencesController.setCurrentLocale(key)
cb(null, direction) cb(null, direction)
return
} catch (err) { } catch (err) {
cb(err) cb(err)
return
} }
} }

@ -29,9 +29,9 @@ function transformState (state) {
const identities = newState.PreferencesController.identities const identities = newState.PreferencesController.identities
const tokens = newState.PreferencesController.tokens const tokens = newState.PreferencesController.tokens
newState.PreferencesController.accountTokens = {} newState.PreferencesController.accountTokens = {}
for (const identity in identities) { Object.keys(identities).forEach((identity) => {
newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens } newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens }
} })
newState.PreferencesController.tokens = [] newState.PreferencesController.tokens = []
} }
} }

@ -27,9 +27,9 @@ function transformState (state) {
const newAddressBook = {} const newAddressBook = {}
// add all of the chainIds to a set // add all of the chainIds to a set
for (const item in ab) { Object.values(ab).forEach((v) => {
chainIds.add(ab[item].chainId) chainIds.add(v.chainId)
} })
// fill the chainId object with the entries with the matching chainId // fill the chainId object with the entries with the matching chainId
for (const id of chainIds.values()) { for (const id of chainIds.values()) {

@ -105,6 +105,7 @@ export default class ExtensionPlatform {
}) })
} catch (e) { } catch (e) {
cb(e) cb(e)
return
} }
} }

@ -15,7 +15,7 @@ const SYMBOLS = {
Quarter: '▎', Quarter: '▎',
Eighth: '▏', Eighth: '▏',
RightHalf: '▐', RightHalf: '▐',
RightEigth: '▕', RightEighth: '▕',
} }
function setupTaskDisplay (taskEvents) { function setupTaskDisplay (taskEvents) {
@ -47,7 +47,7 @@ function displayChart (data) {
console.log(`\nbuild completed. task timeline:`) console.log(`\nbuild completed. task timeline:`)
// build bars for bounds // build bars for bounds
data.map((entry, index) => { data.forEach((entry, index) => {
const [label, start, end] = entry const [label, start, end] = entry
const [start2, end2] = [start, end].map((value) => adjust(value, first, last, 40)) const [start2, end2] = [start, end].map((value) => adjust(value, first, last, 40))
const barString = barBuilder(start2, end2) const barString = barBuilder(start2, end2)
@ -141,7 +141,7 @@ function getSymbolNormalRight (value) {
} else if (rounded === 1 / 2) { } else if (rounded === 1 / 2) {
return SYMBOLS.RightHalf return SYMBOLS.RightHalf
} else if (rounded === 7 / 8) { } else if (rounded === 7 / 8) {
return SYMBOLS.RightEigth return SYMBOLS.RightEighth
} else if (rounded === 1) { } else if (rounded === 1) {
return SYMBOLS.Space return SYMBOLS.Space
} else { } else {

@ -22,6 +22,7 @@ _int () {
trap _term SIGTERM trap _term SIGTERM
trap _int SIGINT trap _int SIGINT
# shellcheck disable=SC2086
$ganache_cli --noVMErrorsOnRPCResponse --networkId 5777 --mnemonic "$seed_phrase" ${GANACHE_ARGS:-} & $ganache_cli --noVMErrorsOnRPCResponse --networkId 5777 --mnemonic "$seed_phrase" ${GANACHE_ARGS:-} &
child=$! child=$!

@ -10,5 +10,5 @@ You can optionally enable debugging, and click `Debug`, for a console window tha
If you have problems debugging, try connecting to the IRC channel `#webextensions` on `irc.mozilla.org`. If you have problems debugging, try connecting to the IRC channel `#webextensions` on `irc.mozilla.org`.
For longer questions, use the StackOverfow tag `firefox-addons`. For longer questions, use the StackOverflow tag `firefox-addons`.

@ -67,9 +67,9 @@
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@metamask/controllers": "^2.0.1", "@metamask/controllers": "^2.0.1",
"@metamask/eth-ledger-bridge-keyring": "^0.2.6", "@metamask/eth-ledger-bridge-keyring": "^0.2.6",
"@metamask/eth-token-tracker": "^2.0.0", "@metamask/eth-token-tracker": "^3.0.0",
"@metamask/etherscan-link": "^1.1.0", "@metamask/etherscan-link": "^1.1.0",
"@metamask/inpage-provider": "^6.0.1", "@metamask/inpage-provider": "^6.1.0",
"@popperjs/core": "^2.4.0", "@popperjs/core": "^2.4.0",
"@reduxjs/toolkit": "^1.3.2", "@reduxjs/toolkit": "^1.3.2",
"@sentry/browser": "^5.11.1", "@sentry/browser": "^5.11.1",
@ -83,7 +83,7 @@
"bn.js": "^4.11.7", "bn.js": "^4.11.7",
"c3": "^0.7.10", "c3": "^0.7.10",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"content-hash": "^2.5.0", "content-hash": "^2.5.2",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"currency-formatter": "^1.4.2", "currency-formatter": "^1.4.2",
"d3": "^5.15.0", "d3": "^5.15.0",

@ -43,7 +43,7 @@ const standardDeviationResult = calculateResult((array) => {
const squareDiffs = array.map((value) => Math.pow(value - average, 2)) const squareDiffs = array.map((value) => Math.pow(value - average, 2))
return Math.sqrt(calculateAverage(squareDiffs)) return Math.sqrt(calculateAverage(squareDiffs))
}) })
// 95% margin of error calculated using Student's t-distrbution // 95% margin of error calculated using Student's t-distribution
const calculateMarginOfError = (array) => ttest(array).confidence()[1] - calculateAverage(array) const calculateMarginOfError = (array) => ttest(array).confidence()[1] - calculateAverage(array)
const marginOfErrorResult = calculateResult((array) => calculateMarginOfError(array)) const marginOfErrorResult = calculateResult((array) => calculateMarginOfError(array))

@ -33,6 +33,7 @@ async function withFixtures (options, callback) {
const { driver } = await buildWebDriver(driverOptions) const { driver } = await buildWebDriver(driverOptions)
webDriver = driver webDriver = driver
// eslint-disable-next-line callback-return
await callback({ await callback({
driver, driver,
}) })
@ -46,7 +47,9 @@ async function withFixtures (options, callback) {
} }
} }
} catch (error) { } catch (error) {
if (webDriver) {
await webDriver.verboseReportOnFailure(title) await webDriver.verboseReportOnFailure(title)
}
throw error throw error
} finally { } finally {
await fixtureServer.stop() await fixtureServer.stop()

@ -830,9 +830,9 @@ describe('MetaMask', function () {
it('renders the balance for the new token', async function () { it('renders the balance for the new token', async function () {
const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance')) const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /^10.000\s*TST\s*$/)) await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/))
const tokenAmount = await balance.getText() const tokenAmount = await balance.getText()
assert.ok(/^10.000\s*TST\s*$/.test(tokenAmount)) assert.ok(/^10\s*TST\s*$/.test(tokenAmount))
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
}) })
}) })
@ -992,7 +992,7 @@ describe('MetaMask', function () {
await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/), 10000) await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/), 10000)
const tokenBalanceAmount = await driver.findElements(By.css('.token-overview__primary-balance')) const tokenBalanceAmount = await driver.findElements(By.css('.token-overview__primary-balance'))
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000) await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/), 10000)
}) })
}) })
@ -1018,8 +1018,8 @@ describe('MetaMask', function () {
return pendingTxes.length === 1 return pendingTxes.length === 1
}, 10000) }, 10000)
const [txListValue] = await driver.findElements(By.css('.transaction-list-item__primary-currency')) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading'))
await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/))
await driver.clickElement(By.css('.transaction-list-item')) await driver.clickElement(By.css('.transaction-list-item'))
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
}) })
@ -1104,14 +1104,12 @@ describe('MetaMask', function () {
return confirmedTxes.length === 3 return confirmedTxes.length === 3
}, 10000) }, 10000)
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
await driver.wait(until.elementTextMatches(txValues[0], /-5\s*TST/))
const txStatuses = await driver.findElements(By.css('.list-item__heading')) const txStatuses = await driver.findElements(By.css('.list-item__heading'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/))
}) })
}) })
describe('Tranfers a custom token from dapp when no gas value is specified', function () { describe('Transfers a custom token from dapp when no gas value is specified', function () {
it('transfers an already created token, without specifying gas', async function () { it('transfers an already created token, without specifying gas', async function () {
const windowHandles = await driver.getAllWindowHandles() const windowHandles = await driver.getAllWindowHandles()
const extension = windowHandles[0] const extension = windowHandles[0]
@ -1177,8 +1175,8 @@ describe('MetaMask', function () {
return pendingTxes.length === 1 return pendingTxes.length === 1
}, 10000) }, 10000)
const [txListValue] = await driver.findElements(By.css('.transaction-list-item__primary-currency')) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading'))
await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/))
await driver.clickElement(By.css('.transaction-list-item')) await driver.clickElement(By.css('.transaction-list-item'))
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
}) })
@ -1204,10 +1202,8 @@ describe('MetaMask', function () {
return confirmedTxes.length === 5 return confirmedTxes.length === 5
}, 10000) }, 10000)
const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency'))
await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
const txStatuses = await driver.findElements(By.css('.list-item__heading')) const txStatuses = await driver.findElements(By.css('.list-item__heading'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/))
}) })
}) })

@ -51,7 +51,7 @@ describe('MetaMask', function () {
await driver.quit() await driver.quit()
}) })
describe('successfuly signs typed data', function () { describe('successfully signs typed data', function () {
let extension let extension
let popup let popup
let dapp let dapp

@ -9,7 +9,7 @@ async function buildWebDriver ({ responsive, port } = {}) {
const extensionPath = `dist/${browser}` const extensionPath = `dist/${browser}`
const { driver: seleniumDriver, extensionId, extensionUrl } = await buildBrowserWebDriver(browser, { extensionPath, responsive, port }) const { driver: seleniumDriver, extensionId, extensionUrl } = await buildBrowserWebDriver(browser, { extensionPath, responsive, port })
setupFetchMocking(seleniumDriver) await setupFetchMocking(seleniumDriver)
const driver = new Driver(seleniumDriver, browser, extensionUrl) const driver = new Driver(seleniumDriver, browser, extensionUrl)
await driver.navigate() await driver.navigate()

@ -3,6 +3,8 @@ import nock from 'nock'
import Enzyme from 'enzyme' import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16' import Adapter from 'enzyme-adapter-react-16'
import log from 'loglevel' import log from 'loglevel'
import { JSDOM } from 'jsdom'
nock.disableNetConnect() nock.disableNetConnect()
nock.enableNetConnect('localhost') nock.enableNetConnect('localhost')
@ -45,8 +47,6 @@ global.log = log
// //
// dom // dom
const { JSDOM } = require('jsdom')
const jsdom = new JSDOM() const jsdom = new JSDOM()
global.window = jsdom.window global.window = jsdom.window
@ -87,5 +87,6 @@ if (!window.crypto) {
window.crypto = {} window.crypto = {}
} }
if (!window.crypto.getRandomValues) { if (!window.crypto.getRandomValues) {
// eslint-disable-next-line global-require
window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues') window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues')
} }

@ -89,8 +89,8 @@ describe('DetectTokensController', function () {
controller.isOpen = true controller.isOpen = true
controller.isUnlocked = true controller.isUnlocked = true
const contractAddressses = Object.keys(contracts) const contractAddresses = Object.keys(contracts)
const erc20ContractAddresses = contractAddressses const erc20ContractAddresses = contractAddresses
.filter((contractAddress) => contracts[contractAddress].erc20 === true) .filter((contractAddress) => contracts[contractAddress].erc20 === true)
const existingTokenAddress = erc20ContractAddresses[0] const existingTokenAddress = erc20ContractAddresses[0]
@ -100,7 +100,7 @@ describe('DetectTokensController', function () {
const tokenAddressToAdd = erc20ContractAddresses[1] const tokenAddressToAdd = erc20ContractAddresses[1]
const tokenToAdd = contracts[tokenAddressToAdd] const tokenToAdd = contracts[tokenAddressToAdd]
const contractAddresssesToDetect = contractAddressses const contractAddresssesToDetect = contractAddresses
.filter((address) => address !== existingTokenAddress) .filter((address) => address !== existingTokenAddress)
const indexOfTokenToAdd = contractAddresssesToDetect.indexOf(tokenAddressToAdd) const indexOfTokenToAdd = contractAddresssesToDetect.indexOf(tokenAddressToAdd)

@ -53,9 +53,9 @@ const createLoggerMiddlewareMock = () => (req, res, next) => {
loggerMiddlewareMock.responses.push(res) loggerMiddlewareMock.responses.push(res)
cb() cb()
}) })
} else { return
next()
} }
next()
} }
const MetaMaskController = proxyquire('../../../../app/scripts/metamask-controller', { const MetaMaskController = proxyquire('../../../../app/scripts/metamask-controller', {
@ -839,9 +839,9 @@ describe('MetaMaskController', function () {
const streamTest = createThoughStream((chunk, _, cb) => { const streamTest = createThoughStream((chunk, _, cb) => {
if (chunk.data && chunk.data.method) { if (chunk.data && chunk.data.method) {
cb(null, chunk) cb(null, chunk)
} else { return
cb()
} }
cb()
}) })
metamaskController.setupUntrustedCommunication(streamTest, messageSender) metamaskController.setupUntrustedCommunication(streamTest, messageSender)
@ -877,9 +877,9 @@ describe('MetaMaskController', function () {
const streamTest = createThoughStream((chunk, _, cb) => { const streamTest = createThoughStream((chunk, _, cb) => {
if (chunk.data && chunk.data.method) { if (chunk.data && chunk.data.method) {
cb(null, chunk) cb(null, chunk)
} else { return
cb()
} }
cb()
}) })
metamaskController.setupUntrustedCommunication(streamTest, messageSender) metamaskController.setupUntrustedCommunication(streamTest, messageSender)

@ -323,7 +323,7 @@ describe('TransactionStateManager', function () {
} }
const invalidValues = [1, true, {}, Symbol('1')] const invalidValues = [1, true, {}, Symbol('1')]
for (const key in validTxParams) { Object.keys(validTxParams).forEach((key) => {
for (const value of invalidValues) { for (const value of invalidValues) {
const tx = { const tx = {
id: 1, id: 1,
@ -339,7 +339,7 @@ describe('TransactionStateManager', function () {
assert.ok(Array.isArray(result), 'txList should be an array') assert.ok(Array.isArray(result), 'txList should be an array')
assert.equal(result.length, 0, 'txList should be empty') assert.equal(result.length, 0, 'txList should be empty')
} }
} })
}) })
it('does not override txs from other networks', function () { it('does not override txs from other networks', function () {
@ -361,7 +361,7 @@ describe('TransactionStateManager', function () {
} }
const result = txStateManager.getTxList() const result = txStateManager.getTxList()
assert.equal(result.length, limit, `limit of ${limit} txs enforced`) assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
assert.equal(result[0].id, 1, 'early txs truncted') assert.equal(result[0].id, 1, 'early txs truncated')
}) })
it('cuts off early txs beyond a limit whether or not it is confirmed or rejected', function () { it('cuts off early txs beyond a limit whether or not it is confirmed or rejected', function () {
@ -372,7 +372,7 @@ describe('TransactionStateManager', function () {
} }
const result = txStateManager.getTxList() const result = txStateManager.getTxList()
assert.equal(result.length, limit, `limit of ${limit} txs enforced`) assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
assert.equal(result[0].id, 1, 'early txs truncted') assert.equal(result[0].id, 1, 'early txs truncated')
}) })
it('cuts off early txs beyond a limit but does not cut unapproved txs', function () { it('cuts off early txs beyond a limit but does not cut unapproved txs', function () {
@ -387,7 +387,7 @@ describe('TransactionStateManager', function () {
assert.equal(result.length, limit, `limit of ${limit} txs enforced`) assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
assert.equal(result[0].id, 0, 'first tx should still be there') assert.equal(result[0].id, 0, 'first tx should still be there')
assert.equal(result[0].status, 'unapproved', 'first tx should be unapproved') assert.equal(result[0].status, 'unapproved', 'first tx should be unapproved')
assert.equal(result[1].id, 2, 'early txs truncted') assert.equal(result[1].id, 2, 'early txs truncated')
}) })
}) })
@ -416,7 +416,7 @@ describe('TransactionStateManager', function () {
txStateManager.addTx({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: validTxParams }) txStateManager.addTx({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: validTxParams })
for (const key in validTxParams) { Object.keys(validTxParams).forEach((key) => {
for (const value of invalidValues) { for (const value of invalidValues) {
const originalTx = txStateManager.getTx(1) const originalTx = txStateManager.getTx(1)
const newTx = { const newTx = {
@ -430,7 +430,7 @@ describe('TransactionStateManager', function () {
const result = txStateManager.getTx(1) const result = txStateManager.getTx(1)
assert.deepEqual(result, originalTx, 'tx should not be updated') assert.deepEqual(result, originalTx, 'tx should not be updated')
} }
} })
}) })
it('updates gas price and adds history items', function () { it('updates gas price and adds history items', function () {

@ -68,31 +68,31 @@ describe('storage is migrated successfully and the proper transactions are remov
leftoverNonDeletableTxCount++ leftoverNonDeletableTxCount++
} }
}) })
assert.equal(leftoverNonDeletableTxCount, nonDeletableCount, 'migration shouldnt delete transactions we want to keep') assert.equal(leftoverNonDeletableTxCount, nonDeletableCount, "migration shouldn't delete transactions we want to keep")
assert((migratedTransactions.length >= 40), `should be equal or greater to 40 if they are non deletable states got ${migratedTransactions.length} transactions`) assert((migratedTransactions.length >= 40), `should be equal or greater to 40 if they are non deletable states got ${migratedTransactions.length} transactions`)
done() done()
}).catch(done) }).catch(done)
}) })
it('should not remove any transactions because 40 is the expectable limit', function (done) { it('should not remove any transactions because 40 is the expected limit', function (done) {
storage.meta.version = 22 storage.meta.version = 22
storage.data.TransactionController.transactions = transactions40 storage.data.TransactionController.transactions = transactions40
migration23.migrate(storage) migration23.migrate(storage)
.then((migratedData) => { .then((migratedData) => {
const migratedTransactions = migratedData.data.TransactionController.transactions const migratedTransactions = migratedData.data.TransactionController.transactions
assert.equal(migratedTransactions.length, 40, 'migration shouldnt delete when at limit') assert.equal(migratedTransactions.length, 40, "migration shouldn't delete when at limit")
done() done()
}).catch(done) }).catch(done)
}) })
it('should not remove any transactions because 20 txs is under the expectable limit', function (done) { it('should not remove any transactions because 20 txs is under the expected limit', function (done) {
storage.meta.version = 22 storage.meta.version = 22
storage.data.TransactionController.transactions = transactions20 storage.data.TransactionController.transactions = transactions20
migration23.migrate(storage) migration23.migrate(storage)
.then((migratedData) => { .then((migratedData) => {
const migratedTransactions = migratedData.data.TransactionController.transactions const migratedTransactions = migratedData.data.TransactionController.transactions
assert.equal(migratedTransactions.length, 20, 'migration shouldnt delete when under limit') assert.equal(migratedTransactions.length, 20, "migration shouldn't delete when under limit")
done() done()
}).catch(done) }).catch(done)
}) })

@ -1,4 +1,5 @@
import assert from 'assert' import assert from 'assert'
import firstTimeState from '../../../app/scripts/first-time-state'
import migration26 from '../../../app/scripts/migrations/026' import migration26 from '../../../app/scripts/migrations/026'
const oldStorage = { const oldStorage = {
@ -32,7 +33,7 @@ describe('migration #26', function () {
it('should successfully migrate first time state', function (done) { it('should successfully migrate first time state', function (done) {
migration26.migrate({ migration26.migrate({
meta: {}, meta: {},
data: require('../../../app/scripts/first-time-state'), data: firstTimeState,
}) })
.then((migratedData) => { .then((migratedData) => {
assert.equal(migratedData.meta.version, migration26.version) assert.equal(migratedData.meta.version, migration26.version)

@ -1,4 +1,5 @@
import assert from 'assert' import assert from 'assert'
import firstTimeState from '../../../app/scripts/first-time-state'
import migration27 from '../../../app/scripts/migrations/027' import migration27 from '../../../app/scripts/migrations/027'
const oldStorage = { const oldStorage = {
@ -42,7 +43,7 @@ describe('migration #27', function () {
it('should successfully migrate first time state', function (done) { it('should successfully migrate first time state', function (done) {
migration27.migrate({ migration27.migrate({
meta: {}, meta: {},
data: require('../../../app/scripts/first-time-state'), data: firstTimeState,
}) })
.then((migratedData) => { .then((migratedData) => {
assert.equal(migratedData.meta.version, migration27.version) assert.equal(migratedData.meta.version, migration27.version)

@ -1,4 +1,5 @@
import assert from 'assert' import assert from 'assert'
import firstTimeState from '../../../app/scripts/first-time-state'
import migration28 from '../../../app/scripts/migrations/028' import migration28 from '../../../app/scripts/migrations/028'
const oldStorage = { const oldStorage = {
@ -36,7 +37,7 @@ describe('migration #28', function () {
it('should successfully migrate first time state', function (done) { it('should successfully migrate first time state', function (done) {
migration28.migrate({ migration28.migrate({
meta: {}, meta: {},
data: require('../../../app/scripts/first-time-state'), data: firstTimeState,
}) })
.then((migratedData) => { .then((migratedData) => {
assert.equal(migratedData.meta.version, migration28.version) assert.equal(migratedData.meta.version, migration28.version)

@ -12,7 +12,6 @@ describe('MetaMask Reducers', function () {
it('locks MetaMask', function () { it('locks MetaMask', function () {
const unlockMetaMaskState = { const unlockMetaMaskState = {
isUnlocked: true, isUnlocked: true,
isInitialzed: false,
selectedAddress: 'test address', selectedAddress: 'test address',
} }
const lockMetaMask = reduceMetamask(unlockMetaMaskState, { const lockMetaMask = reduceMetamask(unlockMetaMaskState, {

@ -17,7 +17,7 @@
} }
&__dismiss-button { &__dismiss-button {
background: #037dd6; background: $primary-blue;
color: white; color: white;
height: 40px; height: 40px;
width: 100px; width: 100px;
@ -29,7 +29,7 @@
margin-bottom: 16px; margin-bottom: 16px;
padding: 16px; padding: 16px;
font-size: 14px; font-size: 14px;
border: 1px solid #d73a49; border: 1px solid $accent-red;
background: #f8eae8; background: #f8eae8;
border-radius: 3px; border-radius: 3px;
} }

@ -35,7 +35,7 @@
color: $scorpion; color: $scorpion;
&--edit { &--edit {
color: $curious-blue; color: $primary-blue;
cursor: pointer; cursor: pointer;
} }

@ -34,7 +34,7 @@
&, &,
&:hover { &:hover {
color: $curious-blue; color: $primary-blue;
cursor: pointer; cursor: pointer;
} }
} }
@ -49,8 +49,8 @@
border-top: 1px solid $geyser; border-top: 1px solid $geyser;
&--highlight { &--highlight {
background-color: $warning-light-yellow; background-color: $Yellow-000;
border: 1px solid $warning-yellow; border: 1px solid $accent-yellow;
box-sizing: border-box; box-sizing: border-box;
padding: 16px; padding: 16px;
margin-bottom: 16px; margin-bottom: 16px;

@ -67,7 +67,7 @@ export default class ContactList extends PureComponent {
return 1 return 1
} else if (letter1 === letter2) { } else if (letter1 === letter2) {
return 0 return 0
} else if (letter1 < letter2) { } else {
return -1 return -1
} }
}) })

@ -53,7 +53,7 @@ export default function RecipientGroup ({ label, items, onSelect, selectedAddres
RecipientGroup.propTypes = { RecipientGroup.propTypes = {
label: PropTypes.string, label: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({ items: PropTypes.arrayOf(PropTypes.shape({
address: PropTypes.string, address: PropTypes.string.isRequired,
name: PropTypes.string, name: PropTypes.string,
})), })),
onSelect: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired,

@ -74,7 +74,7 @@ describe('Advanced Gas Inputs', function () {
assert.equal(props.updateCustomGasLimit.calledWith(21000), true) assert.equal(props.updateCustomGasLimit.calledWith(21000), true)
}) })
it('errors when insuffientBalance under gas price and gas limit', function () { it('errors when insufficientBalance under gas price and gas limit', function () {
wrapper.setProps({ insufficientBalance: true }) wrapper.setProps({ insufficientBalance: true })
const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text') const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text')
assert.equal(renderError.length, 2) assert.equal(renderError.length, 2)

@ -68,8 +68,8 @@
} }
&--selected { &--selected {
color: $curious-blue; color: $primary-blue;
border-bottom: 2px solid $curious-blue; border-bottom: 2px solid $primary-blue;
} }
} }
} }

@ -50,13 +50,13 @@
} }
.button-group__button--active { .button-group__button--active {
border: 2px solid $curious-blue; border: 2px solid $primary-blue;
color: $scorpion; color: $scorpion;
i { i {
&:last-child { &:last-child {
display: flex; display: flex;
color: $curious-blue; color: $primary-blue;
margin-top: 8px; margin-top: 8px;
} }
} }
@ -137,7 +137,7 @@
i { i {
&:last-child { &:last-child {
display: flex; display: flex;
color: $curious-blue; color: $primary-blue;
margin-top: 10px; margin-top: 10px;
} }
} }
@ -235,7 +235,7 @@
i { i {
display: flex; display: flex;
color: $curious-blue; color: $primary-blue;
font-size: 12px; font-size: 12px;
} }
} }

@ -16,7 +16,7 @@
-webkit-appearance: none !important; -webkit-appearance: none !important;
height: 34px; height: 34px;
width: 34px; width: 34px;
background-color: $curious-blue; background-color: $primary-blue;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
border-radius: 50%; border-radius: 50%;
position: relative; position: relative;

@ -33,7 +33,7 @@ describe('Confirm Reset Account', function () {
assert(props.hideModal.calledOnce) assert(props.hideModal.calledOnce)
}) })
it('resets account and hidels modal when reset button is clicked', function (done) { it('resets account and hides modal when reset button is clicked', function (done) {
const reset = wrapper.find('.btn-danger.modal-container__footer-button') const reset = wrapper.find('.btn-danger.modal-container__footer-button')
reset.simulate('click') reset.simulate('click')

@ -97,7 +97,7 @@
} }
&__option-label--selected { &__option-label--selected {
color: #037dd6; color: $primary-blue;
} }
&__option-description { &__option-description {
@ -136,7 +136,7 @@
} }
&__radio-button-outline--selected { &__radio-button-outline--selected {
background: #037dd6; background: $primary-blue;
} }
&__radio-button-fill { &__radio-button-fill {
@ -150,7 +150,7 @@
&__radio-button-dot { &__radio-button-dot {
width: 8px; width: 8px;
height: 8px; height: 8px;
background: #037dd6; background: $primary-blue;
border-radius: 4px; border-radius: 4px;
position: absolute; position: absolute;
} }

@ -25,16 +25,16 @@ const insertKeyframesRule = (keyframes) => {
const name = 'anim_' + (++index) + (+new Date()) const name = 'anim_' + (++index) + (+new Date())
let css = '@' + 'keyframes ' + name + ' {' let css = '@' + 'keyframes ' + name + ' {'
for (const key in keyframes) { Object.keys(keyframes).forEach((key) => {
css += key + ' {' css += key + ' {'
for (const property in keyframes[key]) { Object.keys(keyframes[key]).forEach((property) => {
const part = ':' + keyframes[key][property] + ';' const part = ':' + keyframes[key][property] + ';'
css += property + part css += property + part
} })
css += '}' css += '}'
} })
css += '}' css += '}'

@ -16,7 +16,6 @@
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
visibility: none;
.fa-sm { .fa-sm {
display: initial; display: initial;

@ -129,8 +129,8 @@
} }
&__tooltip-body { &__tooltip-body {
display: 'flex'; display: flex;
flex-direction: 'column'; flex-direction: column;
} }
&__bold-title-elements { &__bold-title-elements {

@ -14,7 +14,7 @@
margin-top: 10px; margin-top: 10px;
&--link { &--link {
color: #037dd6; color: $primary-blue;
margin-left: 4px; margin-left: 4px;
cursor: pointer; cursor: pointer;
} }

@ -34,7 +34,6 @@
.page-container__bottom { .page-container__bottom {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-flow: space-between;
height: 100%; height: 100%;
} }

@ -9,11 +9,11 @@
border-radius: 3px; border-radius: 3px;
} }
button:first-child() { button:first-child {
margin-left: 1rem; margin-left: 1rem;
} }
button:last-child() { button:last-child {
margin-right: 1rem; margin-right: 1rem;
} }
} }

@ -75,7 +75,7 @@
&__action-link { &__action-link {
font-size: 0.75rem; font-size: 0.75rem;
cursor: pointer; cursor: pointer;
color: $curious-blue; color: $primary-blue;
} }
b { b {

@ -3,7 +3,7 @@ import { combineTransactionHistories, getActivities } from '../transaction-activ
describe('TransactionActivityLog utils', function () { describe('TransactionActivityLog utils', function () {
describe('combineTransactionHistories', function () { describe('combineTransactionHistories', function () {
it('should return no activites for an empty list of transactions', function () { it('should return no activities for an empty list of transactions', function () {
assert.deepEqual(combineTransactionHistories([]), []) assert.deepEqual(combineTransactionHistories([]), [])
}) })

@ -171,7 +171,7 @@ export function getActivities (transaction, isFirstTransaction = false) {
return acc return acc
}, []) }, [])
// If txReceipt.status is '0x0', that means that an on-chain error occured for the transaction, // If txReceipt.status is '0x0', that means that an on-chain error occurred for the transaction,
// so we add an error entry to the Activity Log. // so we add an error entry to the Activity Log.
return status === '0x0' return status === '0x0'
? historyActivities.concat({ id, hash, eventKey: TRANSACTION_ERRORED_EVENT }) ? historyActivities.concat({ id, hash, eventKey: TRANSACTION_ERRORED_EVENT })

@ -15,6 +15,7 @@ import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'
import { import {
TRANSACTION_CATEGORY_SIGNATURE_REQUEST, TRANSACTION_CATEGORY_SIGNATURE_REQUEST,
UNAPPROVED_STATUS, UNAPPROVED_STATUS,
TRANSACTION_CATEGORY_APPROVAL,
FAILED_STATUS, FAILED_STATUS,
DROPPED_STATUS, DROPPED_STATUS,
REJECTED_STATUS, REJECTED_STATUS,
@ -55,6 +56,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST
const isApproval = category === TRANSACTION_CATEGORY_APPROVAL
const isUnapproved = status === UNAPPROVED_STATUS const isUnapproved = status === UNAPPROVED_STATUS
const className = classnames('transaction-list-item', { const className = classnames('transaction-list-item', {
@ -137,7 +139,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
</span> </span>
</h3> </h3>
)} )}
rightContent={!isSignatureReq && ( rightContent={!isSignatureReq && !isApproval && (
<> <>
<h2 className="transaction-list-item__primary-currency">{primaryCurrency}</h2> <h2 className="transaction-list-item__primary-currency">{primaryCurrency}</h2>
<h3 className="transaction-list-item__secondary-currency">{secondaryCurrency}</h3> <h3 className="transaction-list-item__secondary-currency">{secondaryCurrency}</h3>

@ -1,13 +1,13 @@
.alert-circle-icon { .alert-circle-icon {
&--danger { &--danger {
border-color: $danger-red; border-color: $accent-red;
color: $danger-red; color: $accent-red;
background: $danger-light-red; background: $Red-000;
} }
&--warning { &--warning {
border-color: $warning-yellow; border-color: $accent-yellow;
color: $warning-yellow; color: $accent-yellow;
background: $warning-light-yellow; background: $Yellow-000;
} }
} }

@ -8,7 +8,6 @@ $hover-confirm: #0372c3;
$hover-red: #feb6bf; $hover-red: #feb6bf;
$hover-red-primary: #c72837; $hover-red-primary: #c72837;
$hover-orange: #ffd3b5; $hover-orange: #ffd3b5;
$danger-light-red: #ea7e77;
$warning-light-orange: #f8b588; $warning-light-orange: #f8b588;
%button { %button {
@ -216,7 +215,7 @@ $warning-light-orange: #f8b588;
*/ */
.btn-raised { .btn-raised {
color: $curious-blue; color: $primary-blue;
background-color: $white; background-color: $white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
padding: 6px; padding: 6px;
@ -297,7 +296,7 @@ button.primary {
&--disabled, &--disabled,
&[disabled] { &[disabled] {
border-color: $Red-100; border-color: $Red-100;
color: $danger-light-red; color: $Red-300;
} }
&:active { &:active {
@ -337,7 +336,7 @@ button.primary {
&--disabled, &--disabled,
&[disabled] { &[disabled] {
background-color: $danger-light-red; background-color: $Red-300;
} }
&:active { &:active {

@ -12,8 +12,8 @@
&__checked, &__checked,
&__indeterminate { &__indeterminate {
color: $curious-blue; color: $primary-blue;
border-color: $curious-blue; border-color: $primary-blue;
} }
&:disabled { &:disabled {

@ -39,7 +39,7 @@
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
color: $curious-blue; color: $primary-blue;
&--copy { &--copy {
border-right: 1px solid $alto; border-right: 1px solid $alto;

@ -2,18 +2,18 @@
margin: 0 4px; margin: 0 4px;
&--success { &--success {
fill: $success-green; fill: $accent-green;
} }
&--info { &--info {
fill: $info-blue; fill: $primary-blue;
} }
&--warning { &--warning {
fill: $warning-yellow; fill: $accent-yellow;
} }
&--danger { &--danger {
fill: $danger-red; fill: $accent-red;
} }
} }

@ -17,7 +17,7 @@
border-style: solid; border-style: solid;
border-radius: 50%; border-radius: 50%;
border-width: 2px; border-width: 2px;
border-color: $curious-blue; border-color: $primary-blue;
} }
&__eth-logo { &__eth-logo {

@ -6,6 +6,6 @@
&--active { &--active {
color: $black; color: $black;
border-bottom: 2px solid $curious-blue; border-bottom: 2px solid $primary-blue;
} }
} }

@ -27,7 +27,7 @@ describe('UnitInput Component', function () {
assert.equal(wrapper.find('.unit-input__suffix').text(), 'ETH') assert.equal(wrapper.find('.unit-input__suffix').text(), 'ETH')
}) })
it('should render properly with a child omponent', function () { it('should render properly with a child component', function () {
const wrapper = shallow( const wrapper = shallow(
<UnitInput> <UnitInput>
<div className="testing"> <div className="testing">

@ -1,14 +1,25 @@
/*
MetaMask design system imports
The variables declared here should take precedence.
They are included first because they will be used to replace bad variable names in itcss
prior to it being fully removed from the system.
*/
@import './variables/index';
/* /*
ITCSS ITCSS
http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528 http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528
https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/ https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
*/
DEPRECATED: This CSS architecture is deprecated. The following imports will be removed
overtime.
*/
@import './itcss/settings/index'; @import './itcss/settings/index';
@import './itcss/tools/index'; @import './itcss/tools/index';
@import './itcss/generic/index'; @import './itcss/generic/index';
@import './itcss/objects/index'; @import './itcss/objects/index';
@import './itcss/components/index'; @import './itcss/components/index';
@import './itcss/trumps/index'; @import './itcss/trumps/index';
// Other imports
@import '../../../node_modules/react-select/dist/react-select'; @import '../../../node_modules/react-select/dist/react-select';

@ -78,7 +78,7 @@
position: absolute; position: absolute;
top: 3px; top: 3px;
left: -8px; left: -8px;
color: $curious-blue; color: $primary-blue;
} }
&__account-primary-balance { &__account-primary-balance {

@ -98,7 +98,7 @@
} }
.confirm-screen-back-button { .confirm-screen-back-button {
color: $curious-blue; color: $primary-blue;
font-family: Roboto; font-family: Roboto;
font-size: 1rem; font-size: 1rem;
position: absolute; position: absolute;

@ -342,7 +342,7 @@
} }
&__link { &__link {
color: $curious-blue; color: $primary-blue;
} }
} }

@ -53,8 +53,8 @@
} }
&__selected { &__selected {
color: $curious-blue; color: $primary-blue;
border-bottom: 3px solid $curious-blue; border-bottom: 3px solid $primary-blue;
cursor: initial; cursor: initial;
pointer-events: none; pointer-events: none;
} }

@ -5,7 +5,7 @@
} }
.permission_approval_origin { .permission_approval_origin {
font-weight: 999; font-weight: 900;
margin-top: 16px; margin-top: 16px;
word-wrap: break-word; word-wrap: break-word;
} }

@ -230,7 +230,7 @@
&__help-link { &__help-link {
cursor: pointer; cursor: pointer;
text-decoration: underline; text-decoration: underline;
color: $curious-blue; color: $primary-blue;
} }
&__footer { &__footer {

@ -149,7 +149,7 @@
.currency-toggle { .currency-toggle {
&__item { &__item {
color: $curious-blue; color: $primary-blue;
cursor: pointer; cursor: pointer;
&--selected { &--selected {
@ -160,7 +160,7 @@
} }
.send-screen-gas-input-customize { .send-screen-gas-input-customize {
color: $curious-blue; color: $primary-blue;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
} }
@ -801,8 +801,8 @@
} }
input:checked + &__button { input:checked + &__button {
background-color: #037dd6; background-color: $primary-blue;
border: 2px solid #037dd6; border: 2px solid $primary-blue;
color: #fff; color: #fff;
} }
} }
@ -830,7 +830,7 @@
justify-content: center; justify-content: center;
height: 24px; height: 24px;
width: 24px; width: 24px;
border: 1px solid $curious-blue; border: 1px solid $primary-blue;
border-radius: 4px; border-radius: 4px;
background-color: $white; background-color: $white;
position: absolute; position: absolute;
@ -841,7 +841,7 @@
} }
&__sliders-icon { &__sliders-icon {
color: $curious-blue; color: $primary-blue;
} }
&__memo-text-area { &__memo-text-area {
@ -1077,7 +1077,7 @@
justify-content: center; justify-content: center;
height: 24px; height: 24px;
width: 24px; width: 24px;
border: 1px solid $curious-blue; border: 1px solid $primary-blue;
border-radius: 4px; border-radius: 4px;
background-color: $white; background-color: $white;
position: absolute; position: absolute;
@ -1105,5 +1105,5 @@
} }
.sliders-icon { .sliders-icon {
color: $curious-blue; color: $primary-blue;
} }

@ -13,23 +13,12 @@ $gray: #808080;
Colors Colors
http://chir.ag/projects/name-that-color http://chir.ag/projects/name-that-color
*/ */
$white-linen: #faf6f0; // formerly 'faint orange (textfield shades)'
$rajah: #f5c26d; // formerly 'light orange (button shades)'
$buttercup: #f5a623; // formerly 'dark orange (text)'
$tundora: #4a4a4a; // formerly 'borders/font/any gray'
$flamingo: #f56821;
$valencia: #d73a49;
$gallery: #efefef; $gallery: #efefef;
$alabaster: #f7f7f7;
$shark: #22232c;
$wild-sand: #f6f6f6; $wild-sand: #f6f6f6;
$white: #fff;
$dusty-gray: #9b9b9b; $dusty-gray: #9b9b9b;
$alto: #dedede; $alto: #dedede;
$alabaster: #fafafa; $alabaster: #fafafa;
$silver-chalice: #aeaeae; $silver-chalice: #aeaeae;
$curious-blue: #037dd6;
$concrete: #f3f3f3;
$tundora: #4d4d4d; $tundora: #4d4d4d;
$nile-blue: #1b344d; $nile-blue: #1b344d;
$scorpion: #5d5d5d; $scorpion: #5d5d5d;
@ -42,19 +31,12 @@ $purple: #690496;
$tulip-tree: #ebb33f; $tulip-tree: #ebb33f;
$malibu-blue: #7ac9fd; $malibu-blue: #7ac9fd;
$athens-grey: #e9edf0; $athens-grey: #e9edf0;
$jaffa: #f28930;
$geyser: #d2d8dd; $geyser: #d2d8dd;
$manatee: #93949d; $manatee: #93949d;
$spindle: #c7ddec; $spindle: #c7ddec;
$mid-gray: #5b5d67; $mid-gray: #5b5d67;
$cape-cod: #38393a; $cape-cod: #38393a;
$onahau: #d1edff;
$java: #29b6af;
$wild-strawberry: #ff4a8d;
$cornflower-blue: #7057ff;
$saffron: #f6c343;
$dodger-blue: #3099f2; $dodger-blue: #3099f2;
$zumthor: #edf7ff;
$ecstasy: #f7861c; $ecstasy: #f7861c;
$linen: #fdf4f4; $linen: #fdf4f4;
$oslo-gray: #8c8e94; $oslo-gray: #8c8e94;
@ -63,19 +45,6 @@ $blizzard-blue: #bfdef3;
$mischka: #dddee9; $mischka: #dddee9;
$web-orange: #f2a202; $web-orange: #f2a202;
$mercury: #e5e5e5; $mercury: #e5e5e5;
$lochmara: #037dd6;
/*
notification and error message colors
*/
$success-green: #28a745;
$success-light-green: #e8f9f1;
$danger-red: #d73a49;
$danger-light-red: #f8eae8;
$info-blue: #037dd6;
$info-light-blue: #e8f4fd;
$warning-yellow: #ffd33d;
$warning-light-yellow: #fefae8;
/* /*
Z-Indicies Z-Indicies
@ -139,44 +108,6 @@ $break-large: 576px;
$primary-font-type: Roboto; $primary-font-type: Roboto;
$Blue-000: #eaf6ff;
$Blue-100: #a7d9fe;
$Blue-200: #75c4fd;
$Blue-300: #43aefc;
$Blue-400: #1098fc;
$Blue-500: #037dd6;
$Blue-600: #0260a4;
$Blue-700: #024272;
$Blue-800: #01253f;
$Blue-900: #00080d;
$Grey-000: #f2f3f4;
$Grey-100: #d6d9dc;
$Grey-200: #bbc0c5;
$Grey-300: #9fa6ae;
$Grey-400: #848c96;
$Grey-200: #bbc0c5;
$Grey-500: #6a737d;
$Grey-600: #535a61;
$Grey-800: #24272a;
$Red-000: #fcf2f3;
$Red-100: #f7d5d8;
$Red-200: #f1b9be;
$Red-300: #e88f97;
$Red-400: #e06470;
$Red-500: #d73a49;
$Red-600: #b92534;
$Red-700: #8e1d28;
$Red-800: #64141c;
$Red-900: #3a0c10;
$Orange-000: #fef5ef;
$Orange-300: #faa66c;
$Orange-600: #c65507;
$Orange-500: #f66a0a;
$Black-100: #24292e;
// Font Sizes // Font Sizes
%h3 { %h3 {

@ -0,0 +1,76 @@
// These are the colors of the MetaMask design system
// Only design system colors should be added, no superfluous variables
// See https://bit.ly/32mnoja (link to figma design system)
$Blue-000: #eaf6ff;
$Blue-100: #a7d9fe;
$Blue-200: #75c4fd;
$Blue-300: #43aefc;
$Blue-400: #1098fc;
$Blue-500: #037dd6;
$Blue-600: #0260a4;
$Blue-700: #024272;
$Blue-800: #01253f;
$Blue-900: #00080d;
$Grey-000: #f2f3f4;
$Grey-100: #d6d9dc;
$Grey-200: #bbc0c5;
$Grey-300: #9fa6ae;
$Grey-400: #848c96;
$Grey-500: #6a737d;
$Grey-600: #535a61;
$Grey-700: #3b4046;
$Grey-800: #24272a;
$Grey-900: #141618;
$Green-000: #f3fcf5;
$Green-100: #d6ffdf;
$Green-200: #afecbd;
$Green-300: #86e29b;
$Green-400: #5dd879;
$Green-500: #28a745;
$Green-600: #1e7e34;
$Green-700: #145523;
$Green-800: #0a2c12;
$Green-900: #041007;
$Red-000: #fcf2f3;
$Red-100: #f7d5d8;
$Red-200: #f1b9be;
$Red-300: #e88f97;
$Red-400: #e06470;
$Red-500: #d73a49;
$Red-600: #b92534;
$Red-700: #8e1d28;
$Red-800: #64141c;
$Red-900: #3a0c10;
$Orange-000: #fef5ef;
$Orange-100: #fde2cf;
$Orange-200: #fbc49d;
$Orange-300: #faa66c;
$Orange-400: #f8883b;
$Orange-500: #f66a0a;
$Orange-600: #c65507;
$Orange-700: #954005;
$Orange-800: #632b04;
$Orange-900: #321602;
$Yellow-000: #fefae8; // Temporary placeholder
$Yellow-100: #fefcde;
$Yellow-500: #ffd33d;
$Black-100: #24292e;
$primary-blue: $Blue-500;
$primary-orange: $Orange-500;
$accent-yellow: $Yellow-500;
$accent-green: $Green-500;
$accent-red: $Red-500;
$accent-purple: #6f42c1;
$accent-pink: #ff45d8;
$neutral-white: #fff;
$neutral-black: $Black-100;
$neutral-grey: $Grey-500;

@ -0,0 +1 @@
@import './colors.scss';

@ -1 +0,0 @@
export { default } from './with-method-data.component'

@ -1,65 +0,0 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { getMethodDataAsync, getFourBytePrefix } from '../../utils/transactions.util'
export default function withMethodData (WrappedComponent) {
return class MethodDataWrappedComponent extends PureComponent {
static propTypes = {
transaction: PropTypes.object,
knownMethodData: PropTypes.object,
addKnownMethodData: PropTypes.func,
}
static defaultProps = {
transaction: {},
knownMethodData: {},
}
state = {
methodData: {},
done: false,
error: null,
}
componentDidMount () {
this.fetchMethodData()
}
async fetchMethodData () {
const { transaction, knownMethodData, addKnownMethodData } = this.props
const { txParams: { data = '' } = {} } = transaction
if (data) {
try {
let methodData
const fourBytePrefix = getFourBytePrefix(data)
if (fourBytePrefix in knownMethodData) {
methodData = knownMethodData[fourBytePrefix]
} else {
methodData = await getMethodDataAsync(data)
if (!Object.entries(methodData).length === 0) {
addKnownMethodData(fourBytePrefix, methodData)
}
}
this.setState({ methodData, done: true })
} catch (error) {
this.setState({ done: true, error })
}
} else {
this.setState({ done: true })
}
}
render () {
const { methodData, done, error } = this.state
return (
<WrappedComponent
{ ...this.props }
methodData={{ data: methodData, done, error }}
/>
)
}
}
}

@ -28,9 +28,9 @@ const valueTable = {
tether: '0.000000000001', tether: '0.000000000001',
} }
const bnTable = {} const bnTable = {}
for (const currency in valueTable) { Object.keys(valueTable).forEach((currency) => {
bnTable[currency] = new ethUtil.BN(valueTable[currency], 10) bnTable[currency] = new ethUtil.BN(valueTable[currency], 10)
} })
export function isEthNetwork (netId) { export function isEthNetwork (netId) {
if (!netId || netId === '1' || netId === '3' || netId === '4' || netId === '42' || netId === '5777') { if (!netId || netId === '1' || netId === '3' || netId === '4' || netId === '42' || netId === '5777') {

@ -230,11 +230,11 @@ describe('util', function () {
} }
const oneEthBn = new ethUtil.BN(ethInWei, 10) const oneEthBn = new ethUtil.BN(ethInWei, 10)
for (const currency in valueTable) { Object.keys(valueTable).forEach((currency) => {
const value = new ethUtil.BN(valueTable[currency], 10) const value = new ethUtil.BN(valueTable[currency], 10)
const output = util.normalizeToWei(value, currency) const output = util.normalizeToWei(value, currency)
assert.equal(output.toString(10), valueTable.wei, `value of ${output.toString(10)} ${currency} should convert to ${oneEthBn}`) assert.equal(output.toString(10), valueTable.wei, `value of ${output.toString(10)} ${currency} should convert to ${oneEthBn}`)
} })
}) })
}) })

@ -21,7 +21,7 @@ describe('useCancelTransaction', function () {
dispatch.resetHistory() dispatch.resetHistory()
}) })
describe('when account has insufficent balance to cover gas', function () { describe('when account has insufficient balance to cover gas', function () {
before(function () { before(function () {
useSelector = sinon.stub(reactRedux, 'useSelector') useSelector = sinon.stub(reactRedux, 'useSelector')
useSelector.callsFake((selector) => { useSelector.callsFake((selector) => {

@ -106,7 +106,7 @@ export function useTransactionDisplayData (transactionGroup) {
subtitleContainsOrigin = true subtitleContainsOrigin = true
} else if (transactionCategory === TOKEN_METHOD_APPROVE) { } else if (transactionCategory === TOKEN_METHOD_APPROVE) {
category = TRANSACTION_CATEGORY_APPROVAL category = TRANSACTION_CATEGORY_APPROVAL
title = t('approve') title = t('approveSpendLimit', [token?.symbol || t('token')])
subtitle = origin subtitle = origin
subtitleContainsOrigin = true subtitleContainsOrigin = true
} else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) { } else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) {

@ -36,7 +36,7 @@
&__edit { &__edit {
flex: 1 1 auto; flex: 1 1 auto;
text-align: right; text-align: right;
color: $curious-blue; color: $primary-blue;
padding-right: 4px; padding-right: 4px;
cursor: pointer; cursor: pointer;
} }

@ -141,7 +141,7 @@
div { div {
width: 22px; width: 22px;
height: 2px; height: 2px;
background: #037dd6; background: $primary-blue;
position: absolute; position: absolute;
} }
@ -157,7 +157,7 @@
&__circle { &__circle {
width: 14px; width: 14px;
height: 14px; height: 14px;
border: 2px solid #037dd6; border: 2px solid $primary-blue;
border-radius: 50%; border-radius: 50%;
background: white; background: white;
position: absolute; position: absolute;
@ -236,7 +236,7 @@
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
font-weight: 500; font-weight: 500;
color: #037dd6; color: $primary-blue;
} }
&__medium-text, &__medium-text,
@ -262,7 +262,7 @@
} }
&__small-blue-text { &__small-blue-text {
color: #037dd6; color: $primary-blue;
} }
&__info-row { &__info-row {

@ -2,7 +2,7 @@
&__footer { &__footer {
a, a,
a:hover { a:hover {
color: #037dd6; color: $primary-blue;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
} }

@ -28,7 +28,7 @@
a:hover { a:hover {
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
color: #037dd6; color: $primary-blue;
cursor: pointer; cursor: pointer;
} }
} }

@ -159,6 +159,6 @@
} }
&__link-text { &__link-text {
color: $curious-blue; color: $primary-blue;
} }
} }

@ -18,7 +18,7 @@ const returnToOnboardingInitiatorTab = async (onboardingInitiator) => {
if (!tab) { if (!tab) {
// this case can happen if the tab was closed since being checked with `extension.tabs.get` // this case can happen if the tab was closed since being checked with `extension.tabs.get`
log.warn(`Setting current tab to onboarding initator has failed; falling back to redirect`) log.warn(`Setting current tab to onboarding initiator has failed; falling back to redirect`)
window.location.assign(onboardingInitiator.location) window.location.assign(onboardingInitiator.location)
} else { } else {
window.close() window.close()

@ -54,7 +54,7 @@
} }
&__export-text { &__export-text {
color: $curious-blue; color: $primary-blue;
cursor: pointer; cursor: pointer;
font-weight: 500; font-weight: 500;
} }

@ -34,7 +34,7 @@
} }
&__text-blue { &__text-blue {
color: $curious-blue; color: $primary-blue;
cursor: pointer; cursor: pointer;
} }
@ -143,7 +143,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-end; align-items: flex-end;
color: #037dd6; color: $primary-blue;
} }
} }

@ -128,7 +128,7 @@ describe('SendFooter Component', function () {
}, },
} }
Object.entries(config).map(([description, obj]) => { Object.entries(config).forEach(([description, obj]) => {
it(description, function () { it(description, function () {
wrapper.setProps(obj) wrapper.setProps(obj)
assert.equal(wrapper.instance().formShouldBeDisabled(), obj.expectedResult) assert.equal(wrapper.instance().formShouldBeDisabled(), obj.expectedResult)

@ -56,7 +56,7 @@ describe('SendHeader Component', function () {
}) })
describe('render', function () { describe('render', function () {
it('should render a PageContainerHeader compenent', function () { it('should render a PageContainerHeader component', function () {
assert.equal(wrapper.find(PageContainerHeader).length, 1) assert.equal(wrapper.find(PageContainerHeader).length, 1)
}) })

@ -103,7 +103,7 @@ describe('send utils', function () {
expectedResult: false, expectedResult: false,
}, },
} }
Object.entries(config).map(([description, obj]) => { Object.entries(config).forEach(([description, obj]) => {
it(description, function () { it(description, function () {
assert.equal(doesAmountErrorRequireUpdate(obj), obj.expectedResult) assert.equal(doesAmountErrorRequireUpdate(obj), obj.expectedResult)
}) })
@ -166,7 +166,7 @@ describe('send utils', function () {
expectedResult: { amount: INSUFFICIENT_TOKENS_ERROR }, expectedResult: { amount: INSUFFICIENT_TOKENS_ERROR },
}, },
} }
Object.entries(config).map(([description, obj]) => { Object.entries(config).forEach(([description, obj]) => {
it(description, function () { it(description, function () {
assert.deepEqual(getAmountErrorObject(obj), obj.expectedResult) assert.deepEqual(getAmountErrorObject(obj), obj.expectedResult)
}) })
@ -190,7 +190,7 @@ describe('send utils', function () {
expectedResult: { gasFee: null }, expectedResult: { gasFee: null },
}, },
} }
Object.entries(config).map(([description, obj]) => { Object.entries(config).forEach(([description, obj]) => {
it(description, function () { it(description, function () {
assert.deepEqual(getGasFeeErrorObject(obj), obj.expectedResult) assert.deepEqual(getGasFeeErrorObject(obj), obj.expectedResult)
}) })
@ -198,7 +198,7 @@ describe('send utils', function () {
}) })
describe('calcTokenBalance()', function () { describe('calcTokenBalance()', function () {
it('should return the calculated token blance', function () { it('should return the calculated token balance', function () {
assert.equal(calcTokenBalance({ assert.equal(calcTokenBalance({
sendToken: { sendToken: {
address: '0x0', address: '0x0',

@ -1,5 +1,6 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Redirect } from 'react-router-dom'
import Identicon from '../../../../components/ui/identicon' import Identicon from '../../../../components/ui/identicon'
import Button from '../../../../components/ui/button/button.component' import Button from '../../../../components/ui/button/button.component'
import TextField from '../../../../components/ui/text-field' import TextField from '../../../../components/ui/text-field'
@ -23,11 +24,11 @@ export default class EditContact extends PureComponent {
viewRoute: PropTypes.string, viewRoute: PropTypes.string,
listRoute: PropTypes.string, listRoute: PropTypes.string,
setAccountLabel: PropTypes.func, setAccountLabel: PropTypes.func,
showingMyAccounts: PropTypes.bool.isRequired,
} }
static defaultProps = { static defaultProps = {
name: '', name: '',
address: '',
memo: '', memo: '',
} }
@ -40,22 +41,43 @@ export default class EditContact extends PureComponent {
render () { render () {
const { t } = this.context const { t } = this.context
const { history, name, addToAddressBook, removeFromAddressBook, address, chainId, memo, viewRoute, listRoute, setAccountLabel } = this.props const {
address,
addToAddressBook,
chainId,
history,
listRoute,
memo,
name,
removeFromAddressBook,
setAccountLabel,
showingMyAccounts,
viewRoute,
} = this.props
if (!address) {
return <Redirect to={{ pathname: listRoute }} />
}
return ( return (
<div className="settings-page__content-row address-book__edit-contact"> <div className="settings-page__content-row address-book__edit-contact">
<div className="settings-page__header address-book__header--edit"> <div className="settings-page__header address-book__header--edit">
<Identicon address={address} diameter={60} /> <Identicon address={address} diameter={60} />
{
showingMyAccounts
? null
: (
<Button <Button
type="link" type="link"
className="settings-page__address-book-button" className="settings-page__address-book-button"
onClick={async () => { onClick={async () => {
await removeFromAddressBook(chainId, address) await removeFromAddressBook(chainId, address)
history.push(listRoute)
}} }}
> >
{t('deleteAccount')} {t('deleteAccount')}
</Button> </Button>
)
}
</div> </div>
<div className="address-book__edit-contact__content"> <div className="address-book__edit-contact__content">
<div className="address-book__view-contact__group"> <div className="address-book__view-contact__group">
@ -117,7 +139,9 @@ export default class EditContact extends PureComponent {
if (isValidAddress(this.state.newAddress)) { if (isValidAddress(this.state.newAddress)) {
await removeFromAddressBook(chainId, address) await removeFromAddressBook(chainId, address)
await addToAddressBook(this.state.newAddress, this.state.newName || name, this.state.newMemo || memo) await addToAddressBook(this.state.newAddress, this.state.newName || name, this.state.newMemo || memo)
if (showingMyAccounts) {
setAccountLabel(this.state.newAddress, this.state.newName || name) setAccountLabel(this.state.newAddress, this.state.newName || name)
}
history.push(listRoute) history.push(listRoute)
} else { } else {
this.setState({ error: this.context.t('invalidAddress') }) this.setState({ error: this.context.t('invalidAddress') })
@ -125,7 +149,9 @@ export default class EditContact extends PureComponent {
} else { } else {
// update name // update name
await addToAddressBook(address, this.state.newName || name, this.state.newMemo || memo) await addToAddressBook(address, this.state.newName || name, this.state.newMemo || memo)
if (showingMyAccounts) {
setAccountLabel(address, this.state.newName || name) setAccountLabel(address, this.state.newName || name)
}
history.push(listRoute) history.push(listRoute)
} }
}} }}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save