diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa6b76751..c80389505 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
## 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
- [#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
diff --git a/app/manifest/_base.json b/app/manifest/_base.json
index 83ad55d90..1d567a273 100644
--- a/app/manifest/_base.json
+++ b/app/manifest/_base.json
@@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
- "version": "8.0.0",
+ "version": "8.0.1",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",
diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js
index 43e13b77a..344f9a972 100644
--- a/app/scripts/controllers/transactions/index.js
+++ b/app/scripts/controllers/transactions/index.js
@@ -443,14 +443,14 @@ export default class TransactionController extends EventEmitter {
const txMeta = this.txStateManager.getTx(txId)
const fromAddress = txMeta.txParams.from
// wait for a nonce
- let { customNonceValue = null } = txMeta
+ let { customNonceValue } = txMeta
customNonceValue = Number(customNonceValue)
nonceLock = await this.nonceTracker.getNonceLock(fromAddress)
// add nonce to txParams
// 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
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))
// add nonce debugging information to txMeta
diff --git a/app/scripts/ui.js b/app/scripts/ui.js
index 5e8cc8e66..822ea73a4 100644
--- a/app/scripts/ui.js
+++ b/app/scripts/ui.js
@@ -83,10 +83,15 @@ async function queryCurrentActiveTab (windowType) {
extension.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const [activeTab] = tabs
- const { title, url } = activeTab
+ const { id, title, url } = activeTab
const { origin, protocol } = url ? new URL(url) : {}
- resolve({ title, origin, protocol, url })
+ if (!origin || origin === 'null') {
+ resolve({})
+ return
+ }
+
+ resolve({ id, title, origin, protocol, url })
})
})
}
diff --git a/development/build/static.js b/development/build/static.js
index de206d1f1..62dbeaa62 100644
--- a/development/build/static.js
+++ b/development/build/static.js
@@ -3,6 +3,8 @@ const path = require('path')
const watch = require('gulp-watch')
const glob = require('fast-glob')
+const locales = require('../../app/_locales/index.json')
+
const { createTask, composeSeries } = require('./task')
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 = [
...copyTargets,
{
diff --git a/package.json b/package.json
index 6e73f61c2..48bf624c7 100644
--- a/package.json
+++ b/package.json
@@ -107,7 +107,7 @@
"eth-json-rpc-filters": "^4.1.1",
"eth-json-rpc-infura": "^4.0.2",
"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-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2",
@@ -189,7 +189,7 @@
"@babel/register": "^7.5.5",
"@metamask/eslint-config": "^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",
"@storybook/addon-actions": "^5.3.14",
"@storybook/addon-backgrounds": "^5.3.14",
diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/app/components/app/menu-bar/menu-bar.js
index 99bc50afa..282307f59 100644
--- a/ui/app/components/app/menu-bar/menu-bar.js
+++ b/ui/app/components/app/menu-bar/menu-bar.js
@@ -26,7 +26,7 @@ export default function MenuBar () {
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false)
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 (
diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js
index 268c973bf..feb6eaa9a 100644
--- a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js
+++ b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js
@@ -7,7 +7,13 @@ import CheckBox from '../../../ui/check-box'
export default class PermissionPageContainerContent extends PureComponent {
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,
onPermissionToggle: PropTypes.func.isRequired,
selectedIdentities: PropTypes.array,
@@ -145,6 +151,7 @@ export default class PermissionPageContainerContent extends PureComponent {
? t('allowExternalExtensionTo', [domainMetadata.extensionId])
: t('allowThisSiteTo')
}
+ siteOrigin={domainMetadata.origin}
/>
{ this.renderRequestedPermissions() }
diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js
index 3020b82b5..0779f2226 100644
--- a/ui/app/components/app/permission-page-container/permission-page-container.component.js
+++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js
@@ -14,7 +14,13 @@ export default class PermissionPageContainer extends Component {
allIdentitiesSelected: PropTypes.bool,
request: 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 = {
diff --git a/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js b/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js
index e32f8a0b1..c1bc5d775 100644
--- a/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js
+++ b/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js
@@ -5,25 +5,25 @@ import SiteIcon from '../../ui/site-icon'
export default class PermissionsConnectHeader extends Component {
static propTypes = {
icon: PropTypes.string,
- iconName: PropTypes.string,
+ iconName: PropTypes.string.isRequired,
+ siteOrigin: PropTypes.string.isRequired,
headerTitle: PropTypes.node,
headerText: PropTypes.string,
}
static defaultProps = {
icon: null,
- iconName: '',
headerTitle: '',
headerText: '',
}
renderHeaderIcon () {
- const { icon, iconName } = this.props
+ const { icon, iconName, siteOrigin } = this.props
return (
-
{iconName}
+
{siteOrigin}
)
}
diff --git a/ui/app/components/ui/page-container/index.scss b/ui/app/components/ui/page-container/index.scss
index 21f6ca0c5..98bbcd9d1 100644
--- a/ui/app/components/ui/page-container/index.scss
+++ b/ui/app/components/ui/page-container/index.scss
@@ -46,6 +46,7 @@
flex: 1;
display: flex;
flex-direction: column;
+ min-height: 0;
}
&__footer {
diff --git a/ui/app/components/ui/popover/index.scss b/ui/app/components/ui/popover/index.scss
index 1742c7754..a34f99e50 100644
--- a/ui/app/components/ui/popover/index.scss
+++ b/ui/app/components/ui/popover/index.scss
@@ -73,7 +73,7 @@
width: 100%;
height: 100%;
background: black;
- opacity: 20%;
+ opacity: .2;
}
&-content {
diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js
index 496bd4524..01a369229 100644
--- a/ui/app/helpers/utils/i18n-helper.js
+++ b/ui/app/helpers/utils/i18n-helper.js
@@ -48,15 +48,17 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => {
// perform substitutions
if (hasSubstitutions) {
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 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
@@ -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()
+}
diff --git a/ui/app/hooks/useTransactionTimeRemaining.js b/ui/app/hooks/useTransactionTimeRemaining.js
index c1d5ddd25..1f959c82f 100644
--- a/ui/app/hooks/useTransactionTimeRemaining.js
+++ b/ui/app/hooks/useTransactionTimeRemaining.js
@@ -50,7 +50,7 @@ export function useTransactionTimeRemaining (
const featureFlags = useSelector(getFeatureFlags)
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
const initialTimeEstimate = useMemo(() => {
diff --git a/ui/app/pages/permissions-connect/choose-account/choose-account.component.js b/ui/app/pages/permissions-connect/choose-account/choose-account.component.js
index 720fd0bb0..606b2ecc9 100644
--- a/ui/app/pages/permissions-connect/choose-account/choose-account.component.js
+++ b/ui/app/pages/permissions-connect/choose-account/choose-account.component.js
@@ -25,7 +25,13 @@ export default class ChooseAccount extends Component {
cancelPermissionsRequest: PropTypes.func.isRequired,
permissionsRequestId: PropTypes.string.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 = {
@@ -197,6 +203,7 @@ export default class ChooseAccount extends Component {
? t('selectAccounts')
: t('connectAccountOrCreate')
}
+ siteOrigin={targetDomainMetadata.origin}
/>
{this.renderAccountsListHeader()}
{this.renderAccountsList()}
diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js
index 068d846dd..4119e04a6 100644
--- a/ui/app/pages/permissions-connect/permissions-connect.component.js
+++ b/ui/app/pages/permissions-connect/permissions-connect.component.js
@@ -31,7 +31,13 @@ export default class PermissionConnect extends Component {
connectPath: PropTypes.string.isRequired,
confirmPermissionPath: 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 = {
@@ -95,7 +101,7 @@ export default class PermissionConnect extends Component {
if (
permissionsRequest &&
- savedMetadata.name !== targetDomainMetadata?.name
+ savedMetadata.origin !== targetDomainMetadata?.origin
) {
return { targetDomainMetadata }
}
diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js
index 31a727cb5..30a76ec55 100644
--- a/ui/app/pages/permissions-connect/permissions-connect.container.js
+++ b/ui/app/pages/permissions-connect/permissions-connect.container.js
@@ -43,13 +43,20 @@ const mapStateToProps = (state, ownProps) => {
const nativeCurrency = getNativeCurrency(state)
const domainMetadata = getDomainMetadata(state)
- const targetDomainMetadata = origin
- ? domainMetadata[origin] || {
- origin,
- name: (new URL(origin)).hostname,
- icon: null,
+
+ let targetDomainMetadata = null
+ if (origin) {
+ if (domainMetadata[origin]) {
+ targetDomainMetadata = { ...domainMetadata[origin], origin }
+ } else {
+ const targetUrl = new URL(origin)
+ targetDomainMetadata = {
+ host: targetUrl.host,
+ name: targetUrl.hostname,
+ origin,
+ }
}
- : null
+ }
const accountsWithLabels = getAccountsWithLabels(state)
diff --git a/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js b/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js
index 3795f348c..ac39de104 100644
--- a/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js
+++ b/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js
@@ -33,5 +33,11 @@ export default function PermissionsRedirect ({ domainMetadata }) {
}
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,
+ }),
}
diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js
index f139d71a0..dd9188687 100644
--- a/ui/app/store/actions.js
+++ b/ui/app/store/actions.js
@@ -4,7 +4,7 @@ import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'
import { checksumAddress } from '../helpers/utils/util'
import { calcTokenBalance, estimateGas } from '../pages/send/send.utils'
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 { fetchSymbolAndDecimals } from '../helpers/utils/token-util'
import switchDirection from '../helpers/utils/switch-direction'
@@ -1191,8 +1191,8 @@ export function showAccountDetail (address) {
const activeTabOrigin = state.activeTab.origin
const selectedAddress = getSelectedAddress(state)
const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state)
- const currentTabIsConnectedToPreviousAddress = permittedAccountsForCurrentTab.includes(selectedAddress)
- const currentTabIsConnectedToNextAddress = permittedAccountsForCurrentTab.includes(address)
+ const currentTabIsConnectedToPreviousAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(selectedAddress)
+ const currentTabIsConnectedToNextAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(address)
const switchingToUnconnectedAddress = currentTabIsConnectedToPreviousAddress && !currentTabIsConnectedToNextAddress
try {
@@ -2012,8 +2012,9 @@ export function setIpfsGateway (val) {
}
export function updateCurrentLocale (key) {
- return (dispatch) => {
+ return async (dispatch) => {
dispatch(showLoadingIndication())
+ await loadRelativeTimeFormatLocaleData(key)
return fetchLocale(key)
.then((localeMessages) => {
log.debug(`background.setCurrentLocale`)
diff --git a/ui/index.js b/ui/index.js
index 8f868f317..44f5fd500 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -10,7 +10,7 @@ import txHelper from './lib/tx-helper'
import { getEnvironmentType } from '../app/scripts/lib/util'
import { ALERT_TYPES } from '../app/scripts/controllers/alert'
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 { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors'
import { ALERT_STATE } from './app/ducks/alerts/unconnected-account'
@@ -48,6 +48,11 @@ async function startApp (metamaskState, backgroundConnection, opts) {
: {}
const enLocaleMessages = await fetchLocale('en')
+ await loadRelativeTimeFormatLocaleData('en')
+ if (metamaskState.currentLocale) {
+ await loadRelativeTimeFormatLocaleData(metamaskState.currentLocale)
+ }
+
if (metamaskState.textDirection === 'rtl') {
await switchDirection('rtl')
}
diff --git a/yarn.lock b/yarn.lock
index bf3cbe901..3220fb053 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1711,10 +1711,10 @@
pump "^3.0.0"
safe-event-emitter "^1.0.1"
-"@metamask/test-dapp@^2.1.1":
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-2.1.1.tgz#c3b79f93c8a698b0904171c5143d0bca1307653a"
- integrity sha512-ed0Ma9TLc+wkQYJK5TWslphp58JSi4Rer84LK2RxW1p4aS2LsGKS30pKMFUegj+g9g//7tyh+uFE87pXu4vPkA==
+"@metamask/test-dapp@^2.2.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-2.2.0.tgz#e48ea589db7ab028ea222ae47ee814c4687e02c6"
+ integrity sha512-KX8ZhR/yLBO6yzx/9/BDxHdrTV6nNoOb8LvpUGm8GiLu6jOXETKZj0qfgvL5quWnQ/LRJMEXeuOZWjtXgcVofg==
"@mrmlnc/readdir-enhanced@^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"
obs-store "^4.0.3"
-eth-keyring-controller@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.0.0.tgz#4629c7b9f08e9c2f24ecfa0a296fc40ea0fa98af"
- integrity sha512-+tdXXwTklX0KX50YwlSriTU/6Xc0Ury0jmcp1mMcJfKSBFSKyWCmPmrhdkMxE9LRd4lbt4qx9LS5wZ3Ia05cLg==
+eth-keyring-controller@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.0.1.tgz#6a4cdd5802b0587320c711be6c1752b2a88221aa"
+ integrity sha512-60j71F1HgLcvwzg7U5R45bA/kgQSUlmiZrsUIIhW4qS7QOYqJn0OQ64enf0ZaxMMPVVcKSfCDersYJiqm/yrlw==
dependencies:
bip39 "^2.4.0"
bluebird "^3.5.0"