-
-
Notifications
You must be signed in to change notification settings - Fork 57
Breaking Change Tracker
This page documents how to migrate your code when we introduce breaking changes. We try to do this as little as possible, but given that we're still in early beta, breaking changes may be introduced at any time.
Each Migration has a Summary, listing the relevant changes in bullets. If a bullet is marked [REQUIRED], your Snaps and/or Snap-enabled dapps will break unless you make the suggested change.
Please keep in mind that, at this early stage, it is too costly to thoroughly QA all changes to metamask-snaps-beta#develop
. Consequently, we may introduce inadvertent breaking changes. Therefore, we recommend clearing your plugin and permissions state in the Snaps beta extension before rebuilding with the latest develop
. Please reach out if you have any questions or concerns.
- Pull Request or Commit
-
[REQUIRED] In order to reinstall Snaps, you have to remove them first.
- We recommend using the
Delete All Plugins
button in the main extension view. Specific Snaps can also be deleted by deselecting them in the Snaps settings page and clickingUpdate
. - Snaps are still installed using
wallet_enable
orwallet_installPlugins
. - In the future, we may add a way for installed/running Snaps to be reinstalled via RPC requests and user confirmation. At the very least, we will add a way for dapps/other Snaps (collectively called external domains) to require specific Snap versions.
- We recommend using the
- You may notice performance improvements with this update, and there may be less of a need to refresh the MetaMask extension in
chrome://extensions
after removing Snaps.
- Pull Request or Commit
-
[REQUIRED] When connecting your dapp to MetaMask, replace all references to
wallet_requestPermissions
withwallet_enable
.- You can leave the parameters to
wallet-enable
as-is, but you can also replacewallet_plugin_pluginName
-like keys with{ wallet_plugin: { [pluginName]: {} }
.
- You can leave the parameters to
- When calling a plugin RPC method, you should use the new
wallet_invokePlugin
method. For example:- Instead of
ethereum.send('wallet_plugin_pluginName', [params])
, doethereum.send('wallet_invokePlugin, [pluginName, params]
.
- Instead of
- With the above two changes, you don't have prefix your plugin identifiers with
wallet_plugin_
, which we think is much better!
All examples in snaps-cli
have been updated to use the new required and preferred APIs.
Previously, Snaps were installed by adding their permissions to wallet_requestPermissions
requests. This created messy methods and workflows in our backend, and made it difficult for API consumers to know whether plugin installation succeeded.
To solve this problem, Snap installation has been broken out into its own RPC method, wallet_installPlugins
. In addition, we've added some syntactic sugar so that dapps don't need to concatenate strings in order to request plugins:
interface IRequestedPlugins {
[ pluginId: string ]: {},
}
Here, pluginId
is just the plugin origin string (we'll figure out a better solution for that at some point in the future). Pair this with:
interface IRequestedPermissions {
[ permissionName: string ]: {},
wallet_plugin?: IRequestedPlugins
}
interface IResolvedPlugins {
permission?: string, // the name of the corresponding permission
error?: Error, // if installation fails, the associated error
}
ethereum.send('wallet_requestPermissions',[ IRequestedPermissions ]) => IOcapLdCapability[] // an array of permission objects
ethereum.send('wallet_installPlugins',[ IRequestedPlugins ]) => IResolvedPlugins
wallet_plugin
is the key in the permissions request object where you put the plugin names. Consider this example:
await ethereum.send('wallet_requestPermissions', [{
wallet_plugin: { 'http://localhost:8084/package.json': {} },
eth_accounts: {}
}])
await ethereum.send('wallet_installPlugins', [{
'http://localhost:8084/package.json': {},
}])
Now, to avoid having to make two requests just to connect your dapp, we introduce the wallet_enable
method:
ethereum.send('wallet_enable', [ IRequestedPermissions ]) => {
accounts: Array<string>,
plugins: IResolvedPlugins,
permissions: Array<IOcapLdCapability>
}
To rewrite our example above:
await ethereum.send('wallet_enable', [{
wallet_plugin: { 'http://localhost:8084/package.json': {} },
eth_accounts: {}
}])
So, what exactly does this do? In detail, wallet_enable
:
-
1. Unwraps the
wallet_plugin
syntactic sugar into actual permissions - 2. Makes the permissions request
- 3. Attempts to install any requested plugins
-
4. Returns the
wallet_enable
return object, with information about permissions, plugins, and accounts- If errors were encountered installing a specific plugin, its object (keyed by its name) will include an
error
property. - If the permission request fails completely, the entire request fails.
- If errors were encountered installing a specific plugin, its object (keyed by its name) will include an
To migrate, all you have to do is request wallet_enable
instead of wallet_requestPermissions
when your plugin-enabled dapp connects to MetaMask. You don't even have to change the params, because we still allow the wallet_plugin_
-prefixed permission names to identify plugin for permissions and installation. However, you have to use either the wallet_plugin: { ... }
sugar or wallet_plugin_
-prefixed keys; using both in the same request will throw an error.
Finally, we introduce one more new RPC method:
ethereum.send('wallet_invokePlugin', [ pluginName: string, pluginMethodParams: any ]) => any
Rather than making RPC requests to plugins by send a request for a method like wallet_plugin_pluginName
, we expose an RPC method wallet_invokePlugin
that takes the pluginName
as a param. For example, in hello-snaps
, instead of:
ethereum.send({
method: 'wallet_plugin_http://localhost:8081',
params: [{
method: 'hello'
}]
})
Do this:
ethereum.send(
'wallet_invokePlugin',
[
'http://localhost:8081',
{ method: 'hello', params: [] }, // params could be omitted here
],
)
In this way, you don't have to concatenate strings with wallet_plugin_
to talk to your plugins. We think this is much better, and hope you will too!