1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 19:26:13 +02:00

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

Version v8.0.1
This commit is contained in:
Mark Stacey 2020-07-02 23:04:52 -03:00 committed by GitHub
commit 42dedc799b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 144 additions and 45 deletions

View File

@ -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

View File

@ -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__",

View File

@ -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

View File

@ -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 })
})
})
}

View File

@ -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,
{

View File

@ -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",

View File

@ -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 (
<div className="menu-bar">

View File

@ -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}
/>
<section className="permission-approval-container__permissions-container">
{ this.renderRequestedPermissions() }

View File

@ -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 = {

View File

@ -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 (
<div className="permissions-connect-header__icon">
<SiteIcon icon={ icon } name={ iconName } size={64} />
<div className="permissions-connect-header__text">{iconName}</div>
<div className="permissions-connect-header__text">{siteOrigin}</div>
</div>
)
}

View File

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

View File

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

View File

@ -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()
}

View File

@ -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(() => {

View File

@ -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()}

View File

@ -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 }
}

View File

@ -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)

View File

@ -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,
}),
}

View File

@ -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`)

View File

@ -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')
}

View File

@ -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"