Merge pull request #8886 from MetaMask/Version-v8.0.1

Version v8.0.1
feature/default_network_editable
Mark Stacey 4 years ago committed by GitHub
commit 42dedc799b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      CHANGELOG.md
  2. 2
      app/manifest/_base.json
  3. 4
      app/scripts/controllers/transactions/index.js
  4. 9
      app/scripts/ui.js
  5. 16
      development/build/static.js
  6. 4
      package.json
  7. 2
      ui/app/components/app/menu-bar/menu-bar.js
  8. 9
      ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js
  9. 8
      ui/app/components/app/permission-page-container/permission-page-container.component.js
  10. 8
      ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js
  11. 1
      ui/app/components/ui/page-container/index.scss
  12. 2
      ui/app/components/ui/popover/index.scss
  13. 32
      ui/app/helpers/utils/i18n-helper.js
  14. 2
      ui/app/hooks/useTransactionTimeRemaining.js
  15. 9
      ui/app/pages/permissions-connect/choose-account/choose-account.component.js
  16. 10
      ui/app/pages/permissions-connect/permissions-connect.component.js
  17. 19
      ui/app/pages/permissions-connect/permissions-connect.container.js
  18. 8
      ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js
  19. 9
      ui/app/store/actions.js
  20. 7
      ui/index.js
  21. 16
      yarn.lock

@ -2,6 +2,18 @@
## Current Develop Branch ## Current Develop Branch
## 8.0.1 Thu Jul 02 2020
- [#8874](https://github.com/MetaMask/metamask-extension/pull/8874): Fx overflow behaviour of add token list
- [#8885](https://github.com/MetaMask/metamask-extension/pull/8885): Show `origin` in connect flow rather than site name
- [#8883](https://github.com/MetaMask/metamask-extension/pull/8883): Allow setting a custom nonce of zero
- [#8889](https://github.com/MetaMask/metamask-extension/pull/8889): Fix language code format mismatch
- [#8891](https://github.com/MetaMask/metamask-extension/pull/8891): Prevent showing connected accounts without origin
- [#8893](https://github.com/MetaMask/metamask-extension/pull/8893): Prevent manually connecting to extension UI
- [#8895](https://github.com/MetaMask/metamask-extension/pull/8895): Allow localized messages to not use substitutions
- [#8897](https://github.com/MetaMask/metamask-extension/pull/8897): Update eth-keyring-controller to fix erasure of imported/hardware account names
- [#8896](https://github.com/MetaMask/metamask-extension/pull/8896): Include relative time polyfill locale data
- [#8898](https://github.com/MetaMask/metamask-extension/pull/8898): Replace percentage opacity value
## 8.0.0 Mon Jun 23 2020 ## 8.0.0 Mon Jun 23 2020
- [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Add permission system - [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Add permission system
- [#7261](https://github.com/MetaMask/metamask-extension/pull/7261): Search accounts by name - [#7261](https://github.com/MetaMask/metamask-extension/pull/7261): Search accounts by name

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

@ -443,14 +443,14 @@ export default class TransactionController extends EventEmitter {
const txMeta = this.txStateManager.getTx(txId) const txMeta = this.txStateManager.getTx(txId)
const fromAddress = txMeta.txParams.from const fromAddress = txMeta.txParams.from
// wait for a nonce // wait for a nonce
let { customNonceValue = null } = txMeta let { customNonceValue } = txMeta
customNonceValue = Number(customNonceValue) customNonceValue = Number(customNonceValue)
nonceLock = await this.nonceTracker.getNonceLock(fromAddress) nonceLock = await this.nonceTracker.getNonceLock(fromAddress)
// add nonce to txParams // add nonce to txParams
// if txMeta has lastGasPrice then it is a retry at same nonce with higher // if txMeta has lastGasPrice then it is a retry at same nonce with higher
// gas price transaction and their for the nonce should not be calculated // gas price transaction and their for the nonce should not be calculated
const nonce = txMeta.lastGasPrice ? txMeta.txParams.nonce : nonceLock.nextNonce const nonce = txMeta.lastGasPrice ? txMeta.txParams.nonce : nonceLock.nextNonce
const customOrNonce = customNonceValue || nonce const customOrNonce = (customNonceValue === 0) ? customNonceValue : customNonceValue || nonce
txMeta.txParams.nonce = ethUtil.addHexPrefix(customOrNonce.toString(16)) txMeta.txParams.nonce = ethUtil.addHexPrefix(customOrNonce.toString(16))
// add nonce debugging information to txMeta // add nonce debugging information to txMeta

@ -83,10 +83,15 @@ async function queryCurrentActiveTab (windowType) {
extension.tabs.query({ active: true, currentWindow: true }, (tabs) => { extension.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const [activeTab] = tabs const [activeTab] = tabs
const { title, url } = activeTab const { id, title, url } = activeTab
const { origin, protocol } = url ? new URL(url) : {} const { origin, protocol } = url ? new URL(url) : {}
resolve({ title, origin, protocol, url }) if (!origin || origin === 'null') {
resolve({})
return
}
resolve({ id, title, origin, protocol, url })
}) })
}) })
} }

@ -3,6 +3,8 @@ const path = require('path')
const watch = require('gulp-watch') const watch = require('gulp-watch')
const glob = require('fast-glob') const glob = require('fast-glob')
const locales = require('../../app/_locales/index.json')
const { createTask, composeSeries } = require('./task') const { createTask, composeSeries } = require('./task')
module.exports = createStaticAssetTasks module.exports = createStaticAssetTasks
@ -45,6 +47,20 @@ const copyTargets = [
}, },
] ]
const languageTags = new Set()
for (const locale of locales) {
const { code } = locale
const tag = code.split('_')[0]
languageTags.add(tag)
}
for (const tag of languageTags) {
copyTargets.push({
src: `./node_modules/@formatjs/intl-relativetimeformat/dist/locale-data/${tag}.json`,
dest: `intl/${tag}/relative-time-format-data.json`,
})
}
const copyTargetsDev = [ const copyTargetsDev = [
...copyTargets, ...copyTargets,
{ {

@ -107,7 +107,7 @@
"eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-filters": "^4.1.1",
"eth-json-rpc-infura": "^4.0.2", "eth-json-rpc-infura": "^4.0.2",
"eth-json-rpc-middleware": "^5.0.1", "eth-json-rpc-middleware": "^5.0.1",
"eth-keyring-controller": "^6.0.0", "eth-keyring-controller": "^6.0.1",
"eth-method-registry": "^1.2.0", "eth-method-registry": "^1.2.0",
"eth-phishing-detect": "^1.1.4", "eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
@ -189,7 +189,7 @@
"@babel/register": "^7.5.5", "@babel/register": "^7.5.5",
"@metamask/eslint-config": "^1.1.0", "@metamask/eslint-config": "^1.1.0",
"@metamask/forwarder": "^1.1.0", "@metamask/forwarder": "^1.1.0",
"@metamask/test-dapp": "^2.1.1", "@metamask/test-dapp": "^2.2.0",
"@sentry/cli": "^1.49.0", "@sentry/cli": "^1.49.0",
"@storybook/addon-actions": "^5.3.14", "@storybook/addon-actions": "^5.3.14",
"@storybook/addon-backgrounds": "^5.3.14", "@storybook/addon-backgrounds": "^5.3.14",

@ -26,7 +26,7 @@ export default function MenuBar () {
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false) const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false)
const origin = useSelector(getOriginOfCurrentTab) const origin = useSelector(getOriginOfCurrentTab)
const showStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP && origin !== extension.runtime.id const showStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP && origin && origin !== extension.runtime.id
return ( return (
<div className="menu-bar"> <div className="menu-bar">

@ -7,7 +7,13 @@ import CheckBox from '../../../ui/check-box'
export default class PermissionPageContainerContent extends PureComponent { export default class PermissionPageContainerContent extends PureComponent {
static propTypes = { static propTypes = {
domainMetadata: PropTypes.object.isRequired, domainMetadata: PropTypes.shape({
extensionId: PropTypes.string,
icon: PropTypes.string,
host: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
}),
selectedPermissions: PropTypes.object.isRequired, selectedPermissions: PropTypes.object.isRequired,
onPermissionToggle: PropTypes.func.isRequired, onPermissionToggle: PropTypes.func.isRequired,
selectedIdentities: PropTypes.array, selectedIdentities: PropTypes.array,
@ -145,6 +151,7 @@ export default class PermissionPageContainerContent extends PureComponent {
? t('allowExternalExtensionTo', [domainMetadata.extensionId]) ? t('allowExternalExtensionTo', [domainMetadata.extensionId])
: t('allowThisSiteTo') : t('allowThisSiteTo')
} }
siteOrigin={domainMetadata.origin}
/> />
<section className="permission-approval-container__permissions-container"> <section className="permission-approval-container__permissions-container">
{ this.renderRequestedPermissions() } { this.renderRequestedPermissions() }

@ -14,7 +14,13 @@ export default class PermissionPageContainer extends Component {
allIdentitiesSelected: PropTypes.bool, allIdentitiesSelected: PropTypes.bool,
request: PropTypes.object, request: PropTypes.object,
requestMetadata: PropTypes.object, requestMetadata: PropTypes.object,
targetDomainMetadata: PropTypes.object.isRequired, targetDomainMetadata: PropTypes.shape({
extensionId: PropTypes.string,
icon: PropTypes.string,
host: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
}),
} }
static defaultProps = { static defaultProps = {

@ -5,25 +5,25 @@ import SiteIcon from '../../ui/site-icon'
export default class PermissionsConnectHeader extends Component { export default class PermissionsConnectHeader extends Component {
static propTypes = { static propTypes = {
icon: PropTypes.string, icon: PropTypes.string,
iconName: PropTypes.string, iconName: PropTypes.string.isRequired,
siteOrigin: PropTypes.string.isRequired,
headerTitle: PropTypes.node, headerTitle: PropTypes.node,
headerText: PropTypes.string, headerText: PropTypes.string,
} }
static defaultProps = { static defaultProps = {
icon: null, icon: null,
iconName: '',
headerTitle: '', headerTitle: '',
headerText: '', headerText: '',
} }
renderHeaderIcon () { renderHeaderIcon () {
const { icon, iconName } = this.props const { icon, iconName, siteOrigin } = this.props
return ( return (
<div className="permissions-connect-header__icon"> <div className="permissions-connect-header__icon">
<SiteIcon icon={ icon } name={ iconName } size={64} /> <SiteIcon icon={ icon } name={ iconName } size={64} />
<div className="permissions-connect-header__text">{iconName}</div> <div className="permissions-connect-header__text">{siteOrigin}</div>
</div> </div>
) )
} }

@ -46,6 +46,7 @@
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 0;
} }
&__footer { &__footer {

@ -73,7 +73,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
background: black; background: black;
opacity: 20%; opacity: .2;
} }
&-content { &-content {

@ -48,15 +48,17 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => {
// perform substitutions // perform substitutions
if (hasSubstitutions) { if (hasSubstitutions) {
const parts = phrase.split(/(\$\d)/g) const parts = phrase.split(/(\$\d)/g)
const partsToReplace = phrase.match(/(\$\d)/g)
if (partsToReplace.length > substitutions.length) {
throw new Error(`Insufficient number of substitutions for message: '${phrase}'`)
}
const substitutedParts = parts.map((part) => { const substitutedParts = parts.map((part) => {
const subMatch = part.match(/\$(\d)/) const subMatch = part.match(/\$(\d)/)
return subMatch ? substitutions[Number(subMatch[1]) - 1] : part if (!subMatch) {
return part
}
const substituteIndex = Number(subMatch[1]) - 1
if (substitutions[substituteIndex]) {
return substitutions[substituteIndex]
}
throw new Error(`Insufficient number of substitutions for message: '${phrase}'`)
}) })
phrase = hasReactSubstitutions phrase = hasReactSubstitutions
@ -77,3 +79,21 @@ export async function fetchLocale (localeCode) {
} }
} }
const relativeTimeFormatLocaleData = new Set()
export async function loadRelativeTimeFormatLocaleData (localeCode) {
const languageTag = localeCode.split('_')[0]
if (
Intl.RelativeTimeFormat &&
typeof Intl.RelativeTimeFormat.__addLocaleData === 'function' &&
!relativeTimeFormatLocaleData.has(languageTag)
) {
const localeData = await fetchRelativeTimeFormatData(languageTag)
Intl.RelativeTimeFormat.__addLocaleData(localeData)
}
}
async function fetchRelativeTimeFormatData (languageTag) {
const response = await window.fetch(`./intl/${languageTag}/relative-time-format-data.json`)
return await response.json()
}

@ -50,7 +50,7 @@ export function useTransactionTimeRemaining (
const featureFlags = useSelector(getFeatureFlags) const featureFlags = useSelector(getFeatureFlags)
const transactionTimeFeatureActive = featureFlags?.transactionTime const transactionTimeFeatureActive = featureFlags?.transactionTime
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto', style: 'narrow' }) const rtf = new Intl.RelativeTimeFormat(locale.replace('_', '-'), { numeric: 'auto', style: 'narrow' })
// Memoize this value so it can be used as a dependency in the effect below // Memoize this value so it can be used as a dependency in the effect below
const initialTimeEstimate = useMemo(() => { const initialTimeEstimate = useMemo(() => {

@ -25,7 +25,13 @@ export default class ChooseAccount extends Component {
cancelPermissionsRequest: PropTypes.func.isRequired, cancelPermissionsRequest: PropTypes.func.isRequired,
permissionsRequestId: PropTypes.string.isRequired, permissionsRequestId: PropTypes.string.isRequired,
selectedAccountAddresses: PropTypes.object.isRequired, selectedAccountAddresses: PropTypes.object.isRequired,
targetDomainMetadata: PropTypes.object, targetDomainMetadata: PropTypes.shape({
extensionId: PropTypes.string,
icon: PropTypes.string,
host: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
}),
} }
state = { state = {
@ -197,6 +203,7 @@ export default class ChooseAccount extends Component {
? t('selectAccounts') ? t('selectAccounts')
: t('connectAccountOrCreate') : t('connectAccountOrCreate')
} }
siteOrigin={targetDomainMetadata.origin}
/> />
{this.renderAccountsListHeader()} {this.renderAccountsListHeader()}
{this.renderAccountsList()} {this.renderAccountsList()}

@ -31,7 +31,13 @@ export default class PermissionConnect extends Component {
connectPath: PropTypes.string.isRequired, connectPath: PropTypes.string.isRequired,
confirmPermissionPath: PropTypes.string.isRequired, confirmPermissionPath: PropTypes.string.isRequired,
page: PropTypes.string.isRequired, page: PropTypes.string.isRequired,
targetDomainMetadata: PropTypes.object, targetDomainMetadata: PropTypes.shape({
extensionId: PropTypes.string,
icon: PropTypes.string,
host: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
}),
} }
static defaultProps = { static defaultProps = {
@ -95,7 +101,7 @@ export default class PermissionConnect extends Component {
if ( if (
permissionsRequest && permissionsRequest &&
savedMetadata.name !== targetDomainMetadata?.name savedMetadata.origin !== targetDomainMetadata?.origin
) { ) {
return { targetDomainMetadata } return { targetDomainMetadata }
} }

@ -43,13 +43,20 @@ const mapStateToProps = (state, ownProps) => {
const nativeCurrency = getNativeCurrency(state) const nativeCurrency = getNativeCurrency(state)
const domainMetadata = getDomainMetadata(state) const domainMetadata = getDomainMetadata(state)
const targetDomainMetadata = origin
? domainMetadata[origin] || { let targetDomainMetadata = null
origin, if (origin) {
name: (new URL(origin)).hostname, if (domainMetadata[origin]) {
icon: null, targetDomainMetadata = { ...domainMetadata[origin], origin }
} else {
const targetUrl = new URL(origin)
targetDomainMetadata = {
host: targetUrl.host,
name: targetUrl.hostname,
origin,
}
} }
: null }
const accountsWithLabels = getAccountsWithLabels(state) const accountsWithLabels = getAccountsWithLabels(state)

@ -33,5 +33,11 @@ export default function PermissionsRedirect ({ domainMetadata }) {
} }
PermissionsRedirect.propTypes = { PermissionsRedirect.propTypes = {
domainMetadata: PropTypes.object.isRequired, domainMetadata: PropTypes.shape({
extensionId: PropTypes.string,
icon: PropTypes.string,
host: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
}),
} }

@ -4,7 +4,7 @@ import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'
import { checksumAddress } from '../helpers/utils/util' import { checksumAddress } from '../helpers/utils/util'
import { calcTokenBalance, estimateGas } from '../pages/send/send.utils' import { calcTokenBalance, estimateGas } from '../pages/send/send.utils'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import { fetchLocale } from '../helpers/utils/i18n-helper' import { fetchLocale, loadRelativeTimeFormatLocaleData } from '../helpers/utils/i18n-helper'
import { getMethodDataAsync } from '../helpers/utils/transactions.util' import { getMethodDataAsync } from '../helpers/utils/transactions.util'
import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' import { fetchSymbolAndDecimals } from '../helpers/utils/token-util'
import switchDirection from '../helpers/utils/switch-direction' import switchDirection from '../helpers/utils/switch-direction'
@ -1191,8 +1191,8 @@ export function showAccountDetail (address) {
const activeTabOrigin = state.activeTab.origin const activeTabOrigin = state.activeTab.origin
const selectedAddress = getSelectedAddress(state) const selectedAddress = getSelectedAddress(state)
const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state) const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state)
const currentTabIsConnectedToPreviousAddress = permittedAccountsForCurrentTab.includes(selectedAddress) const currentTabIsConnectedToPreviousAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(selectedAddress)
const currentTabIsConnectedToNextAddress = permittedAccountsForCurrentTab.includes(address) const currentTabIsConnectedToNextAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(address)
const switchingToUnconnectedAddress = currentTabIsConnectedToPreviousAddress && !currentTabIsConnectedToNextAddress const switchingToUnconnectedAddress = currentTabIsConnectedToPreviousAddress && !currentTabIsConnectedToNextAddress
try { try {
@ -2012,8 +2012,9 @@ export function setIpfsGateway (val) {
} }
export function updateCurrentLocale (key) { export function updateCurrentLocale (key) {
return (dispatch) => { return async (dispatch) => {
dispatch(showLoadingIndication()) dispatch(showLoadingIndication())
await loadRelativeTimeFormatLocaleData(key)
return fetchLocale(key) return fetchLocale(key)
.then((localeMessages) => { .then((localeMessages) => {
log.debug(`background.setCurrentLocale`) log.debug(`background.setCurrentLocale`)

@ -10,7 +10,7 @@ import txHelper from './lib/tx-helper'
import { getEnvironmentType } from '../app/scripts/lib/util' import { getEnvironmentType } from '../app/scripts/lib/util'
import { ALERT_TYPES } from '../app/scripts/controllers/alert' import { ALERT_TYPES } from '../app/scripts/controllers/alert'
import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums' import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums'
import { fetchLocale } from './app/helpers/utils/i18n-helper' import { fetchLocale, loadRelativeTimeFormatLocaleData } from './app/helpers/utils/i18n-helper'
import switchDirection from './app/helpers/utils/switch-direction' import switchDirection from './app/helpers/utils/switch-direction'
import { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors' import { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors'
import { ALERT_STATE } from './app/ducks/alerts/unconnected-account' import { ALERT_STATE } from './app/ducks/alerts/unconnected-account'
@ -48,6 +48,11 @@ async function startApp (metamaskState, backgroundConnection, opts) {
: {} : {}
const enLocaleMessages = await fetchLocale('en') const enLocaleMessages = await fetchLocale('en')
await loadRelativeTimeFormatLocaleData('en')
if (metamaskState.currentLocale) {
await loadRelativeTimeFormatLocaleData(metamaskState.currentLocale)
}
if (metamaskState.textDirection === 'rtl') { if (metamaskState.textDirection === 'rtl') {
await switchDirection('rtl') await switchDirection('rtl')
} }

@ -1711,10 +1711,10 @@
pump "^3.0.0" pump "^3.0.0"
safe-event-emitter "^1.0.1" safe-event-emitter "^1.0.1"
"@metamask/test-dapp@^2.1.1": "@metamask/test-dapp@^2.2.0":
version "2.1.1" version "2.2.0"
resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-2.1.1.tgz#c3b79f93c8a698b0904171c5143d0bca1307653a" resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-2.2.0.tgz#e48ea589db7ab028ea222ae47ee814c4687e02c6"
integrity sha512-ed0Ma9TLc+wkQYJK5TWslphp58JSi4Rer84LK2RxW1p4aS2LsGKS30pKMFUegj+g9g//7tyh+uFE87pXu4vPkA== integrity sha512-KX8ZhR/yLBO6yzx/9/BDxHdrTV6nNoOb8LvpUGm8GiLu6jOXETKZj0qfgvL5quWnQ/LRJMEXeuOZWjtXgcVofg==
"@mrmlnc/readdir-enhanced@^2.2.1": "@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1" version "2.2.1"
@ -10215,10 +10215,10 @@ eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.6.1:
loglevel "^1.5.0" loglevel "^1.5.0"
obs-store "^4.0.3" obs-store "^4.0.3"
eth-keyring-controller@^6.0.0: eth-keyring-controller@^6.0.1:
version "6.0.0" version "6.0.1"
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.0.0.tgz#4629c7b9f08e9c2f24ecfa0a296fc40ea0fa98af" resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.0.1.tgz#6a4cdd5802b0587320c711be6c1752b2a88221aa"
integrity sha512-+tdXXwTklX0KX50YwlSriTU/6Xc0Ury0jmcp1mMcJfKSBFSKyWCmPmrhdkMxE9LRd4lbt4qx9LS5wZ3Ia05cLg== integrity sha512-60j71F1HgLcvwzg7U5R45bA/kgQSUlmiZrsUIIhW4qS7QOYqJn0OQ64enf0ZaxMMPVVcKSfCDersYJiqm/yrlw==
dependencies: dependencies:
bip39 "^2.4.0" bip39 "^2.4.0"
bluebird "^3.5.0" bluebird "^3.5.0"

Loading…
Cancel
Save