diff --git a/CHANGELOG.md b/CHANGELOG.md index 88c299c7d..e3ab9d3b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Current Develop Branch +## 9.0.1 Wed Jan 13 2021 +- [#10169](https://github.com/MetaMask/metamask-extension/pull/10169): Improved detection of contract methods with array parameters +- [#10178](https://github.com/MetaMask/metamask-extension/pull/10178): Only warn of injected web3 usage once per page +- [#10179](https://github.com/MetaMask/metamask-extension/pull/10179): Restore support for @metamask/inpage provider@"< 8.0.0" +- [#10180](https://github.com/MetaMask/metamask-extension/pull/10180): Fix UI crash when domain metadata is missing on public encryption key confirmation page + ## 9.0.0 Fri Jan 8 2021 - [#9156](https://github.com/MetaMask/metamask-extension/pull/9156): Remove window.web3 injection diff --git a/app/manifest/_base.json b/app/manifest/_base.json index 5fef12ea1..6b6a4e2b0 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -78,6 +78,6 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "9.0.0", + "version": "9.0.1", "web_accessible_resources": ["inpage.js", "phishing.html"] } diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 7e55faec4..116cad02d 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -4,6 +4,7 @@ import LocalMessageDuplexStream from 'post-message-stream' import ObjectMultiplex from 'obj-multiplex' import extension from 'extensionizer' import PortStream from 'extension-port-stream' +import { obj as createThoughStream } from 'through2' // These require calls need to use require to be statically recognized by browserify const fs = require('fs') @@ -20,6 +21,12 @@ const CONTENT_SCRIPT = 'metamask-contentscript' const INPAGE = 'metamask-inpage' const PROVIDER = 'metamask-provider' +// TODO:LegacyProvider: Delete +const LEGACY_CONTENT_SCRIPT = 'contentscript' +const LEGACY_INPAGE = 'inpage' +const LEGACY_PROVIDER = 'provider' +const LEGACY_PUBLIC_CONFIG = 'publicConfig' + if (shouldInjectProvider()) { injectScript(inpageBundle) setupStreams() @@ -63,6 +70,7 @@ async function setupStreams() { pageMux.setMaxListeners(25) const extensionMux = new ObjectMultiplex() extensionMux.setMaxListeners(25) + extensionMux.ignoreStream(LEGACY_PUBLIC_CONFIG) // TODO:LegacyProvider: Delete pump(pageMux, pageStream, pageMux, (err) => logStreamDisconnectWarning('MetaMask Inpage Multiplex', err), @@ -78,6 +86,44 @@ async function setupStreams() { // connect "phishing" channel to warning system const phishingStream = extensionMux.createStream('phishing') phishingStream.once('data', redirectToPhishingWarning) + + // TODO:LegacyProvider: Delete + // handle legacy provider + const legacyPageStream = new LocalMessageDuplexStream({ + name: LEGACY_CONTENT_SCRIPT, + target: LEGACY_INPAGE, + }) + + const legacyPageMux = new ObjectMultiplex() + legacyPageMux.setMaxListeners(25) + const legacyExtensionMux = new ObjectMultiplex() + legacyExtensionMux.setMaxListeners(25) + + pump(legacyPageMux, legacyPageStream, legacyPageMux, (err) => + logStreamDisconnectWarning('MetaMask Legacy Inpage Multiplex', err), + ) + pump( + legacyExtensionMux, + extensionStream, + getNotificationTransformStream(), + legacyExtensionMux, + (err) => { + logStreamDisconnectWarning('MetaMask Background Legacy Multiplex', err) + notifyInpageOfStreamFailure() + }, + ) + + forwardNamedTrafficBetweenMuxes( + LEGACY_PROVIDER, + PROVIDER, + legacyPageMux, + legacyExtensionMux, + ) + forwardTrafficBetweenMuxes( + LEGACY_PUBLIC_CONFIG, + legacyPageMux, + legacyExtensionMux, + ) } function forwardTrafficBetweenMuxes(channelName, muxA, muxB) { @@ -91,6 +137,37 @@ function forwardTrafficBetweenMuxes(channelName, muxA, muxB) { ) } +// TODO:LegacyProvider: Delete +function forwardNamedTrafficBetweenMuxes( + channelAName, + channelBName, + muxA, + muxB, +) { + const channelA = muxA.createStream(channelAName) + const channelB = muxB.createStream(channelBName) + pump(channelA, channelB, channelA, (error) => + console.debug( + `MetaMask: Muxed traffic between channels "${channelAName}" and "${channelBName}" failed.`, + error, + ), + ) +} + +// TODO:LegacyProvider: Delete +function getNotificationTransformStream() { + return createThoughStream((chunk, _, cb) => { + if (chunk?.name === PROVIDER) { + if (chunk.data?.method === 'metamask_accountsChanged') { + chunk.data.method = 'wallet_accountsChanged' + chunk.data.result = chunk.data.params + delete chunk.data.params + } + } + cb(null, chunk) + }) +} + /** * Error handler for page to extension stream disconnections * diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0608ac2b8..2e76464aa 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,6 +1,8 @@ import EventEmitter from 'events' import pump from 'pump' import Dnode from 'dnode' +import { ObservableStore } from '@metamask/obs-store' +import { storeAsStream } from '@metamask/obs-store/dist/asStream' import { JsonRpcEngine } from 'json-rpc-engine' import { debounce } from 'lodash' import createEngineStream from 'json-rpc-middleware-stream/engineStream' @@ -413,6 +415,9 @@ export default class MetamaskController extends EventEmitter { ) { this.submitPassword(password) } + + // TODO:LegacyProvider: Delete + this.publicConfigStore = this.createPublicConfigStore() } /** @@ -459,6 +464,38 @@ export default class MetamaskController extends EventEmitter { return providerProxy } + /** + * TODO:LegacyProvider: Delete + * Constructor helper: initialize a public config store. + * This store is used to make some config info available to Dapps synchronously. + */ + createPublicConfigStore() { + // subset of state for metamask inpage provider + const publicConfigStore = new ObservableStore() + const { networkController } = this + + // setup memStore subscription hooks + this.on('update', updatePublicConfigStore) + updatePublicConfigStore(this.getState()) + + function updatePublicConfigStore(memState) { + const chainId = networkController.getCurrentChainId() + if (memState.network !== 'loading') { + publicConfigStore.putState(selectPublicState(chainId, memState)) + } + } + + function selectPublicState(chainId, { isUnlocked, network }) { + return { + isUnlocked, + chainId, + networkVersion: network, + } + } + + return publicConfigStore + } + /** * Gets relevant state for the provider of an external origin. * @@ -1831,6 +1868,10 @@ export default class MetamaskController extends EventEmitter { // messages between inpage and background this.setupProviderConnection(mux.createStream('metamask-provider'), sender) + + // TODO:LegacyProvider: Delete + // legacy streams + this.setupPublicConfig(mux.createStream('publicConfig')) } /** @@ -2016,6 +2057,28 @@ export default class MetamaskController extends EventEmitter { return engine } + /** + * TODO:LegacyProvider: Delete + * A method for providing our public config info over a stream. + * This includes info we like to be synchronous if possible, like + * the current selected account, and network ID. + * + * Since synchronous methods have been deprecated in web3, + * this is a good candidate for deprecation. + * + * @param {*} outStream - The stream to provide public config over. + */ + setupPublicConfig(outStream) { + const configStream = storeAsStream(this.publicConfigStore) + + pump(configStream, outStream, (err) => { + configStream.destroy() + if (err) { + log.error(err) + } + }) + } + /** * Adds a reference to a connection by origin. Ignores the 'metamask' origin. * Caller must ensure that the returned id is stored such that the reference diff --git a/package.json b/package.json index 312789a00..ba59f09d3 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@metamask/eth-ledger-bridge-keyring": "^0.2.6", "@metamask/eth-token-tracker": "^3.0.1", "@metamask/etherscan-link": "^1.4.0", - "@metamask/inpage-provider": "^8.0.1", + "@metamask/inpage-provider": "^8.0.2", "@metamask/jazzicon": "^2.0.0", "@metamask/logo": "^2.5.0", "@metamask/obs-store": "^5.0.0", @@ -110,7 +110,7 @@ "eth-json-rpc-infura": "^5.1.0", "eth-json-rpc-middleware": "^6.0.0", "eth-keyring-controller": "^6.1.0", - "eth-method-registry": "^1.2.0", + "eth-method-registry": "^2.0.0", "eth-phishing-detect": "^1.1.14", "eth-query": "^2.1.2", "eth-sig-util": "^3.0.0", diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index 6dda958cc..bcafae970 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -1,4 +1,4 @@ -import MethodRegistry from 'eth-method-registry' +import { MethodRegistry } from 'eth-method-registry' import abi from 'human-standard-token-abi' import { ethers } from 'ethers' import log from 'loglevel' diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js index 08a3cbf95..c3d1dfaa2 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js @@ -158,23 +158,24 @@ export default class ConfirmEncryptionPublicKey extends Component { const { domainMetadata, txData } = this.props const { t } = this.context - const origin = domainMetadata[txData.origin] - const notice = t('encryptionPublicKeyNotice', [origin.name]) + const originMetadata = domainMetadata[txData.origin] + const notice = t('encryptionPublicKeyNotice', [txData.origin]) + const name = originMetadata?.name || txData.origin return (
{this.renderAccountInfo()}
- {origin.icon ? ( + {originMetadata?.icon ? ( ) : ( - {origin.name.charAt(0).toUpperCase()} + {name.charAt(0).toUpperCase()} )}
diff --git a/yarn.lock b/yarn.lock index 56428f975..126c52d11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2114,18 +2114,18 @@ resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd" integrity sha512-Hggj4y0QIjDzKGTXzarhEPIQyFSB2bi2y6YLJNwaT4JmP30UB5Cj6gqoY0M4pj3QT57fzp0BUuGp7F/AUe28tw== -"@metamask/inpage-provider@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@metamask/inpage-provider/-/inpage-provider-8.0.1.tgz#67b1f0733ae7c0e0e429dc5c067ba9d2dd6d66da" - integrity sha512-dN3IpiJtaHeiPzF01UXnrQ6TxXbXbkU54kiOHuIUe9e8s7vyPzgDgN2nj84xjmIkqxL0MKY90Wcp0obFKnNj+Q== +"@metamask/inpage-provider@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@metamask/inpage-provider/-/inpage-provider-8.0.2.tgz#50e7559a3ab729e46c5f1e92baa3a3465617c10e" + integrity sha512-LG4wqf7LKwv9akI38HR25Mt/9+YD+DOtbZZKZSG8zUx3hI8moIKxbSwS64pqEyARmLhLKXYkZNROkPjxqbvTdA== dependencies: + "@metamask/object-multiplex" "^1.1.0" "@metamask/safe-event-emitter" "^2.0.0" eth-rpc-errors "^4.0.2" fast-deep-equal "^2.0.1" is-stream "^2.0.0" json-rpc-engine "^6.1.0" - json-rpc-middleware-stream "^2.1.1" - obj-multiplex "^1.0.0" + json-rpc-middleware-stream "^3.0.0" pump "^3.0.0" "@metamask/jazzicon@^2.0.0": @@ -2144,6 +2144,15 @@ gl-mat4 "1.1.4" gl-vec3 "1.0.3" +"@metamask/object-multiplex@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@metamask/object-multiplex/-/object-multiplex-1.1.0.tgz#6b1507c4d10caafd2ea82dd2a5360b91631e036e" + integrity sha512-ImDw5+NdO5qnzmK/rpSlPmQMQm6HIC6wAHdR9nBaDK8TpeuRik5H8DCUcoNrxSeUAk1iHwchZ03lpZu6mZfrdw== + dependencies: + end-of-stream "^1.4.4" + once "^1.4.0" + readable-stream "^2.3.3" + "@metamask/obs-store@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@metamask/obs-store/-/obs-store-5.0.0.tgz#cf2213874c62186a8a4c80f0c402af62a0a877a9" @@ -9858,12 +9867,12 @@ eth-method-registry@1.1.0: dependencies: ethjs "^0.3.0" -eth-method-registry@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eth-method-registry/-/eth-method-registry-1.2.0.tgz#2160592d7938ef0b850c9267bc40b3470c2700c9" - integrity sha512-m+nphH4kOxz5KTvQ+BeIKVggxAul1sp4Ev09lfxRXIEHM1t/6NQEtaErL5ddTDFXXFVtTiW8uC9edTVUTnBZNg== +eth-method-registry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eth-method-registry/-/eth-method-registry-2.0.0.tgz#96b643891d1c72853e709e3d74d89103a48a4460" + integrity sha512-uzwguuAdnd83SjogNo0xMd7pSuyK1dlyAeVGB++OaY7xaprT+31jXkBGYSIkmTz7sGIVf6A1Qy9Ir+/hXs4jWg== dependencies: - ethjs "^0.3.0" + ethjs "^0.4.0" eth-phishing-detect@^1.1.13, eth-phishing-detect@^1.1.14: version "1.1.14" @@ -15234,6 +15243,14 @@ json-rpc-middleware-stream@^2.1.1: readable-stream "^2.3.3" safe-event-emitter "^1.0.1" +json-rpc-middleware-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-middleware-stream/-/json-rpc-middleware-stream-3.0.0.tgz#8540331d884f36b9e0ad31054cc68ac6b5a89b52" + integrity sha512-JmZmlehE0xF3swwORpLHny/GvW3MZxCsb2uFNBrn8TOqMqivzCfz232NSDLLOtIQlrPlgyEjiYpyzyOPFOzClw== + dependencies: + "@metamask/safe-event-emitter" "^2.0.0" + readable-stream "^2.3.3" + json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8"