aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/metamask-controller.js
diff options
context:
space:
mode:
authorkumavis <kumavis@users.noreply.github.com>2019-05-04 01:32:05 +0800
committerFrankie <frankie.diamond@gmail.com>2019-05-04 01:32:05 +0800
commit2845398c3d824e5da1830ba7905ffdbf8149cf9e (patch)
treea95ca83b7cf8ac42cef5ad08d29e8240f8bf1e30 /app/scripts/metamask-controller.js
parent2ff522604b2a5f45697087613de5efb9bba58790 (diff)
downloadtangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.gz
tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.zst
tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.zip
Refactor ProviderApprovalController to use rpc and publicConfigStore (#6410)
* Ensure home screen does not render if there are unapproved txs (#6501) * Ensure that the confirm screen renders before the home screen if there are unapproved txs. * Only render confirm screen before home screen on mount. * inpage - revert _metamask api to isEnabled isApproved isUnlocked
Diffstat (limited to 'app/scripts/metamask-controller.js')
-rw-r--r--app/scripts/metamask-controller.js102
1 files changed, 80 insertions, 22 deletions
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index be2090f63..7d666ae88 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -7,8 +7,10 @@
const EventEmitter = require('events')
const pump = require('pump')
const Dnode = require('dnode')
+const pify = require('pify')
const ObservableStore = require('obs-store')
const ComposableObservableStore = require('./lib/ComposableObservableStore')
+const createDnodeRemoteGetter = require('./lib/createDnodeRemoteGetter')
const asStream = require('obs-store/lib/asStream')
const AccountTracker = require('./lib/account-tracker')
const RpcEngine = require('json-rpc-engine')
@@ -87,7 +89,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.createVaultMutex = new Mutex()
// network store
- this.networkController = new NetworkController(initState.NetworkController, this.platform)
+ this.networkController = new NetworkController(initState.NetworkController)
// preferences controller
this.preferencesController = new PreferencesController({
@@ -235,15 +237,17 @@ module.exports = class MetamaskController extends EventEmitter {
this.messageManager = new MessageManager()
this.personalMessageManager = new PersonalMessageManager()
this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController })
- this.publicConfigStore = this.initPublicConfigStore()
+
+ // ensure isClientOpenAndUnlocked is updated when memState updates
+ this.on('update', (memState) => {
+ this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen
+ })
this.providerApprovalController = new ProviderApprovalController({
closePopup: opts.closePopup,
keyringController: this.keyringController,
openPopup: opts.openPopup,
- platform: opts.platform,
preferencesController: this.preferencesController,
- publicConfigStore: this.publicConfigStore,
})
this.store.updateStructure({
@@ -322,22 +326,32 @@ module.exports = class MetamaskController extends EventEmitter {
* Constructor helper: initialize a public config store.
* This store is used to make some config info available to Dapps synchronously.
*/
- initPublicConfigStore () {
- // get init state
+ createPublicConfigStore ({ checkIsEnabled }) {
+ // subset of state for metamask inpage provider
const publicConfigStore = new ObservableStore()
- // memStore -> transform -> publicConfigStore
- this.on('update', (memState) => {
- this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen
+ // setup memStore subscription hooks
+ this.on('update', updatePublicConfigStore)
+ updatePublicConfigStore(this.getState())
+
+ publicConfigStore.destroy = () => {
+ this.removeEventListener('update', updatePublicConfigStore)
+ }
+
+ function updatePublicConfigStore (memState) {
const publicState = selectPublicState(memState)
publicConfigStore.putState(publicState)
- })
+ }
- function selectPublicState (memState) {
+ function selectPublicState ({ isUnlocked, selectedAddress, network, completedOnboarding }) {
+ const isEnabled = checkIsEnabled()
+ const isReady = isUnlocked && isEnabled
const result = {
- selectedAddress: memState.isUnlocked ? memState.selectedAddress : undefined,
- networkVersion: memState.network,
- onboardingcomplete: memState.completedOnboarding,
+ isUnlocked,
+ isEnabled,
+ selectedAddress: isReady ? selectedAddress : undefined,
+ networkVersion: network,
+ onboardingcomplete: completedOnboarding,
}
return result
}
@@ -477,9 +491,10 @@ module.exports = class MetamaskController extends EventEmitter {
signTypedMessage: nodeify(this.signTypedMessage, this),
cancelTypedMessage: this.cancelTypedMessage.bind(this),
- approveProviderRequest: providerApprovalController.approveProviderRequest.bind(providerApprovalController),
+ // provider approval
+ approveProviderRequestByOrigin: providerApprovalController.approveProviderRequestByOrigin.bind(providerApprovalController),
+ rejectProviderRequestByOrigin: providerApprovalController.rejectProviderRequestByOrigin.bind(providerApprovalController),
clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController),
- rejectProviderRequest: providerApprovalController.rejectProviderRequest.bind(providerApprovalController),
}
}
@@ -1296,8 +1311,9 @@ module.exports = class MetamaskController extends EventEmitter {
// setup multiplexing
const mux = setupMultiplex(connectionStream)
// connect features
- this.setupProviderConnection(mux.createStream('provider'), originDomain)
- this.setupPublicConfig(mux.createStream('publicConfig'))
+ const publicApi = this.setupPublicApi(mux.createStream('publicApi'), originDomain)
+ this.setupProviderConnection(mux.createStream('provider'), originDomain, publicApi)
+ this.setupPublicConfig(mux.createStream('publicConfig'), originDomain)
}
/**
@@ -1370,7 +1386,7 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {*} outStream - The stream to provide over.
* @param {string} origin - The URI of the requesting resource.
*/
- setupProviderConnection (outStream, origin) {
+ setupProviderConnection (outStream, origin, publicApi) {
// setup json rpc engine stack
const engine = new RpcEngine()
const provider = this.provider
@@ -1390,6 +1406,11 @@ module.exports = class MetamaskController extends EventEmitter {
engine.push(subscriptionManager.middleware)
// watch asset
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
+ // requestAccounts
+ engine.push(this.providerApprovalController.createMiddleware({
+ origin,
+ getSiteMetadata: publicApi && publicApi.getSiteMetadata,
+ }))
// forward to metamask primary provider
engine.push(providerAsMiddleware(provider))
@@ -1418,12 +1439,18 @@ module.exports = class MetamaskController extends EventEmitter {
*
* @param {*} outStream - The stream to provide public config over.
*/
- setupPublicConfig (outStream) {
- const configStream = asStream(this.publicConfigStore)
+ setupPublicConfig (outStream, originDomain) {
+ const configStore = this.createPublicConfigStore({
+ // check the providerApprovalController's approvedOrigins
+ checkIsEnabled: () => this.providerApprovalController.shouldExposeAccounts(originDomain),
+ })
+ const configStream = asStream(configStore)
+
pump(
configStream,
outStream,
(err) => {
+ configStore.destroy()
configStream.destroy()
if (err) log.error(err)
}
@@ -1431,6 +1458,38 @@ module.exports = class MetamaskController extends EventEmitter {
}
/**
+ * A method for providing our public api over a stream.
+ * This includes a method for setting site metadata like title and image
+ *
+ * @param {*} outStream - The stream to provide the api over.
+ */
+ setupPublicApi (outStream, originDomain) {
+ const dnode = Dnode()
+ // connect dnode api to remote connection
+ pump(
+ outStream,
+ dnode,
+ outStream,
+ (err) => {
+ // report any error
+ if (err) log.error(err)
+ }
+ )
+
+ const getRemote = createDnodeRemoteGetter(dnode)
+
+ const publicApi = {
+ // wrap with an await remote
+ getSiteMetadata: async () => {
+ const remote = await getRemote()
+ return await pify(remote.getSiteMetadata)()
+ },
+ }
+
+ return publicApi
+ }
+
+ /**
* Handle a KeyringController update
* @param {object} state the KC state
* @return {Promise<void>}
@@ -1734,7 +1793,6 @@ module.exports = class MetamaskController extends EventEmitter {
* Locks MetaMask
*/
setLocked () {
- this.providerApprovalController.setLocked()
return this.keyringController.setLocked()
}
}