Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Commit

Permalink
Add account types (#167)
Browse files Browse the repository at this point in the history
* Add account types

Introduces a concept of "account types" to the AccountsController.

When requesting the permission to `wallet_manageIdentities` (now known
as `wallet_manageAccounts_*`, where `*` is an account type identifier
string. Currently this string is `bip44:60` for
Ethereum, with the intention of rendering any bip44 protocol's name
given the second segment's identifier.

Also introduces `wallet_accounts_*`, where `*` is again an account type
identifier. This method is meant to so that `eth_accounts` can be an
alias for `wallet_accounts_bip44:60`, except that it also supports
paramters.

If any parameters are present in a call to `wallet_accounts_*`, then
those parameters will be passed to the handler for the account defined
by the `from` value on its `AccountMessageHandler` function, allowing
account type snaps to define their own interfaces, and the accounts
permission to allow passing through messages related to the permitted
accounts.

Will benefit from a number of improvements:
- [ ] Rendering protocol names from slip44 identifier.
- [ ] Allow selecting accounts of non-eth protocols.
- [ ] Redirect `eth_accounts` at `wallet_accounts_*`.
- [ ] See if we can redirect all classic eth signing methods through
this new general purpose send method (allows keyrings to iterate faster
than the keyring-controller).

* Linted

* Fix slip44

* Linted

* Linted

* Linted

* Fix bugs, make service registration use protocol name
  • Loading branch information
danfinlay authored Sep 21, 2020
1 parent 404b516 commit c3d798a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
18 changes: 15 additions & 3 deletions app/scripts/controllers/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ class AccountsController extends EventEmitter {
})
}

// This is really more of a "get ether addresses" method,
// the naming is legacy compatability with `eth-keyring-controller`.
async getAccounts () {
const keyAccounts = await this.keyringController.getAccounts()
const pluginAccounts = await this.getPluginAccounts()
const pluginAccounts = await this.getEtherPluginAccounts()
return [...keyAccounts, ...pluginAccounts]
}

async getPluginAccounts () {
return this.pluginAccounts.resources.map(acct => acct.address)
async getEtherPluginAccounts () {
return this.pluginAccounts.resources
.filter(acct => acct.type === 'Ether')
.map(acct => acct.address)
}

async exportAccount (address) {
Expand Down Expand Up @@ -86,6 +90,14 @@ class AccountsController extends EventEmitter {
}
}

async sendMessage (opts) {
if (!opts.from) {
throw new Error('From is a required field.')
}
const handler = this.getHandlerForAccount(opts.from)
return handler(opts)
}

async fullUpdate () {
const update = await this.keyringController.fullUpdate()
const pluginAccounts = this.pluginAccounts.resources
Expand Down
37 changes: 34 additions & 3 deletions app/scripts/controllers/permissions/restrictedMethods.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ function getExternalRestrictedMethods (permissionsController, addPrompt) {
method: (_, res, __, end) => {
permissionsController.accountsController.getAccounts()
.then((accounts) => {
res.result = accounts
res.result = accounts.filter((account) => {
return account.type === 'Ether'
})
end()
})
.catch((reason) => {
Expand All @@ -92,13 +94,42 @@ function getExternalRestrictedMethods (permissionsController, addPrompt) {
},
},

'wallet_manageIdentities': {
description: 'Provide accounts to your wallet and be responsible for their security.',
'wallet_manageAccounts_*': {
description: 'Provide accounts of type "$1" to your wallet and be responsible for their security.',
method: (req, res, _next, end, engine) => {
const methodSegments = req.method.split('_')
const accountTypeCode = methodSegments[methodSegments.length - 1]
req.params[1].type = accountTypeCode
// TODO: Enforce that snaps can only manage their own accounts.
pluginAccountsController.handleRpcRequest(req, res, _next, end, engine)
},
},

'wallet_accounts_*': {
description: 'View all accounts of type "$1" and suggest interactions related to them.',
method: async (req, res, _next, end) => {
const methodSegments = req.method.split('_')
const accountTypeCode = methodSegments[methodSegments.length - 1]
req.params[1].type = accountTypeCode

// if no params, get accounts
if (!req.params) {
// TODO: Add account selector dialog here.
res.result = pluginAccountsController.resources.filter(acct => acct.type === accountTypeCode)
end()
} else {

try {
res.result = await permissionsController.accountsController.sendMessage(req.params)
} catch (err) {
res.error = err
end(res.error)
}

}
},
},

'alert': {
description: 'Show alerts over the current page.',
method: (req, res, _next, end, engine) => {
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.keyringController.memStore.subscribe((s) => this._onKeyringControllerUpdate(s))

this.pluginAccountsController = new ResourceController({
requiredFields: ['address'],
requiredFields: ['address', 'type'],
storageKey: RESOURCE_KEYS.PLUGIN_ACCOUNTS,
})

Expand Down Expand Up @@ -432,7 +432,7 @@ module.exports = class MetamaskController extends EventEmitter {
) {
const permittedAccounts = await this.permissionsController.getAccounts(origin)
// TODO: figure out plugin account permissions
const pluginAccounts = await this.accountsController.getPluginAccounts()
const pluginAccounts = await this.accountsController.getEtherPluginAccounts()
return [ ...permittedAccounts, ...pluginAccounts ]
}
return [] // changing this is a breaking change
Expand Down

0 comments on commit c3d798a

Please sign in to comment.