mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
commit
42dedc799b
12
CHANGELOG.md
12
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
|
||||
|
@ -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__",
|
||||
|
@ -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
|
||||
|
@ -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 })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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",
|
||||
|
@ -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">
|
||||
|
@ -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() }
|
||||
|
@ -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 = {
|
||||
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
|
@ -73,7 +73,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: black;
|
||||
opacity: 20%;
|
||||
opacity: .2;
|
||||
}
|
||||
|
||||
&-content {
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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(() => {
|
||||
|
@ -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()}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
}),
|
||||
}
|
||||
|
@ -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`)
|
||||
|
@ -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')
|
||||
}
|
||||
|
16
yarn.lock
16
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"
|
||||
|
Loading…
Reference in New Issue
Block a user