Skip to content

Commit

Permalink
Document wallet_snap (MetaMask#107)
Browse files Browse the repository at this point in the history
* Document wallet_snap

* doc wallet_snap

* fix links

* dapp -> website

* integrate reviewer feedback

* remove wallet_snap_* instances

* minor fix

* reviewer feedback

* Apply suggestions from code review

Co-authored-by: Hassan Malik <[email protected]>

* update wallet_snap

* add return info

* Apply suggestions from code review

Co-authored-by: Byron Gravenorst <[email protected]>

---------

Co-authored-by: Hassan Malik <[email protected]>
Co-authored-by: Byron Gravenorst <[email protected]>
  • Loading branch information
3 people authored Apr 14, 2023
1 parent be50fd4 commit 56f9618
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 43 deletions.
118 changes: 78 additions & 40 deletions snaps/reference/rpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ Some methods are only callable by snaps, and some are only callable by websites.

## Unrestricted methods

You can use unrestricted methods without [requesting permission](../how-to/request-permissions.md)
to do so.
You can call unrestricted methods without requesting permission to do so.

### wallet_getSnaps

Expand All @@ -28,8 +27,9 @@ Each snap is an object containing:
- `id` - The ID of the snap.
- `initialPermissions` - The initial permissions of the snap, which will be requested when the snap
is installed.
- `permissionName` - The name of the permission used to invoke the snap.
- `version` - The version of the snap.
- `enabled` - `true` if the snap is enabled, `false` otherwise.
- `blocked` - `true` if the snap is blocked, `false` otherwise.

#### Example

Expand All @@ -48,18 +48,12 @@ console.log(result);
```javascript
// Example result if any snaps are permitted
{
accountRPC methods?s: ['0xa...', '0xb...'],
permissions: {
eth_accounts: {},
'wallet_snap_npm:@metamask/example-snap': {},
'npm:@metamask/example-snap': {
version: '1.0.0',
id: 'npm:@metamask/example-snap',
enabled: true,
blocked: false,
},
snaps: {
'npm:@metamask/example-snap': {
version: '1.0.0',
permissionName: 'wallet_snap_npm:@metamask/example-snap',
...
}
}
}
```

Expand Down Expand Up @@ -159,13 +153,15 @@ try {
{
'npm:@metamask/example-snap': {
version: '1.0.0',
permissionName: 'wallet_snap_npm:@metamask/example-snap',
...
id: 'npm:@metamask/example-snap',
enabled: true,
blocked: false,
},
'npm:fooSnap': {
version: '1.0.5',
permissionName: 'wallet_snap_npm:fooSnap',
...
id: 'npm:fooSnap',
enabled: true,
blocked: false,
},
}
```
Expand All @@ -174,9 +170,10 @@ try {

## Restricted methods

You must
[request permission](../how-to/request-permissions.md#rpc-api-permissions) in the snap manifest file
to use a restricted method.
For restricted methods callable by snaps, a snap must request permission to call the method in the
[snap manifest file](../how-to/request-permissions.md).
For restricted methods callable by websites, a website must request permission to call the method using
[`wallet_requestPermissions`](../../wallet/reference/rpc-api#wallet_requestpermissions).

### snap_confirm (deprecated)

Expand Down Expand Up @@ -707,49 +704,90 @@ An object containing the contents of the notification:
await snap.request({
method: 'snap_notify',
params: {
type: 'inApp',
message: `Hello, world!`,
type: 'inApp',
message: 'Hello, world!',
},
});
```

### wallet\_snap\_*
### wallet_snap

Invokes the specified JSON-RPC method of the snap corresponding to the specified permission name.
The snap must be installed and the caller must have permission to communicate with the snap, or the
request is rejected.
A website must request the `wallet_snap` permission using
[`wallet_requestPermissions`](../../wallet/reference/rpc-api#wallet_requestpermissions) to
interact with the specified snaps.

Snaps are responsible for implementing their JSON-RPC API.
Consult the snap's documentation for available methods, their parameters, and return values.
A website can also call this method to invoke the specified JSON-RPC method of the specified snap.

This method is only callable by websites.
This method is synonymous to [`wallet_invokeSnap`](#wallet_invokesnap), and is only callable by websites.

:::note
This is a namespaced method.
The `*` in the name is always substituted for a string, in this case a snap ID.
:::

:::tip
[`wallet_invokeSnap`](#wallet_invokesnap) provides a more convenient way of calling this method.
Most websites only make one call to `wallet_requestPermissions`.
Consecutive calls to `wallet_requestPermissions` for the `wallet_snap` permission overwrites a
website's existing permissions to interact with snaps.
To deal with this, you must write custom logic to merge existing snap IDs with new ones you're requesting.
Use [`wallet_getSnaps`](#wallet_getsnaps) to get a list of a website's permitted snaps.
:::

#### Parameters

The JSON-RPC request object to send to the invoked snap.
When requesting this permission, specify a caveat of type `snapIds`.
Specify each snap to request permission to interact with as an entry in the `value` field of the caveat.
Each snap entry can include a `version` to install.
The default is the latest version.

When calling this method, specify an object containing:

- `snapId` - The ID of the snap to invoke.
- `request` - The JSON-RPC request object to send to the invoked snap.

#### Returns

The result of the snap method call.
Result of the snap method call.

#### Example

<!--tabs-->

# wallet_requestPermissions

The following is an example of calling `wallet_requestPermissions` to request the `wallet_snap`
permission:

```javascript
const result = await ethereum.request({
method: 'wallet_snap_npm:@metamask/example-snap',
method: 'wallet_requestPermissions',
params: [{
wallet_snap: {
caveats: [
{
type: 'snapIds',
value: {
'npm:@metamask/example-snap': { version: '1.0.0' },
'npm:@metamask/foo-bar-snap': { version: '1.2.1' },
}
}
]
}
}],
});
```

# wallet_snap

The following is an example of calling `wallet_snap`:

```javascript
const result = await ethereum.request({
method: 'wallet_snap',
params: {
method: 'hello',
snapId: 'npm:@metamask/example-snap',
request: {
method: 'hello',
},
},
});

console.log(result); // In this example, the result is a boolean.
```

<!--/tabs-->
4 changes: 1 addition & 3 deletions wallet/reference/rpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Make sure to handle errors for every call to

MetaMask introduced web3 wallet permissions in [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255).
In this permissions system, each RPC method is restricted or unrestricted.
If a method is restricted, the caller must request permission to call it using
If a method is restricted, a dapp must request permission to call it using
[`wallet_requestPermssions`](#wallet_requestpermissions).
Under the hood, permissions are plain, JSON-compatible objects, with fields that are mostly used
internally by MetaMask.
Expand Down Expand Up @@ -112,8 +112,6 @@ If the caller has no permissions, the array is empty.
### wallet_requestPermissions

Requests [permissions](#restricted-methods) from the user.
Currently only [`eth_accounts`](https://metamask.github.io/api-playground/api-documentation/#eth_accounts)
requires requesting permission.

The request causes a MetaMask popup to appear.
You should only request permissions in response to a direct user action, such as a button click.
Expand Down

0 comments on commit 56f9618

Please sign in to comment.