Merge remote-tracking branch 'origin/develop' into sync-master

* origin/develop:
  Fix locale lint errors (#10410)
  Update zh_CN translation (#9388)
  cancel unapproved confirmations on network change (#10357)
  Remove unused `confirmTransaction` state (#10396)
  Update `eth-sig-util` and `ethashjs` lockfile versions (#10383)
  Fix `transferFrom` localized message (#10395)
  Storybook: Signature Request (#10400)
  Use string literals for transaction category localized messages (#10391)
  Fix `start:dev` script (#10399)
  storybook/i18n - add i18n party button (#10382)
  Update `ja` localized messages (#10265)
feature/default_network_editable
Mark Stacey 4 years ago
commit 3f394c48f0
  1. 37
      .storybook/i18n-party-addon/register.js
  2. 1
      .storybook/main.js
  3. 52
      .storybook/preview.js
  4. 218
      .storybook/test-data.js
  5. 1836
      app/_locales/ja/messages.json
  6. 1259
      app/_locales/zh_CN/messages.json
  7. 39
      app/scripts/background.js
  8. 5
      app/scripts/controllers/app-state.js
  9. 3
      app/scripts/controllers/incoming-transactions.js
  10. 2
      app/scripts/controllers/network/index.js
  11. 12
      app/scripts/controllers/network/network.js
  12. 3
      app/scripts/controllers/swaps.js
  13. 5
      app/scripts/controllers/transactions/index.js
  14. 5
      app/scripts/controllers/transactions/tx-state-manager.js
  15. 11
      app/scripts/lib/decrypt-message-manager.js
  16. 11
      app/scripts/lib/encryption-public-key-manager.js
  17. 11
      app/scripts/lib/message-manager.js
  18. 11
      app/scripts/lib/personal-message-manager.js
  19. 11
      app/scripts/lib/typed-message-manager.js
  20. 32
      app/scripts/metamask-controller.js
  21. 16
      package.json
  22. 3
      test/unit/app/controllers/incoming-transactions-test.js
  23. 5
      test/unit/app/controllers/metametrics-test.js
  24. 6
      test/unit/app/controllers/swaps-test.js
  25. 6
      test/unit/app/controllers/transactions/tx-controller-test.js
  26. 5
      ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
  27. 5
      ui/app/components/app/signature-request/signature-request-header/index.scss
  28. 37
      ui/app/components/app/signature-request/signature-request.stories.js
  29. 127
      ui/app/ducks/confirm-transaction/confirm-transaction.duck.js
  30. 262
      ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js
  31. 42
      ui/app/helpers/utils/transactions.util.js
  32. 11
      ui/app/hooks/useTransactionDisplayData.js
  33. 3
      ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js
  34. 419
      yarn.lock

@ -0,0 +1,37 @@
// import { useGlobals } from '@storybook/api';
const { useGlobals } = require('@storybook/api')
const React = require("react")
const { addons, types } = require("@storybook/addons")
const { Icons, IconButton } = require('@storybook/components')
const localeList = require('../../app/_locales/index.json')
const { useEffect } = React
addons.register("i18n-party", () => {
addons.add("i18n-party", {
title: "rotates through every i18n locale",
//👇 Sets the type of UI element in Storybook
type: types.TOOL,
match: () => true,
render: (...args) => {
// https://github.com/storybookjs/storybook/blob/6490a0d646dbaa293b76bbde477daca615efe789/addons/toolbars/src/components/MenuToolbar.tsx#L2
const [globals, updateGlobals] = useGlobals()
useEffect(() => {
if (!globals.localeParty) return
const interval = setInterval((...args) => {
const currentIndex = localeList.findIndex(({ code }) => code === globals.locale)
const nextIndex = (currentIndex + 1) % localeList.length
const nextLocale = localeList[nextIndex].code
updateGlobals({ locale: nextLocale })
}, 2000)
return () => clearInterval(interval)
})
return (
<IconButton onClick={() => updateGlobals({ localeParty: !globals.localeParty })}>
<Icons icon={globals.localeParty ? 'star' : 'starhollow'}/>
</IconButton>
)
},
})
})

@ -9,6 +9,7 @@ module.exports = {
'@storybook/addon-actions',
'@storybook/addon-backgrounds',
'@storybook/addon-toolbars',
'./i18n-party-addon/register.js',
],
webpackFinal: async (config) => {
config.module.strictExportPresence = true

@ -1,22 +1,24 @@
import React from 'react'
import { addDecorator, addParameters } from '@storybook/react'
import { withKnobs } from '@storybook/addon-knobs'
import { Provider } from 'react-redux'
import configureStore from '../ui/app/store/store'
import '../ui/app/css/index.scss'
import localeList from '../app/_locales/index.json'
import * as allLocales from './locales'
import { I18nProvider, LegacyI18nProvider } from './i18n'
import React, { useEffect } from 'react';
import { addDecorator, addParameters } from '@storybook/react';
import { useGlobals } from '@storybook/api';
import { withKnobs } from '@storybook/addon-knobs';
import { Provider } from 'react-redux';
import configureStore from '../ui/app/store/store';
import '../ui/app/css/index.scss';
import localeList from '../app/_locales/index.json';
import * as allLocales from './locales';
import { I18nProvider, LegacyI18nProvider } from './i18n';
import testData from './test-data.js'
addParameters({
backgrounds: {
default: 'light',
values: [
{ name: 'light', value: '#FFFFFF'},
{ name: 'light', value: '#FFFFFF' },
{ name: 'dark', value: '#333333' },
],
}
})
},
});
export const globalTypes = {
locale: {
@ -26,8 +28,8 @@ export const globalTypes = {
toolbar: {
icon: 'globe',
items: localeList.map(({ code, name }) => {
return { value: code, right: code, title: name }
})
return { value: code, right: code, title: name };
}),
},
},
};
@ -37,15 +39,13 @@ const styles = {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}
};
const store = configureStore({
metamask: { metamask: { } },
})
const store = configureStore(testData)
const metamaskDecorator = (story, context) => {
const currentLocale = context.globals.locale
const current = allLocales[currentLocale]
const currentLocale = context.globals.locale;
const current = allLocales[currentLocale];
return (
<Provider store={store}>
<I18nProvider
@ -54,14 +54,12 @@ const metamaskDecorator = (story, context) => {
en={allLocales.en}
>
<LegacyI18nProvider>
<div style={styles}>
{ story() }
</div>
<div style={styles}>{story()}</div>
</LegacyI18nProvider>
</I18nProvider>
</Provider>
)
}
);
};
addDecorator(withKnobs)
addDecorator(metamaskDecorator)
addDecorator(withKnobs);
addDecorator(metamaskDecorator);

@ -0,0 +1,218 @@
import { TRANSACTION_STATUSES } from '../shared/constants/transaction';
const state = {
metamask: {
isInitialized: true,
isUnlocked: true,
featureFlags: { sendHexData: true },
rpcUrl: 'https://rawtestrpc.metamask.io/',
identities: {
'0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': {
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
name: 'Send Account 1',
},
'0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': {
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
name: 'Send Account 2',
},
'0x2f8d4a878cfa04a6e60d46362f5644deab66572d': {
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
name: 'Send Account 3',
},
'0xd85a4b6a394794842887b8284293d69163007bbb': {
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
name: 'Send Account 4',
},
},
cachedBalances: {},
currentBlockGasLimit: '0x4c1878',
currentCurrency: 'USD',
conversionRate: 1200.88200327,
conversionDate: 1489013762,
nativeCurrency: 'ETH',
frequentRpcList: [],
network: '3',
provider: {
type: 'ropsten',
chainId: '0x3',
},
accounts: {
'0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': {
code: '0x',
balance: '0x47c9d71831c76efe',
nonce: '0x1b',
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
},
'0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': {
code: '0x',
balance: '0x37452b1315889f80',
nonce: '0xa',
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
},
'0x2f8d4a878cfa04a6e60d46362f5644deab66572d': {
code: '0x',
balance: '0x30c9d71831c76efe',
nonce: '0x1c',
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
},
'0xd85a4b6a394794842887b8284293d69163007bbb': {
code: '0x',
balance: '0x0',
nonce: '0x0',
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
},
},
addressBook: {
'0x3': {
'0x06195827297c7a80a443b6894d3bdb8824b43896': {
address: '0x06195827297c7a80a443b6894d3bdb8824b43896',
name: 'Address Book Account 1',
chainId: '0x3',
},
},
},
tokens: [
{
address: '0x1a195821297c7a80a433b6894d3bdb8824b43896',
decimals: 18,
symbol: 'ABC',
},
{
address: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
decimals: 4,
symbol: 'DEF',
},
{
address: '0xa42084c8d1d9a2198631988579bb36b48433a72b',
decimals: 18,
symbol: 'GHI',
},
],
transactions: {},
currentNetworkTxList: [
{
id: 'mockTokenTx1',
txParams: {
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
from: '0xd85a4b6a394794842887b8284293d69163007bbb',
},
time: 1700000000000,
},
{
id: 'mockTokenTx2',
txParams: {
to: '0xafaketokenaddress',
from: '0xd85a4b6a394794842887b8284293d69163007bbb',
},
time: 1600000000000,
},
{
id: 'mockTokenTx3',
txParams: {
to: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
from: '0xd85a4b6a394794842887b8284293d69163007bbb',
},
time: 1500000000000,
},
{
id: 'mockEthTx1',
txParams: {
to: '0xd85a4b6a394794842887b8284293d69163007bbb',
from: '0xd85a4b6a394794842887b8284293d69163007bbb',
},
time: 1400000000000,
},
],
unapprovedMsgs: {
'0xabc': { id: 'unapprovedMessage1', time: 1650000000000 },
'0xdef': { id: 'unapprovedMessage2', time: 1550000000000 },
'0xghi': { id: 'unapprovedMessage3', time: 1450000000000 },
},
unapprovedMsgCount: 0,
unapprovedPersonalMsgs: {},
unapprovedPersonalMsgCount: 0,
unapprovedDecryptMsgs: {},
unapprovedDecryptMsgCount: 0,
unapprovedEncryptionPublicKeyMsgs: {},
unapprovedEncryptionPublicKeyMsgCount: 0,
keyringTypes: ['Simple Key Pair', 'HD Key Tree'],
keyrings: [
{
type: 'HD Key Tree',
accounts: [
'fdea65c8e26263f6d9a1b5de9555d2931a33b825',
'c5b8dbac4c1d3f152cdeb400e2313f309c410acb',
'2f8d4a878cfa04a6e60d46362f5644deab66572d',
],
},
{
type: 'Simple Key Pair',
accounts: ['0xd85a4b6a394794842887b8284293d69163007bbb'],
},
],
selectedAddress: '0xd85a4b6a394794842887b8284293d69163007bbb',
send: {
gasLimit: '0xFFFF',
gasPrice: '0xaa',
gasTotal: '0xb451dc41b578',
tokenBalance: 3434,
from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
to: '0x987fedabc',
amount: '0x080',
memo: '',
errors: {
someError: null,
},
maxModeOn: false,
editingTransactionId: 97531,
},
unapprovedTxs: {
4768706228115573: {
id: 4768706228115573,
time: 1487363153561,
status: TRANSACTION_STATUSES.UNAPPROVED,
gasMultiplier: 1,
metamaskNetworkId: '3',
txParams: {
from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761',
value: '0xde0b6b3a7640000',
metamaskId: 4768706228115573,
metamaskNetworkId: '3',
gas: '0x5209',
},
txFee: '17e0186e60800',
txValue: 'de0b6b3a7640000',
maxCost: 'de234b52e4a0800',
gasPrice: '4a817c800',
},
},
currentLocale: 'en',
},
appState: {
menuOpen: false,
currentView: {
name: 'accountDetail',
detailView: null,
context: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
},
accountDetail: {
subview: 'transactions',
},
modal: {
modalState: {},
previousModalState: {},
},
isLoading: false,
warning: null,
scrollToBottom: false,
forgottenPassword: null,
},
send: {
fromDropdownOpen: false,
toDropdownOpen: false,
errors: { someError: null },
},
};
export default state;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -32,7 +32,9 @@ import LocalStore from './lib/local-store';
import ReadOnlyNetworkStore from './lib/network-store';
import createStreamSink from './lib/createStreamSink';
import NotificationManager from './lib/notification-manager';
import MetamaskController from './metamask-controller';
import MetamaskController, {
METAMASK_CONTROLLER_EVENTS,
} from './metamask-controller';
import rawFirstTimeState from './first-time-state';
import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code';
import getObjStructure from './lib/getObjStructure';
@ -396,14 +398,35 @@ function setupController(initState, initLangCode) {
//
updateBadge();
controller.txController.on('update:badge', updateBadge);
controller.messageManager.on('updateBadge', updateBadge);
controller.personalMessageManager.on('updateBadge', updateBadge);
controller.decryptMessageManager.on('updateBadge', updateBadge);
controller.encryptionPublicKeyManager.on('updateBadge', updateBadge);
controller.typedMessageManager.on('updateBadge', updateBadge);
controller.txController.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.messageManager.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.personalMessageManager.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.decryptMessageManager.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.encryptionPublicKeyManager.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.typedMessageManager.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.approvalController.subscribe(updateBadge);
controller.appStateController.on('updateBadge', updateBadge);
controller.appStateController.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
/**
* Updates the Web Extension's "badge" number, on the little fox in the toolbar.

@ -1,5 +1,6 @@
import EventEmitter from 'events';
import { ObservableStore } from '@metamask/obs-store';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
export default class AppStateController extends EventEmitter {
/**
@ -74,7 +75,7 @@ export default class AppStateController extends EventEmitter {
*/
waitForUnlock(resolve, shouldShowUnlockRequest) {
this.waitingForUnlock.push({ resolve });
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
if (shouldShowUnlockRequest) {
this._showUnlockRequest();
}
@ -88,7 +89,7 @@ export default class AppStateController extends EventEmitter {
while (this.waitingForUnlock.length > 0) {
this.waitingForUnlock.shift().resolve();
}
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
}

@ -23,6 +23,7 @@ import {
ROPSTEN,
ROPSTEN_CHAIN_ID,
} from '../../../shared/constants/network';
import { NETWORK_EVENTS } from './network';
const fetchWithTimeout = getFetchWithTimeout(30000);
@ -111,7 +112,7 @@ export default class IncomingTransactionsController {
}),
);
this.networkController.on('networkDidChange', async () => {
this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, async () => {
const address = this.preferencesController.getSelectedAddress();
await this._update({
address,

@ -1 +1 @@
export { default } from './network';
export { default, NETWORK_EVENTS } from './network';

@ -47,6 +47,13 @@ const defaultProviderConfig = {
...defaultProviderConfigOpts,
};
export const NETWORK_EVENTS = {
// Fired after the actively selected network is changed
NETWORK_DID_CHANGE: 'networkDidChange',
// Fired when the actively selected network *will* change
NETWORK_WILL_CHANGE: 'networkWillChange',
};
export default class NetworkController extends EventEmitter {
constructor(opts = {}) {
super();
@ -73,7 +80,7 @@ export default class NetworkController extends EventEmitter {
this._providerProxy = null;
this._blockTrackerProxy = null;
this.on('networkDidChange', this.lookupNetwork);
this.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, this.lookupNetwork);
}
/**
@ -229,9 +236,10 @@ export default class NetworkController extends EventEmitter {
//
_switchNetwork(opts) {
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
this.setNetworkState('loading');
this._configureProvider(opts);
this.emit('networkDidChange', opts.type);
this.emit(NETWORK_EVENTS.NETWORK_DID_CHANGE, opts.type);
}
_configureProvider({ type, rpcUrl, chainId }) {

@ -19,6 +19,7 @@ import {
fetchSwapsFeatureLiveness as defaultFetchSwapsFeatureLiveness,
fetchSwapsQuoteRefreshTime as defaultFetchSwapsQuoteRefreshTime,
} from '../../../ui/app/pages/swaps/swaps.util';
import { NETWORK_EVENTS } from './network';
const METASWAP_ADDRESS = '0x881d40237659c251811cec9c364ef91dc08d300c';
@ -103,7 +104,7 @@ export default class SwapsController {
this.ethersProvider = new ethers.providers.Web3Provider(provider);
this._currentNetwork = networkController.store.getState().network;
networkController.on('networkDidChange', (network) => {
networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, (network) => {
if (network !== 'loading' && network !== this._currentNetwork) {
this._currentNetwork = network;
this.ethersProvider = new ethers.providers.Web3Provider(provider);

@ -23,6 +23,7 @@ import {
TRANSACTION_STATUSES,
TRANSACTION_TYPES,
} from '../../../../shared/constants/transaction';
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
import TransactionStateManager from './tx-state-manager';
import TxGasUtil from './tx-gas-utils';
import PendingTransactionTracker from './pending-tx-tracker';
@ -113,7 +114,9 @@ export default class TransactionController extends EventEmitter {
),
});
this.txStateManager.store.subscribe(() => this.emit('update:badge'));
this.txStateManager.store.subscribe(() =>
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE),
);
this._setupListeners();
// memstore is computed from a few different stores
this._updateMemstore();

@ -3,6 +3,7 @@ import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel';
import createId from '../../lib/random-id';
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
import {
generateHistoryEntry,
replayHistory,
@ -474,7 +475,7 @@ export default class TransactionStateManager extends EventEmitter {
* @param {TransactionStatuses[keyof TransactionStatuses]} status - the status to set on the txMeta
* @emits tx:status-update - passes txId and status
* @emits ${txMeta.id}:finished - if it is a finished state. Passes the txMeta
* @emits update:badge
* @emits 'updateBadge'
*/
_setTxStatus(txId, status) {
const txMeta = this.getTx(txId);
@ -497,7 +498,7 @@ export default class TransactionStateManager extends EventEmitter {
) {
this.emit(`${txMeta.id}:finished`, txMeta);
}
this.emit('update:badge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
} catch (error) {
log.error(error);
}

@ -4,6 +4,7 @@ import ethUtil from 'ethereumjs-util';
import { ethErrors } from 'eth-rpc-errors';
import log from 'loglevel';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import { addHexPrefix } from './util';
import createId from './random-id';
@ -253,6 +254,14 @@ export default class DecryptMessageManager extends EventEmitter {
this._setMsgStatus(msgId, 'errored');
}
/**
* Clears all unapproved messages from memory.
*/
clearUnapproved() {
this.messages = this.messages.filter((msg) => msg.status !== 'unapproved');
this._saveMsgList();
}
/**
* Updates the status of a DecryptMessage in this.messages via a call to this._updateMsg
*
@ -316,7 +325,7 @@ export default class DecryptMessageManager extends EventEmitter {
unapprovedDecryptMsgs,
unapprovedDecryptMsgCount,
});
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
/**

@ -3,6 +3,7 @@ import { ObservableStore } from '@metamask/obs-store';
import { ethErrors } from 'eth-rpc-errors';
import log from 'loglevel';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from './random-id';
/**
@ -242,6 +243,14 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
this._setMsgStatus(msgId, 'errored');
}
/**
* Clears all unapproved messages from memory.
*/
clearUnapproved() {
this.messages = this.messages.filter((msg) => msg.status !== 'unapproved');
this._saveMsgList();
}
/**
* Updates the status of a EncryptionPublicKey in this.messages via a call to this._updateMsg
*
@ -303,6 +312,6 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
unapprovedEncryptionPublicKeyMsgs,
unapprovedEncryptionPublicKeyMsgCount,
});
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
}

@ -3,6 +3,7 @@ import { ObservableStore } from '@metamask/obs-store';
import ethUtil from 'ethereumjs-util';
import { ethErrors } from 'eth-rpc-errors';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from './random-id';
/**
@ -220,6 +221,14 @@ export default class MessageManager extends EventEmitter {
this._setMsgStatus(msgId, 'rejected');
}
/**
* Clears all unapproved messages from memory.
*/
clearUnapproved() {
this.messages = this.messages.filter((msg) => msg.status !== 'unapproved');
this._saveMsgList();
}
/**
* Updates the status of a Message in this.messages via a call to this._updateMsg
*
@ -272,7 +281,7 @@ export default class MessageManager extends EventEmitter {
const unapprovedMsgs = this.getUnapprovedMsgs();
const unapprovedMsgCount = Object.keys(unapprovedMsgs).length;
this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount });
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
}

@ -4,6 +4,7 @@ import ethUtil from 'ethereumjs-util';
import { ethErrors } from 'eth-rpc-errors';
import log from 'loglevel';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import { addHexPrefix } from './util';
import createId from './random-id';
@ -241,6 +242,14 @@ export default class PersonalMessageManager extends EventEmitter {
this._setMsgStatus(msgId, 'rejected');
}
/**
* Clears all unapproved messages from memory.
*/
clearUnapproved() {
this.messages = this.messages.filter((msg) => msg.status !== 'unapproved');
this._saveMsgList();
}
/**
* Updates the status of a PersonalMessage in this.messages via a call to this._updateMsg
*
@ -301,7 +310,7 @@ export default class PersonalMessageManager extends EventEmitter {
unapprovedPersonalMsgs,
unapprovedPersonalMsgCount,
});
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
/**

@ -7,6 +7,7 @@ import { isValidAddress } from 'ethereumjs-util';
import log from 'loglevel';
import jsonschema from 'jsonschema';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from './random-id';
/**
@ -313,6 +314,14 @@ export default class TypedMessageManager extends EventEmitter {
this._setMsgStatus(msgId, 'errored');
}
/**
* Clears all unapproved messages from memory.
*/
clearUnapproved() {
this.messages = this.messages.filter((msg) => msg.status !== 'unapproved');
this._saveMsgList();
}
//
// PRIVATE METHODS
//
@ -377,6 +386,6 @@ export default class TypedMessageManager extends EventEmitter {
unapprovedTypedMessages,
unapprovedTypedMessagesCount,
});
this.emit('updateBadge');
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
}
}

@ -35,7 +35,7 @@ import createTabIdMiddleware from './lib/createTabIdMiddleware';
import createOnboardingMiddleware from './lib/createOnboardingMiddleware';
import { setupMultiplex } from './lib/stream-utils';
import EnsController from './controllers/ens';
import NetworkController from './controllers/network';
import NetworkController, { NETWORK_EVENTS } from './controllers/network';
import PreferencesController from './controllers/preferences';
import AppStateController from './controllers/app-state';
import CachedBalancesController from './controllers/cached-balances';
@ -61,6 +61,12 @@ import seedPhraseVerifier from './lib/seed-phrase-verifier';
import MetaMetricsController from './controllers/metametrics';
import { segment, segmentLegacy } from './lib/segment';
export const METAMASK_CONTROLLER_EVENTS = {
// Fired after state changes that impact the extension badge (unapproved msg count)
// The process of updating the badge happens in app/scripts/background.js.
UPDATE_BADGE: 'updateBadge',
};
export default class MetamaskController extends EventEmitter {
/**
* @constructor
@ -127,7 +133,7 @@ export default class MetamaskController extends EventEmitter {
preferencesStore: this.preferencesController.store,
onNetworkDidChange: this.networkController.on.bind(
this.networkController,
'networkDidChange',
NETWORK_EVENTS.NETWORK_DID_CHANGE,
),
getNetworkIdentifier: this.networkController.getNetworkIdentifier.bind(
this.networkController,
@ -214,11 +220,6 @@ export default class MetamaskController extends EventEmitter {
preferencesController: this.preferencesController,
});
// ensure accountTracker updates balances after network change
this.networkController.on('networkDidChange', () => {
this.accountTracker._updateAccounts();
});
const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring];
this.keyringController = new KeyringController({
keyringTypes: additionalKeyrings,
@ -323,7 +324,7 @@ export default class MetamaskController extends EventEmitter {
}
});
this.networkController.on('networkDidChange', () => {
this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => {
this.setCurrentCurrency(
this.currencyRateController.state.currentCurrency,
(error) => {
@ -357,6 +358,21 @@ export default class MetamaskController extends EventEmitter {
tokenRatesStore: this.tokenRatesController.store,
});
// ensure accountTracker updates balances after network change
this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => {
this.accountTracker._updateAccounts();
});
// clear unapproved transactions and messages when the network will change
this.networkController.on(NETWORK_EVENTS.NETWORK_WILL_CHANGE, () => {
this.txController.txStateManager.clearUnapprovedTxs();
this.encryptionPublicKeyManager.clearUnapproved();
this.personalMessageManager.clearUnapproved();
this.typedMessageManager.clearUnapproved();
this.decryptMessageManager.clearUnapproved();
this.messageManager.clearUnapproved();
});
// ensure isClientOpenAndUnlocked is updated when memState updates
this.on('update', (memState) => this._onStateUpdate(memState));

@ -197,13 +197,13 @@
"@metamask/forwarder": "^1.1.0",
"@metamask/test-dapp": "^4.0.1",
"@sentry/cli": "^1.58.0",
"@storybook/addon-actions": "^6.1.9",
"@storybook/addon-backgrounds": "^6.1.9",
"@storybook/addon-knobs": "^6.1.9",
"@storybook/addon-actions": "^6.1.17",
"@storybook/addon-backgrounds": "^6.1.17",
"@storybook/addon-knobs": "^6.1.17",
"@storybook/addon-toolbars": "^6.1.17",
"@storybook/core": "^6.1.9",
"@storybook/react": "^6.1.9",
"@storybook/storybook-deployer": "^2.8.6",
"@storybook/core": "^6.1.17",
"@storybook/react": "^6.1.17",
"@storybook/storybook-deployer": "^2.8.7",
"@testing-library/react": "^10.4.8",
"@testing-library/react-hooks": "^3.2.1",
"@types/react": "^16.9.53",
@ -308,6 +308,8 @@
"chromedriver": true,
"geckodriver": true,
"@sentry/cli": true,
"electron": true,
"sqlite3": true,
"core-js": false,
"core-js-pure": false,
"keccak": false,
@ -316,10 +318,8 @@
"sha3": false,
"bufferutil": false,
"utf-8-validate": false,
"electron": false,
"ejs": false,
"sc-uws": false,
"sqlite3": false,
"leveldown": false,
"ursa-optional": false,
"gc-stats": false,

@ -19,6 +19,7 @@ import {
TRANSACTION_CATEGORIES,
TRANSACTION_STATUSES,
} from '../../../../shared/constants/transaction';
import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network';
const IncomingTransactionsController = proxyquire(
'../../../../app/scripts/controllers/incoming-transactions',
@ -161,7 +162,7 @@ describe('IncomingTransactionsController', function () {
assert(incomingTransactionsController.networkController.on.calledOnce);
assert.equal(
incomingTransactionsController.networkController.on.getCall(0).args[0],
'networkDidChange',
NETWORK_EVENTS.NETWORK_DID_CHANGE,
);
const networkControllerListenerCallback = incomingTransactionsController.networkController.on.getCall(
0,

@ -8,6 +8,7 @@ import {
METAMETRICS_BACKGROUND_PAGE_OBJECT,
} from '../../../../shared/constants/metametrics';
import waitUntilCalled from '../../../lib/wait-until-called';
import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network';
const segment = createSegmentMock(2, 10000);
const segmentLegacy = createSegmentMock(2, 10000);
@ -49,7 +50,7 @@ function getMockNetworkController(
provider = { type: NETWORK },
) {
let networkStore = { chainId, provider };
const on = sinon.stub().withArgs('networkDidChange');
const on = sinon.stub().withArgs(NETWORK_EVENTS.NETWORK_DID_CHANGE);
const updateState = (newState) => {
networkStore = { ...networkStore, ...newState };
on.getCall(0).args[1]();
@ -99,7 +100,7 @@ function getMetaMetricsController({
),
onNetworkDidChange: networkController.on.bind(
networkController,
'networkDidChange',
NETWORK_EVENTS.NETWORK_DID_CHANGE,
),
preferencesStore,
version: '0.0.1',

@ -14,6 +14,7 @@ import { createTestProviderTools } from '../../../stub/provider';
import SwapsController, {
utils,
} from '../../../../app/scripts/controllers/swaps';
import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network';
const MOCK_FETCH_PARAMS = {
slippage: 3,
@ -101,7 +102,10 @@ function getMockNetworkController() {
};
},
},
on: sinon.stub().withArgs('networkDidChange').callsArgAsync(1),
on: sinon
.stub()
.withArgs(NETWORK_EVENTS.NETWORK_DID_CHANGE)
.callsArgAsync(1),
};
}

@ -15,6 +15,7 @@ import {
TRANSACTION_STATUSES,
TRANSACTION_TYPES,
} from '../../../../../shared/constants/transaction';
import { METAMASK_CONTROLLER_EVENTS } from '../../../../../app/scripts/metamask-controller';
const noop = () => true;
const currentNetworkId = '42';
@ -395,7 +396,10 @@ describe('Transaction Controller', function () {
txParams: {},
};
const eventNames = ['update:badge', '1:unapproved'];
const eventNames = [
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
'1:unapproved',
];
const listeners = [];
eventNames.forEach((eventName) => {
listeners.push(

@ -19,10 +19,6 @@ const gasActionSpies = {
resetCustomData: sinon.spy(),
};
const confirmTransactionActionSpies = {
updateGasAndCalculate: sinon.spy(),
};
const sendActionSpies = {
hideGasButtonGroup: sinon.spy(),
};
@ -48,7 +44,6 @@ proxyquire('../gas-modal-page-container.container.js', {
},
'../../../../store/actions': actionSpies,
'../../../../ducks/gas/gas.duck': gasActionSpies,
'../../../../ducks/confirm-transaction/confirm-transaction.duck': confirmTransactionActionSpies,
'../../../../ducks/send/send.duck': sendActionSpies,
});

@ -9,12 +9,11 @@
&--account,
&--network {
flex: 1;
}
&--account {
display: flex;
align-items: center;
}
&--account {
.account-list-item {
&__top-row {
display: flex;

@ -0,0 +1,37 @@
import React from 'react';
import testData from '../../../../../.storybook/test-data';
import SignatureRequest from './signature-request.component';
const primaryIdentity = Object.values(testData.metamask.identities)[0];
const containerStyle = {
width: '357px',
};
export default {
title: 'Signature Request',
};
export const FirstLook = () => {
return (
<div style={containerStyle}>
<SignatureRequest
txData={{
msgParams: {
data: JSON.stringify({
domain: {
name: 'happydapp.website',
},
message: {
string: 'haay wuurl',
number: 42,
},
}),
origin: 'https://happydapp.website/governance?futarchy=true',
},
}}
fromAccount={primaryIdentity}
/>
</div>
);
};

@ -1,4 +1,3 @@
import { addHexPrefix } from '../../../../app/scripts/lib/util';
import {
conversionRateSelector,
currentCurrencySelector,
@ -24,32 +23,19 @@ import { conversionUtil } from '../../helpers/utils/conversion-util';
const createActionType = (action) => `metamask/confirm-transaction/${action}`;
const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA');
const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA');
const UPDATE_TOKEN_DATA = createActionType('UPDATE_TOKEN_DATA');
const CLEAR_TOKEN_DATA = createActionType('CLEAR_TOKEN_DATA');
const UPDATE_METHOD_DATA = createActionType('UPDATE_METHOD_DATA');
const CLEAR_METHOD_DATA = createActionType('CLEAR_METHOD_DATA');
const CLEAR_CONFIRM_TRANSACTION = createActionType('CLEAR_CONFIRM_TRANSACTION');
const UPDATE_TRANSACTION_AMOUNTS = createActionType(
'UPDATE_TRANSACTION_AMOUNTS',
);
const UPDATE_TRANSACTION_FEES = createActionType('UPDATE_TRANSACTION_FEES');
const UPDATE_TRANSACTION_TOTALS = createActionType('UPDATE_TRANSACTION_TOTALS');
const UPDATE_TOKEN_PROPS = createActionType('UPDATE_TOKEN_PROPS');
const UPDATE_NONCE = createActionType('UPDATE_NONCE');
const UPDATE_TO_SMART_CONTRACT = createActionType('UPDATE_TO_SMART_CONTRACT');
const FETCH_DATA_START = createActionType('FETCH_DATA_START');
const FETCH_DATA_END = createActionType('FETCH_DATA_END');
// Initial state
const initState = {
txData: {},
tokenData: {},
methodData: {},
tokenProps: {
tokenDecimals: '',
tokenSymbol: '',
},
fiatTransactionAmount: '',
fiatTransactionFee: '',
fiatTransactionTotal: '',
@ -60,8 +46,6 @@ const initState = {
hexTransactionFee: '',
hexTransactionTotal: '',
nonce: '',
toSmartContract: false,
fetchingData: false,
};
// Reducer
@ -74,11 +58,6 @@ export default function reducer(state = initState, action = {}) {
...action.payload,
},
};
case CLEAR_TX_DATA:
return {
...state,
txData: {},
};
case UPDATE_TOKEN_DATA:
return {
...state,
@ -86,23 +65,6 @@ export default function reducer(state = initState, action = {}) {
...action.payload,
},
};
case CLEAR_TOKEN_DATA:
return {
...state,
tokenData: {},
};
case UPDATE_METHOD_DATA:
return {
...state,
methodData: {
...action.payload,
},
};
case CLEAR_METHOD_DATA:
return {
...state,
methodData: {},
};
case UPDATE_TRANSACTION_AMOUNTS: {
const {
fiatTransactionAmount,
@ -146,37 +108,11 @@ export default function reducer(state = initState, action = {}) {
hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal,
};
}
case UPDATE_TOKEN_PROPS: {
const { tokenSymbol = '', tokenDecimals = '' } = action.payload;
return {
...state,
tokenProps: {
...state.tokenProps,
tokenSymbol,
tokenDecimals,
},
};
}
case UPDATE_NONCE:
return {
...state,
nonce: action.payload,
};
case UPDATE_TO_SMART_CONTRACT:
return {
...state,
toSmartContract: action.payload,
};
case FETCH_DATA_START:
return {
...state,
fetchingData: true,
};
case FETCH_DATA_END:
return {
...state,
fetchingData: false,
};
case CLEAR_CONFIRM_TRANSACTION:
return initState;
default:
@ -192,12 +128,6 @@ export function updateTxData(txData) {
};
}
export function clearTxData() {
return {
type: CLEAR_TX_DATA,
};
}
export function updateTokenData(tokenData) {
return {
type: UPDATE_TOKEN_DATA,
@ -205,25 +135,6 @@ export function updateTokenData(tokenData) {
};
}
export function clearTokenData() {
return {
type: CLEAR_TOKEN_DATA,
};
}
export function updateMethodData(methodData) {
return {
type: UPDATE_METHOD_DATA,
payload: methodData,
};
}
export function clearMethodData() {
return {
type: CLEAR_METHOD_DATA,
};
}
export function updateTransactionAmounts(amounts) {
return {
type: UPDATE_TRANSACTION_AMOUNTS,
@ -245,13 +156,6 @@ export function updateTransactionTotals(totals) {
};
}
export function updateTokenProps(tokenProps) {
return {
type: UPDATE_TOKEN_PROPS,
payload: tokenProps,
};
}
export function updateNonce(nonce) {
return {
type: UPDATE_NONCE,
@ -259,37 +163,6 @@ export function updateNonce(nonce) {
};
}
export function updateToSmartContract(toSmartContract) {
return {
type: UPDATE_TO_SMART_CONTRACT,
payload: toSmartContract,
};
}
export function setFetchingData(isFetching) {
return {
type: isFetching ? FETCH_DATA_START : FETCH_DATA_END,
};
}
export function updateGasAndCalculate({ gasLimit, gasPrice }) {
return (dispatch, getState) => {
const {
confirmTransaction: { txData },
} = getState();
const newTxData = {
...txData,
txParams: {
...txData.txParams,
gas: addHexPrefix(gasLimit),
gasPrice: addHexPrefix(gasPrice),
},
};
dispatch(updateTxDataAndCalculate(newTxData));
};
}
function increaseFromLastGasPrice(txData) {
const {
lastGasPrice,

@ -2,21 +2,13 @@ import assert from 'assert';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import sinon from 'sinon';
import {
TRANSACTION_CATEGORIES,
TRANSACTION_STATUSES,
} from '../../../../shared/constants/transaction';
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck';
const initialState = {
txData: {},
tokenData: {},
methodData: {},
tokenProps: {
tokenDecimals: '',
tokenSymbol: '',
},
fiatTransactionAmount: '',
fiatTransactionFee: '',
fiatTransactionTotal: '',
@ -27,28 +19,17 @@ const initialState = {
hexTransactionFee: '',
hexTransactionTotal: '',
nonce: '',
toSmartContract: false,
fetchingData: false,
};
const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA';
const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA';
const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA';
const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA';
const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA';
const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA';
const UPDATE_TRANSACTION_AMOUNTS =
'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS';
const UPDATE_TRANSACTION_FEES =
'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES';
const UPDATE_TRANSACTION_TOTALS =
'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS';
const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS';
const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE';
const UPDATE_TO_SMART_CONTRACT =
'metamask/confirm-transaction/UPDATE_TO_SMART_CONTRACT';
const FETCH_DATA_START = 'metamask/confirm-transaction/FETCH_DATA_START';
const FETCH_DATA_END = 'metamask/confirm-transaction/FETCH_DATA_END';
const CLEAR_CONFIRM_TRANSACTION =
'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION';
@ -61,13 +42,6 @@ describe('Confirm Transaction Duck', function () {
tokenData: {
name: 'abcToken',
},
methodData: {
name: TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE,
},
tokenProps: {
tokenDecimals: '3',
tokenSymbol: 'ABC',
},
fiatTransactionAmount: '469.26',
fiatTransactionFee: '0.01',
fiatTransactionTotal: '1.000021',
@ -78,8 +52,6 @@ describe('Confirm Transaction Duck', function () {
hexTransactionFee: '0x1319718a5000',
hexTransactionTotal: '',
nonce: '0x0',
toSmartContract: false,
fetchingData: false,
};
it('should initialize state', function () {
@ -117,18 +89,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should clear txData when receiving a CLEAR_TX_DATA action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: CLEAR_TX_DATA,
}),
{
...mockState,
txData: {},
},
);
});
it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
@ -147,48 +107,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: CLEAR_TOKEN_DATA,
}),
{
...mockState,
tokenData: {},
},
);
});
it('should set methodData when receiving a UPDATE_METHOD_DATA action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: UPDATE_METHOD_DATA,
payload: {
name: 'transferFrom',
},
}),
{
...mockState,
methodData: {
...mockState.methodData,
name: 'transferFrom',
},
},
);
});
it('should clear methodData when receiving a CLEAR_METHOD_DATA action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: CLEAR_METHOD_DATA,
}),
{
...mockState,
methodData: {},
},
);
});
it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
@ -246,25 +164,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: UPDATE_TOKEN_PROPS,
payload: {
tokenSymbol: 'DEF',
tokenDecimals: '1',
},
}),
{
...mockState,
tokenProps: {
tokenSymbol: 'DEF',
tokenDecimals: '1',
},
},
);
});
it('should update nonce when receiving an UPDATE_NONCE action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
@ -278,41 +177,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: UPDATE_TO_SMART_CONTRACT,
payload: true,
}),
{
...mockState,
toSmartContract: true,
},
);
});
it('should set fetchingData to true when receiving a FETCH_DATA_START action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
type: FETCH_DATA_START,
}),
{
...mockState,
fetchingData: true,
},
);
});
it('should set fetchingData to false when receiving a FETCH_DATA_END action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(
{ fetchingData: true },
{ type: FETCH_DATA_END },
),
{ fetchingData: false },
);
});
it('should clear confirmTransaction when receiving a FETCH_DATA_END action', function () {
assert.deepStrictEqual(
ConfirmTransactionReducer(mockState, {
@ -334,14 +198,6 @@ describe('Confirm Transaction Duck', function () {
assert.deepStrictEqual(actions.updateTxData(txData), expectedAction);
});
it('should create an action to clear txData', function () {
const expectedAction = {
type: CLEAR_TX_DATA,
};
assert.deepStrictEqual(actions.clearTxData(), expectedAction);
});
it('should create an action to update tokenData', function () {
const tokenData = { test: 123 };
const expectedAction = {
@ -355,35 +211,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should create an action to clear tokenData', function () {
const expectedAction = {
type: CLEAR_TOKEN_DATA,
};
assert.deepStrictEqual(actions.clearTokenData(), expectedAction);
});
it('should create an action to update methodData', function () {
const methodData = { test: 123 };
const expectedAction = {
type: UPDATE_METHOD_DATA,
payload: methodData,
};
assert.deepStrictEqual(
actions.updateMethodData(methodData),
expectedAction,
);
});
it('should create an action to clear methodData', function () {
const expectedAction = {
type: CLEAR_METHOD_DATA,
};
assert.deepStrictEqual(actions.clearMethodData(), expectedAction);
});
it('should create an action to update transaction amounts', function () {
const transactionAmounts = { test: 123 };
const expectedAction = {
@ -423,22 +250,6 @@ describe('Confirm Transaction Duck', function () {
);
});
it('should create an action to update tokenProps', function () {
const tokenProps = {
tokenDecimals: '1',
tokenSymbol: 'abc',
};
const expectedAction = {
type: UPDATE_TOKEN_PROPS,
payload: tokenProps,
};
assert.deepStrictEqual(
actions.updateTokenProps(tokenProps),
expectedAction,
);
});
it('should create an action to update nonce', function () {
const nonce = '0x1';
const expectedAction = {
@ -449,22 +260,6 @@ describe('Confirm Transaction Duck', function () {
assert.deepStrictEqual(actions.updateNonce(nonce), expectedAction);
});
it('should create an action to set fetchingData to true', function () {
const expectedAction = {
type: FETCH_DATA_START,
};
assert.deepStrictEqual(actions.setFetchingData(true), expectedAction);
});
it('should create an action to set fetchingData to false', function () {
const expectedAction = {
type: FETCH_DATA_END,
};
assert.deepStrictEqual(actions.setFetchingData(false), expectedAction);
});
it('should create an action to clear confirmTransaction', function () {
const expectedAction = {
type: CLEAR_CONFIRM_TRANSACTION,
@ -489,61 +284,6 @@ describe('Confirm Transaction Duck', function () {
global.eth.getCode.resetHistory();
});
it('updates txData and gas on an existing transaction in confirmTransaction', function () {
const mockState = {
metamask: {
conversionRate: 468.58,
currentCurrency: 'usd',
},
confirmTransaction: {
ethTransactionAmount: '1',
ethTransactionFee: '0.000021',
ethTransactionTotal: '1.000021',
fetchingData: false,
fiatTransactionAmount: '469.26',
fiatTransactionFee: '0.01',
fiatTransactionTotal: '469.27',
hexGasTotal: '0x1319718a5000',
methodData: {},
nonce: '',
tokenData: {},
tokenProps: {
tokenDecimals: '',
tokenSymbol: '',
},
txData: {
history: [],
id: 2603411941761054,
loadingDefaults: false,
metamaskNetworkId: '3',
origin: 'faucet.metamask.io',
status: TRANSACTION_STATUSES.UNAPPROVED,
time: 1530838113716,
},
},
};
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const store = mockStore(mockState);
const expectedActions = [
'metamask/confirm-transaction/UPDATE_TX_DATA',
'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
];
store.dispatch(
actions.updateGasAndCalculate({ gasLimit: '0x2', gasPrice: '0x25' }),
);
const storeActions = store.getActions();
assert.strictEqual(storeActions.length, expectedActions.length);
storeActions.forEach((action, index) =>
assert.strictEqual(action.type, expectedActions[index]),
);
});
it('updates txData and updates gas values in confirmTransaction', function () {
const txData = {
history: [],

@ -205,3 +205,45 @@ export function getBlockExplorerUrlForTx(networkId, hash, rpcPrefs = {}) {
const prefix = getEtherscanNetworkPrefix(networkId);
return `https://${prefix}etherscan.io/tx/${hash}`;
}
/**
* Returns a title for the given transaction category.
*
* This will throw an error if the transaction category is unrecognized and no default is provided.
* @param {function} t - The translation function
* @param {TRANSACTION_CATEGORIES[keyof TRANSACTION_CATEGORIES]} transactionCategory - The transaction category constant
* @returns {string} The transaction category title
*/
export function getTransactionCategoryTitle(t, transactionCategory) {
switch (transactionCategory) {
case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER: {
return t('transfer');
}
case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM: {
return t('transferFrom');
}
case TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE: {
return t('approve');
}
case TRANSACTION_CATEGORIES.SENT_ETHER: {
return t('sentEther');
}
case TRANSACTION_CATEGORIES.CONTRACT_INTERACTION: {
return t('contractInteraction');
}
case TRANSACTION_CATEGORIES.DEPLOY_CONTRACT: {
return t('contractDeployment');
}
case TRANSACTION_CATEGORIES.SWAP: {
return t('swap');
}
case TRANSACTION_CATEGORIES.SWAP_APPROVAL: {
return t('swapApproval');
}
default: {
throw new Error(
`Unrecognized transaction category: ${transactionCategory}`,
);
}
}
}

@ -1,6 +1,9 @@
import { useSelector } from 'react-redux';
import { getKnownMethodData } from '../selectors/selectors';
import { getStatusKey } from '../helpers/utils/transactions.util';
import {
getStatusKey,
getTransactionCategoryTitle,
} from '../helpers/utils/transactions.util';
import { camelCaseToCapitalize } from '../helpers/utils/common.util';
import { PRIMARY, SECONDARY } from '../helpers/constants/common';
import { getTokenAddressParam } from '../helpers/utils/token-util';
@ -186,9 +189,13 @@ export function useTransactionDisplayData(transactionGroup) {
transactionCategory === TRANSACTION_CATEGORIES.CONTRACT_INTERACTION
) {
category = TRANSACTION_GROUP_CATEGORIES.INTERACTION;
const transactionCategoryTitle = getTransactionCategoryTitle(
t,
transactionCategory,
);
title =
(methodData?.name && camelCaseToCapitalize(methodData.name)) ||
t(transactionCategory);
transactionCategoryTitle;
subtitle = origin;
subtitleContainsOrigin = true;
} else if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) {

@ -22,6 +22,7 @@ import {
TRANSACTION_CATEGORIES,
TRANSACTION_STATUSES,
} from '../../../../shared/constants/transaction';
import { getTransactionCategoryTitle } from '../../helpers/utils/transactions.util';
export default class ConfirmTransactionBase extends Component {
static contextTypes = {
@ -690,7 +691,7 @@ export default class ConfirmTransactionBase extends Component {
let functionType = getMethodName(name);
if (!functionType) {
if (transactionCategory) {
functionType = t(transactionCategory) || transactionCategory;
functionType = getTransactionCategoryTitle(t, transactionCategory);
} else {
functionType = t('contractInteraction');
}

@ -2243,7 +2243,7 @@
schema-utils "^2.6.5"
source-map "^0.7.3"
"@popperjs/core@^2.4.0", "@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4":
"@popperjs/core@^2.4.0", "@popperjs/core@^2.5.4":
version "2.5.4"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a"
integrity sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ==
@ -2406,17 +2406,17 @@
resolved "https://registry.yarnpkg.com/@stablelib/utf8/-/utf8-0.10.1.tgz#eecf54884da7b2bee235e3c70efb8cd5c07ba5bd"
integrity sha512-+uM1YZ4MhBC82vt99prF7DXNGqhYmJ9cQ3p5qNowMNkkzn9OWEkqBvguBW3ChAt7JvqZ3SD5HJOfc6YgnfMTHw==
"@storybook/addon-actions@^6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.9.tgz#b6d185b8e4e73691acc428b59e4d331195d64a40"
integrity sha512-vYqwuaBHrjRbbuyf4WBc5uDhrSejVEEiCabuu4g00R3dN7P5Ne/tbSw9EkYbbrRKxlEhdkk83DU1/J/+mCY5jw==
dependencies:
"@storybook/addons" "6.1.9"
"@storybook/api" "6.1.9"
"@storybook/client-api" "6.1.9"
"@storybook/components" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/theming" "6.1.9"
"@storybook/addon-actions@^6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.17.tgz#9d32336284738cefa69b99acafa4b132d5533600"
integrity sha512-4hyAvmjnI4C1ZQ7/t21jKKXE0jO1zAk310BkYin0NJf77Qi0tUE1DNOwirJY/xzRih36wWi1V79c/ZOJNsLv9Q==
dependencies:
"@storybook/addons" "6.1.17"
"@storybook/api" "6.1.17"
"@storybook/client-api" "6.1.17"
"@storybook/components" "6.1.17"
"@storybook/core-events" "6.1.17"
"@storybook/theming" "6.1.17"
core-js "^3.0.1"
fast-deep-equal "^3.1.1"
global "^4.3.2"
@ -2429,17 +2429,17 @@
util-deprecate "^1.0.2"
uuid "^8.0.0"
"@storybook/addon-backgrounds@^6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.9.tgz#4e9647001b2f396f56428218480f541e3a8a0e60"
integrity sha512-0/nnbnWZqo4NjyHFxcCHkcU+t8uUdk///9jSXRs4swmOLIFRaftEc/ZJ2rScu1Sc7y0CQdbk1Jjyx5/2cHBQtw==
dependencies:
"@storybook/addons" "6.1.9"
"@storybook/api" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/components" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/theming" "6.1.9"
"@storybook/addon-backgrounds@^6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.17.tgz#df4eeec1df72d5f835e82bee433493110463f896"
integrity sha512-1a8Vu50eQWdwMek9w2QOehhu10aZYzyR404qwGvPCRGt5uMMsKxoKvv1M6/ETW7d2G4Srl/Ka+k4x6ykoHIepA==
dependencies:
"@storybook/addons" "6.1.17"
"@storybook/api" "6.1.17"
"@storybook/client-logger" "6.1.17"
"@storybook/components" "6.1.17"
"@storybook/core-events" "6.1.17"
"@storybook/theming" "6.1.17"
core-js "^3.0.1"
global "^4.3.2"
memoizerific "^1.11.3"
@ -2447,18 +2447,18 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/addon-knobs@^6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.9.tgz#49773931770effc208db094c61eeecbceaf5836b"
integrity sha512-aUKD9FaQGl/WOkGT6utElspYZJ7cBtUARe41JN59qOao7RNviabipQUASrjORcYUUU55sfKsLPEqQaEKB3x2bw==
dependencies:
"@storybook/addons" "6.1.9"
"@storybook/api" "6.1.9"
"@storybook/channels" "6.1.9"
"@storybook/client-api" "6.1.9"
"@storybook/components" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/theming" "6.1.9"
"@storybook/addon-knobs@^6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.17.tgz#c7cdd5be813c2b80ce7f464eabf8ceb06486e82d"
integrity sha512-WUkoGtHhXIurXFQybsMXZaphAtCNclZjZHvji8O5eg+ahx7pIM/Wldh3uJwOdOkW5LHxT76hLxPvuXvOEysnbw==
dependencies:
"@storybook/addons" "6.1.17"
"@storybook/api" "6.1.17"
"@storybook/channels" "6.1.17"
"@storybook/client-api" "6.1.17"
"@storybook/components" "6.1.17"
"@storybook/core-events" "6.1.17"
"@storybook/theming" "6.1.17"
copy-to-clipboard "^3.0.8"
core-js "^3.0.1"
escape-html "^1.0.3"
@ -2498,21 +2498,6 @@
global "^4.3.2"
regenerator-runtime "^0.13.7"
"@storybook/addons@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.9.tgz#78f3cb27b7d934f091f311f89b6ca312d34f12b8"
integrity sha512-NRxdlGLmmSoVwlirVRgKC8xmW9cFkG+Sp5GEd4XkJDaaIg2vKR3RuFU9GuvIOVMxOhhERqhQ07bnDaAMKbFzGw==
dependencies:
"@storybook/api" "6.1.9"
"@storybook/channels" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/router" "6.1.9"
"@storybook/theming" "6.1.9"
core-js "^3.0.1"
global "^4.3.2"
regenerator-runtime "^0.13.7"
"@storybook/api@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.17.tgz#50393ce9b718063b67680212df895eceacc0c11d"
@ -2538,31 +2523,6 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/api@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.9.tgz#3f9bf00b2b18fa02965079fe775bd713677b30a3"
integrity sha512-S9SXlSiMeI450NIbOnx3UU9TZNyVD7jcBCjfNzhj0PqzRX/IG5Usj+R88Jm6MSIDjtsVjrWRCou+PrCh2xMnlQ==
dependencies:
"@reach/router" "^1.3.3"
"@storybook/channels" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/csf" "0.0.1"
"@storybook/router" "6.1.9"
"@storybook/semver" "^7.3.2"
"@storybook/theming" "6.1.9"
"@types/reach__router" "^1.3.5"
core-js "^3.0.1"
fast-deep-equal "^3.1.1"
global "^4.3.2"
lodash "^4.17.15"
memoizerific "^1.11.3"
regenerator-runtime "^0.13.7"
store2 "^2.7.1"
telejson "^5.0.2"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/channel-postmessage@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.17.tgz#309ce67c94637ec13319d4ce360a8f3742ddbaf4"
@ -2576,19 +2536,6 @@
qs "^6.6.0"
telejson "^5.0.2"
"@storybook/channel-postmessage@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.9.tgz#5d73c67ba94bcf68b14138bba6c5bb0850c72c5e"
integrity sha512-tX7pD9Xrf1WsatpJqtJ6o8MlgxG7jH+oFhNPkGvUbWiolVDQmuDndwM8Hh1kUnOWlyE1AN5hlM7av8MY+9D3NA==
dependencies:
"@storybook/channels" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/core-events" "6.1.9"
core-js "^3.0.1"
global "^4.3.2"
qs "^6.6.0"
telejson "^5.0.2"
"@storybook/channels@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.17.tgz#2cc89a6b9727d19c24b15fa3cb15569b469db864"
@ -2598,15 +2545,6 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/channels@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.9.tgz#94f07ff3615b11c07d1902be6b6cd298c0eea55c"
integrity sha512-aV+KsZPuoTtFKSMUkSCyVlVmtVHkSH35dSbyMazjlUD9cOLwkXB1s+LZL/GxxSR6a6uR75V0QWxItfNxaJETMQ==
dependencies:
core-js "^3.0.1"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/client-api@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.17.tgz#3ced22f08a47af70ccf8929111bc44b79e9e8ec0"
@ -2631,30 +2569,6 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/client-api@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.9.tgz#d4a8d38bc657f26e4837831b961e085da1954d51"
integrity sha512-b2DFaGAS5G2ly3UJY5NJNXh/LxgLgSJLbqPL4t48MFW5XjH+rmEWXE9P+ujCaPclH1/y7mZRMprDj3ycDbRo3Q==
dependencies:
"@storybook/addons" "6.1.9"
"@storybook/channel-postmessage" "6.1.9"
"@storybook/channels" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/csf" "0.0.1"
"@types/qs" "^6.9.0"
"@types/webpack-env" "^1.15.3"
core-js "^3.0.1"
global "^4.3.2"
lodash "^4.17.15"
memoizerific "^1.11.3"
qs "^6.6.0"
regenerator-runtime "^0.13.7"
stable "^0.1.8"
store2 "^2.7.1"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/client-logger@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.17.tgz#0d89aaf824457f19bf9aa585bbcada57595e7d01"
@ -2663,14 +2577,6 @@
core-js "^3.0.1"
global "^4.3.2"
"@storybook/client-logger@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.9.tgz#1d61a64000d4691780d75e19b78fd44adfdb5d9c"
integrity sha512-i7Q2ky9+Jwv+wmnlOGxmDOEdmaTIB69OQnnZNWGKufOwoIMjn6QO0VifARyA9W++nNSijjJ5th84tLJALaoCTA==
dependencies:
core-js "^3.0.1"
global "^4.3.2"
"@storybook/components@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.17.tgz#f92d36e370ec6039d8c7cee9ef13dda866eed3da"
@ -2697,32 +2603,6 @@
react-textarea-autosize "^8.1.1"
ts-dedent "^2.0.0"
"@storybook/components@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.9.tgz#f25d18f3a410cc7e9549ddb3c971c40d9108d4d8"
integrity sha512-cYYm3fHo9MW0bbl47lu1ncwulV7V9VEF8FC96uvys07oaCTFWKzQ0z/FD0nCqeK6eEz1+SEqnGwLFmOtqlRXDQ==
dependencies:
"@popperjs/core" "^2.4.4"
"@storybook/client-logger" "6.1.9"
"@storybook/csf" "0.0.1"
"@storybook/theming" "6.1.9"
"@types/overlayscrollbars" "^1.9.0"
"@types/react-color" "^3.0.1"
"@types/react-syntax-highlighter" "11.0.4"
core-js "^3.0.1"
fast-deep-equal "^3.1.1"
global "^4.3.2"
lodash "^4.17.15"
markdown-to-jsx "^6.11.4"
memoizerific "^1.11.3"
overlayscrollbars "^1.10.2"
polished "^3.4.4"
react-color "^2.17.0"
react-popper-tooltip "^3.1.0"
react-syntax-highlighter "^13.5.0"
react-textarea-autosize "^8.1.1"
ts-dedent "^2.0.0"
"@storybook/core-events@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.17.tgz#697ed916fcb2a411bc9f8bdbfacd0eb9d394eb58"
@ -2730,17 +2610,10 @@
dependencies:
core-js "^3.0.1"
"@storybook/core-events@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.9.tgz#0a88281837d1aa657a93a9abf7f5aad65b8d68e7"
integrity sha512-oOpqpjCTJCt0U5lnQ16OZU0iKIDh2/MIg4yrnDw+Pt6zGyX3zSvtB+9W8LQFnMwm+cXaNmiizGwt/W+4OiORjQ==
dependencies:
core-js "^3.0.1"
"@storybook/core@6.1.9", "@storybook/core@^6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.9.tgz#e6575e294cb4d2d9b57d5976a145cae8f4a88594"
integrity sha512-guz+R6eDX923Cw7NqgS5PrpTmmjDB+m5X1iF9pwKlpPTfzIiT/wTzJm4PwhFoGONNoXrItObX/6hW6OQbX4aOA==
"@storybook/core@6.1.17", "@storybook/core@^6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.17.tgz#21c3d2c23fcaac4b930c9413f396d158aaeb7546"
integrity sha512-9x8ezlKlm8SQ+OW3kKwJwuVcaTDCw2OlA9YZEOo1kdRKsiiy5X14VqjJocl/BqnDt2VgzUUchz3m4neHYMAivQ==
dependencies:
"@babel/core" "^7.12.3"
"@babel/plugin-proposal-class-properties" "^7.12.1"
@ -2764,20 +2637,20 @@
"@babel/preset-react" "^7.12.1"
"@babel/preset-typescript" "^7.12.1"
"@babel/register" "^7.12.1"
"@storybook/addons" "6.1.9"
"@storybook/api" "6.1.9"
"@storybook/channel-postmessage" "6.1.9"
"@storybook/channels" "6.1.9"
"@storybook/client-api" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/components" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/addons" "6.1.17"
"@storybook/api" "6.1.17"
"@storybook/channel-postmessage" "6.1.17"
"@storybook/channels" "6.1.17"
"@storybook/client-api" "6.1.17"
"@storybook/client-logger" "6.1.17"
"@storybook/components" "6.1.17"
"@storybook/core-events" "6.1.17"
"@storybook/csf" "0.0.1"
"@storybook/node-logger" "6.1.9"
"@storybook/router" "6.1.9"
"@storybook/node-logger" "6.1.17"
"@storybook/router" "6.1.17"
"@storybook/semver" "^7.3.2"
"@storybook/theming" "6.1.9"
"@storybook/ui" "6.1.9"
"@storybook/theming" "6.1.17"
"@storybook/ui" "6.1.17"
"@types/glob-base" "^0.3.0"
"@types/micromatch" "^4.0.1"
"@types/node-fetch" "^2.5.4"
@ -2851,10 +2724,10 @@
dependencies:
lodash "^4.17.15"
"@storybook/node-logger@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.9.tgz#c63a61f72209d76eeeffe9d151fec043864b9438"
integrity sha512-2gP9BSBXEOGIcUyzRdIkIJi1UEINUAIyuv9bfKODo4GfujRg7DLz/mpi/FdwmulGg/viXWSXa6ccb6ziIgY9RA==
"@storybook/node-logger@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.17.tgz#468e65c9f0c103d4b0cd7f5da945af81e9aaa3d4"
integrity sha512-Z0xQ4kzvf7GnwFG9UY1HJO2UR66t8IBnC5GxvWrJ/kwXE+DRF3mm/MT41Zz/d9zAY5Vo4mhE5zRwlYSAtrxQIQ==
dependencies:
"@types/npmlog" "^4.1.2"
chalk "^4.0.0"
@ -2862,17 +2735,17 @@
npmlog "^4.1.2"
pretty-hrtime "^1.0.3"
"@storybook/react@^6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.9.tgz#063427015b3d0ce582b1b6b7826d40d963d265ce"
integrity sha512-HJWHQE+eCC7sz1vqvgmBMn2sA1uc0ByEj+NeSgyi45jBFI+Ke4a8hxx6k5XA7k9gLznqG8TPGg0z6EdQTJTLkQ==
"@storybook/react@^6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.17.tgz#cb48386d435984d7ca58a24e686a72159367077b"
integrity sha512-gBylKDuwUzWueB6mEhTo72SelWU3vPWHAFsi+NK6zWFIc2a5dJc9QqDfN+2rBhVOdRXqhSHzYwNWurqYpWuqew==
dependencies:
"@babel/preset-flow" "^7.12.1"
"@babel/preset-react" "^7.12.1"
"@pmmmwh/react-refresh-webpack-plugin" "^0.4.2"
"@storybook/addons" "6.1.9"
"@storybook/core" "6.1.9"
"@storybook/node-logger" "6.1.9"
"@storybook/addons" "6.1.17"
"@storybook/core" "6.1.17"
"@storybook/node-logger" "6.1.17"
"@storybook/semver" "^7.3.2"
"@types/webpack-env" "^1.15.3"
babel-plugin-add-react-displayname "^0.0.5"
@ -2901,18 +2774,6 @@
memoizerific "^1.11.3"
qs "^6.6.0"
"@storybook/router@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.9.tgz#c0b24dc3ab53d58541b81c7abea2f11d7fbbebf6"
integrity sha512-kIlmSFBnqI198oMCncFZR7MxoV5/kP6KS0paFcyu1XE1zO2ovV6eQZ8pPpOjSsD/ISu4Y44uE+ZDNsEehjj6GQ==
dependencies:
"@reach/router" "^1.3.3"
"@types/reach__router" "^1.3.5"
core-js "^3.0.1"
global "^4.3.2"
memoizerific "^1.11.3"
qs "^6.6.0"
"@storybook/semver@^7.3.2":
version "7.3.2"
resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0"
@ -2921,10 +2782,10 @@
core-js "^3.6.5"
find-up "^4.1.0"
"@storybook/storybook-deployer@^2.8.6":
version "2.8.6"
resolved "https://registry.yarnpkg.com/@storybook/storybook-deployer/-/storybook-deployer-2.8.6.tgz#00c2e84f27dfaa88cb0785361453f23b1ebb4ea3"
integrity sha512-Bpe7ZtsR5NUuohK3VsQa+nxEHtVxMZZo3DRlRUZW5IZOmzmvSID3i+jkizloG9xO7sw5zUvlD31YMHm7OtdrMA==
"@storybook/storybook-deployer@^2.8.7":
version "2.8.7"
resolved "https://registry.yarnpkg.com/@storybook/storybook-deployer/-/storybook-deployer-2.8.7.tgz#c1eed33d03bd9267f884c60eea8e03dc3261ec11"
integrity sha512-O0hKHV6hg93fPMvKGC5M/sd7KTL473+SzMKm+WZNVEyLEfXXcVU+Ts9/VL1IhmC1P2A8Bg9oBnkcPqAqjAN46w==
dependencies:
git-url-parse "^11.1.2"
glob "^7.1.3"
@ -2950,39 +2811,21 @@
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
"@storybook/theming@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.9.tgz#8c584aa623f3d6e33b1e3b3de2ec1f41bdc5d9ab"
integrity sha512-orzMQkyEhAQEi0E9iwmUkzh5yPHoYGBz17t2aydDeT6oGKii6if8Mq2oPVycfVKZ84QO7GFAS9q1nVCRcuD8oA==
dependencies:
"@emotion/core" "^10.1.1"
"@emotion/is-prop-valid" "^0.8.6"
"@emotion/styled" "^10.0.23"
"@storybook/client-logger" "6.1.9"
core-js "^3.0.1"
deep-object-diff "^1.1.0"
emotion-theming "^10.0.19"
global "^4.3.2"
memoizerific "^1.11.3"
polished "^3.4.4"
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
"@storybook/ui@6.1.9":
version "6.1.9"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.9.tgz#1ed3168d9fe5827285c13d8507dd1fd872830542"
integrity sha512-4MK5iTf7kI5DYVeWRiD6lkXdd0S6eiQJu9lvWqMOQJLOH5Bq77g0Ejo+38RTEQpV6we7hCPWWnRXQBjmJ2+19w==
"@storybook/ui@6.1.17":
version "6.1.17"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.17.tgz#c29e7a03c645dd94793a3cbd587fcb6e0ba0f22e"
integrity sha512-D4Vri1MmqfmNq+g1hSRqZyld5zX2VLUexQHGSPmNj+FhlOzkeNA5RcoMBWMvIUSUENiBx3a5gmr/6cbXo7ljdQ==
dependencies:
"@emotion/core" "^10.1.1"
"@storybook/addons" "6.1.9"
"@storybook/api" "6.1.9"
"@storybook/channels" "6.1.9"
"@storybook/client-logger" "6.1.9"
"@storybook/components" "6.1.9"
"@storybook/core-events" "6.1.9"
"@storybook/router" "6.1.9"
"@storybook/addons" "6.1.17"
"@storybook/api" "6.1.17"
"@storybook/channels" "6.1.17"
"@storybook/client-logger" "6.1.17"
"@storybook/components" "6.1.17"
"@storybook/core-events" "6.1.17"
"@storybook/router" "6.1.17"
"@storybook/semver" "^7.3.2"
"@storybook/theming" "6.1.9"
"@storybook/theming" "6.1.17"
"@types/markdown-to-jsx" "^6.11.0"
copy-to-clipboard "^3.0.8"
core-js "^3.0.1"
@ -3145,11 +2988,6 @@
dependencies:
"@types/unist" "*"
"@types/history@*":
version "4.7.3"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.3.tgz#856c99cdc1551d22c22b18b5402719affec9839a"
integrity sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw==
"@types/html-minifier-terser@^5.0.0":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
@ -3304,14 +3142,6 @@
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b"
integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==
"@types/reach__router@^1.3.5":
version "1.3.6"
resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709"
integrity sha512-RHYataCUPQnt+GHoASyRLq6wmZ0n8jWlBW8Lxcwd30NN6vQfbmTeoSDfkgxO0S1lEzArp8OFDsq5KIs7FygjtA==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/reach__router@^1.3.7":
version "1.3.7"
resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.7.tgz#de8ab374259ae7f7499fc1373b9697a5f3cd6428"
@ -6039,12 +5869,12 @@ bn.js@^1.0.0:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-1.3.0.tgz#0db4cbf96f8f23b742f5bcb9d1aa7a9994a05e83"
integrity sha1-DbTL+W+PI7dC9by50ap6mZSgXoM=
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.4.0, bn.js@^4.8.0:
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.4.0, bn.js@^4.8.0:
version "4.11.9"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
bn.js@^5.1.1:
bn.js@^5.1.1, bn.js@^5.1.2:
version "5.1.3"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
@ -6518,6 +6348,13 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer-xor@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289"
integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==
dependencies:
safe-buffer "^5.1.1"
buffer@^4.3.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
@ -10261,27 +10098,23 @@ eth-sig-util@^1.4.0, eth-sig-util@^1.4.2:
ethereumjs-util "^5.1.1"
eth-sig-util@^2.0.0, eth-sig-util@^2.4.4, eth-sig-util@^2.5.0:
version "2.5.3"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.3.tgz#6938308b38226e0b3085435474900b03036abcbe"
integrity sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw==
version "2.5.4"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5"
integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A==
dependencies:
buffer "^5.2.1"
elliptic "^6.4.0"
ethereumjs-abi "0.6.5"
ethereumjs-abi "0.6.8"
ethereumjs-util "^5.1.1"
tweetnacl "^1.0.0"
tweetnacl "^1.0.3"
tweetnacl-util "^0.15.0"
eth-sig-util@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e"
integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ==
version "3.0.1"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96"
integrity sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ==
dependencies:
buffer "^5.2.1"
elliptic "^6.4.0"
ethereumjs-abi "0.6.5"
ethereumjs-abi "^0.6.8"
ethereumjs-util "^5.1.1"
tweetnacl "^1.0.0"
tweetnacl "^1.0.3"
tweetnacl-util "^0.15.0"
eth-simple-keyring@^3.5.0:
@ -10324,13 +10157,13 @@ eth-tx-summary@^3.1.2:
through2 "^2.0.3"
ethashjs@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.7.tgz#30bfe4196726690a0c59d3b8272e70d4d0c34bae"
integrity sha1-ML/kGWcmaQoMWdO4Jy5w1NDDS64=
version "0.0.8"
resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9"
integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==
dependencies:
async "^1.4.2"
buffer-xor "^1.0.3"
ethereumjs-util "^4.0.1"
async "^2.1.2"
buffer-xor "^2.0.1"
ethereumjs-util "^7.0.2"
miller-rabin "^4.0.0"
ethereum-bloom-filters@^1.0.6:
@ -10376,15 +10209,7 @@ ethereum-ens-network-map@^1.0.0, ethereum-ens-network-map@^1.0.2:
resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz#4e27bad18dae7bd95d84edbcac2c9e739fc959b9"
integrity sha512-5qwJ5n3YhjSpE6O/WEBXCAb2nagUgyagJ6C0lGUBWC4LjKp/rRzD+pwtDJ6KCiITFEAoX4eIrWOjRy0Sylq5Hg==
ethereumjs-abi@0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241"
integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=
dependencies:
bn.js "^4.10.0"
ethereumjs-util "^4.3.0"
ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5:
ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5, ethereumjs-abi@^0.6.8:
version "0.6.8"
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae"
integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==
@ -10505,17 +10330,6 @@ ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj
ethjs-util "0.1.6"
rlp "^2.2.3"
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=
dependencies:
bn.js "^4.8.0"
create-hash "^1.1.2"
keccakjs "^0.2.0"
rlp "^2.0.0"
secp256k1 "^3.0.1"
ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642"
@ -10529,6 +10343,18 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum
safe-buffer "^5.1.1"
secp256k1 "^3.0.1"
ethereumjs-util@^7.0.2:
version "7.0.8"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz#5258762b7b17e3d828e41834948363ff0a703ffd"
integrity sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ==
dependencies:
"@types/bn.js" "^4.11.3"
bn.js "^5.1.2"
create-hash "^1.1.2"
ethereum-cryptography "^0.1.3"
ethjs-util "0.1.6"
rlp "^2.2.4"
ethereumjs-util@~6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8"
@ -15923,7 +15749,7 @@ keccak@^1.0.2:
nan "^2.2.1"
safe-buffer "^5.1.0"
keccakjs@^0.2.0, keccakjs@^0.2.1:
keccakjs@^0.2.1:
version "0.2.3"
resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72"
integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg==
@ -21553,7 +21379,7 @@ react-motion@^0.5.2:
prop-types "^15.5.8"
raf "^3.1.0"
react-popper-tooltip@^3.1.0, react-popper-tooltip@^3.1.1:
react-popper-tooltip@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac"
integrity sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ==
@ -22759,6 +22585,13 @@ rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3:
dependencies:
bn.js "^4.11.1"
rlp@^2.2.4:
version "2.2.6"
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c"
integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==
dependencies:
bn.js "^4.11.1"
rn-host-detect@^1.1.5:
version "1.2.0"
resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.2.0.tgz#8b0396fc05631ec60c1cb8789e5070cdb04d0da0"
@ -25426,7 +25259,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
tweetnacl@^1.0.0, tweetnacl@^1.0.1:
tweetnacl@^1.0.0, tweetnacl@^1.0.1, tweetnacl@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==

Loading…
Cancel
Save