Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Snaps dialogs and home pages #1302

Merged
merged 2 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ of the [MetaMask developer page](https://metamask.io/developer/).

## May 2024

- Documented [Snaps home pages](/snaps/features/custom-ui/home-pages).
([#1302](https://github.com/MetaMask/metamask-docs/pull/1302))
- Documented [Snaps dialogs](/snaps/features/custom-ui/dialogs).
([#1302](https://github.com/MetaMask/metamask-docs/pull/1302))
- Documented [Snaps network access](/snaps/features/network-access).
([#1301](https://github.com/MetaMask/metamask-docs/pull/1301))
- Documented [provider API methods for removing event listeners](/wallet/reference/provider-api/#remove-event-listeners).
Expand Down
Binary file added snaps/assets/alert-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snaps/assets/confirmation-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snaps/assets/home-page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snaps/assets/prompt-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 124 additions & 0 deletions snaps/features/custom-ui/dialogs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
description: Display custom alert, confirmation, or prompt screens in MetaMask.
sidebar_position: 2
---

# Dialogs

You can display a dialog in the MetaMask UI using the
[`snap_dialog`](../../reference/snaps-api.md#snap_dialog) API method.
Dialogs can contain [custom UI](index.md) and [interactive UI](interactive-ui.md) components.

There are three types of dialogs: [alerts](#display-an-alert-dialog),
alexandratran marked this conversation as resolved.
Show resolved Hide resolved
[confirmations](#display-a-confirmation-dialog), and [prompts](#display-a-prompt-dialog).

:::caution
Dialogs do not work when MetaMask is locked.
To check if MetaMask is locked, use
[`snap_getClientStatus`](../../reference/snaps-api.md#snap_getclientstatus).
:::

## Request permission to display dialogs

To display dialogs, first request the [`snap_dialog`](../../reference/snaps-api.md#snap_dialog) permission.
Add the following to your Snap's manifest file:

```json title="snap.manifest.json"
"initialPermissions": {
"snap_dialog": {}
}
```

## Display an alert dialog

To display an alert that can only be acknowledged, call
[`snap_dialog`](../../reference/snaps-api.md#snap_dialog) with `type: "alert"`.
The following example displays custom UI that alerts the user when something happens in the system:

```javascript title="index.js"
import { panel, text, heading } from "@metamask/snaps-sdk";

await snap.request({
method: "snap_dialog",
params: {
type: "alert",
content: panel([
heading("Something happened in the system"),
text("The thing that happened is..."),
]),
},
});

// Code that should execute after the alert has been acknowledged.
```

<p align="center">
<img src={require("../../assets/alert-dialog.png").default} alt="Alert dialog example" width="360px" style={{border: "1px solid #DCDCDC"}} />
</p>

## Display a confirmation dialog

To display a confirmation that can be accepted or rejected, call
[`snap_dialog`](../../reference/snaps-api.md#snap_dialog) with `type: "confirmation"`.
The following example displays custom UI that asks the user to confirm whether they would like to
take an action:

```javascript title="index.js"
import { panel, text, heading } from "@metamask/snaps-sdk";

const result = await snap.request({
method: "snap_dialog",
params: {
type: "confirmation",
content: panel([
heading("Would you like to take the action?"),
text("The action is..."),
]),
},
});

if (result === true) {
// Do the action.
}
```

<p align="center">
<img src={require("../../assets/confirmation-dialog.png").default} alt="Confirmation dialog example" width="360px" style={{border: "1px solid #DCDCDC"}} />
</p>

## Display a prompt dialog

To display a prompt where the user can enter a text response, call
[`snap_dialog`](../../reference/snaps-api.md#snap_dialog) with `type: "prompt"`.
Prompt dialogs also accept a `placeholder` value that displays in the input field when no text is entered.

The following example displays custom UI that prompts the user to enter a wallet address:

```javascript title="index.js"
import { panel, text, heading } from "@metamask/snaps-sdk";

const walletAddress = await snap.request({
method: "snap_dialog",
params: {
type: "prompt",
content: panel([
heading("What is the wallet address?"),
text("Please enter the wallet address to be monitored"),
]),
placeholder: "0x123...",
},
});

// walletAddress will be a string containing the address entered by the user.
```

<p align="center">
<img src={require("../../assets/prompt-dialog.png").default} alt="Prompt dialog example" width="360px" style={{border: "1px solid #DCDCDC"}} />
</p>

## Example

See the [`@metamask/dialog-example-snap`](https://github.com/MetaMask/snaps/tree/main/packages/examples/packages/dialogs)
package for a full example of implementing dialogs.
This example exposes a [custom JSON-RPC API](../../learn/about-snaps/apis.md#custom-json-rpc-apis)
for dapps to display dialogs.
56 changes: 56 additions & 0 deletions snaps/features/custom-ui/home-pages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
description: Display a dedicated UI page in MetaMask for your Snap.
sidebar_position: 3
---

# Home pages

You can display a dedicated UI, or "home page," for your Snap within MetaMask.
This is useful for introducing your Snap to end users.
Users can access your home page through the Snaps menu in MetaMask.
Snap home pages can contain [custom UI](index.md) and [interactive UI](interactive-ui.md)
components.

## Steps

### 1. Request permission to display a home page

Request the [`endowment:page-home`](../../reference/permissions.md#endowmentpage-home) permission.
Add the following to your Snap's manifest file:

```json title="snap.manifest.json"
"initialPermissions": {
"endowment:page-home": {}
}
```

### 2. Create a home page

Expose an [`onHomePage`](../../reference/entry-points.md#onhomepage) entry point, which returns the
custom or interactive UI to be shown.
MetaMask calls this method when a user selects your Snap name in the Snaps menu.

The following example displays custom UI that welcomes the user to the Snap's home page:

```typescript title="index.ts"
import type { OnHomePageHandler } from "@metamask/snaps-sdk";
import { panel, text, heading } from "@metamask/snaps-sdk";

export const onHomePage: OnHomePageHandler = async () => {
return {
content: panel([
heading("Hello world!"),
text("Welcome to my Snap home page!"),
]),
};
};
```

<p align="center">
<img src={require("../../assets/home-page.png").default} alt="Home page example" width="360px" style={{border: "1px solid #DCDCDC"}} />
</p>

## Example

See the [`@metamask/home-page-example-snap`](https://github.com/MetaMask/snaps/tree/main/packages/examples/packages/home-page)
package for a full example of implementing a Snap home page.
11 changes: 6 additions & 5 deletions snaps/features/custom-ui/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ sidebar_position: 4
# Custom UI

You can display custom user interface (UI) components using the
[`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) module with
the following methods and entry points:
[`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) module when
implementing the following features:

- [`snap_dialog`](../../reference/snaps-api.md#snap_dialog)
- [`onTransaction`](../../reference/entry-points.md#ontransaction)
- [`onHomePage`](../../reference/entry-points.md#onhomepage)
- [Dialogs](dialogs.md)
- [Home pages](home-pages.md)
- [Transaction insights](../../reference/entry-points.md#ontransaction)
- [Signature insights](../signature-insights.md)

To use custom UI, first install [`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk)
using the following command:
Expand Down
5 changes: 2 additions & 3 deletions snaps/features/custom-ui/interactive-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ sidebar_position: 1

You can display interactive user interface (UI) components.
Interactive UI is an extension of [custom UI](index.md).
It allows interfaces returned from [`snap_dialog`](../../reference/snaps-api.md#snap_dialog),
[`onTransaction`](../../reference/entry-points.md#ontransaction), and
[`onHomePage`](../../reference/entry-points.md#onhomepage) to respond to user input.
It allows interfaces returned from [dialogs](dialogs.md), [home pages](home-pages.md), and
[transaction insights](../../reference/entry-points.md#ontransaction) to respond to user input.

The following interactive UI components are available:

Expand Down
11 changes: 5 additions & 6 deletions snaps/features/data-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ However, this data can be shared across multiple dapps.
Do not assume that the data a Snap stores is unique to a single dapp unless it is specifically designed to be that way.
:::

## Steps
## Request permission to store data

### 1. Get permission to store data

Request the [`snap_manageState`](../reference/snaps-api.md#snap_managestate) permission.
To store data within a Snap, first request the
[`snap_manageState`](../reference/snaps-api.md#snap_managestate) permission.
Add the following to your Snap's manifest file:

```json title="snap.manifest.json"
Expand All @@ -31,7 +30,7 @@ Add the following to your Snap's manifest file:
}
```

### 2. Use encrypted storage
## Use encrypted storage
alexandratran marked this conversation as resolved.
Show resolved Hide resolved

By default, [`snap_manageState`](../reference/snaps-api.md#snap_managestate) automatically encrypts
data using a Snap-specific key before storing it on the user's disk, and automatically decrypts it
Expand Down Expand Up @@ -77,7 +76,7 @@ If you need to access encrypted state in a background task such as a [cron job](
unlocked before accessing state, preventing an unexpected password request.
:::

### 3. Use unencrypted storage
## Use unencrypted storage

To use unencrypted storage, set `encrypted` to `false` when storing, retrieving, or clearing data
using [`snap_manageState`](../reference/snaps-api.md#snap_managestate).
Expand Down
4 changes: 2 additions & 2 deletions snaps/features/lifecycle-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ To run an action when a user installs your Snap, expose the
[`onInstall`](../reference/entry-points.md#oninstall) entry point and implement the action.
For example, you can use `onInstall` to perform any initialization that is required upon installation.

The following example displays an [alert dialog](../reference/snaps-api.md#alert-dialog) upon installation:
The following example displays an [alert dialog](custom-ui/dialogs.md#display-an-alert-dialog) upon installation:

```typescript title="index.ts"
import type { OnInstallHandler } from "@metamask/snaps-sdk";
Expand Down Expand Up @@ -56,7 +56,7 @@ To run an action when a user updates your Snap, expose the
[`onUpdate`](../reference/entry-points.md#onupdate) entry point and implement the action.
For example, you can use `onUpdate` to perform any migrations that are required upon update.

The following example displays an [alert dialog](../reference/snaps-api.md#alert-dialog) upon update:
The following example displays an [alert dialog](custom-ui/dialogs.md#display-an-alert-dialog) upon update:

```typescript title="index.ts"
import type { OnUpdateHandler } from "@metamask/snaps-sdk";
Expand Down
2 changes: 1 addition & 1 deletion snaps/features/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ using the [`snap_notify`](../reference/snaps-api.md#snap_notify) API method.

## Steps

### 1. Get permission to notify users
### 1. Request permission to notify users

Request the [`snap_notify`](../reference/snaps-api.md#snap_notify) permission.
Add the following to your Snap's manifest file:
Expand Down
6 changes: 3 additions & 3 deletions snaps/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The following Snaps features are available in the stable version of MetaMask:
items={[
{
icon: require("./assets/features/dialog.png").default,
href: "reference/snaps-api#snap_dialog",
href: "features/custom-ui/dialogs",
title: "Dialogs",
description: "Display custom alert, confirmation, or prompt screens in MetaMask."
},
Expand Down Expand Up @@ -104,9 +104,9 @@ The following Snaps features are available in the stable version of MetaMask:
},
{
icon: require("./assets/features/homepage.png").default,
href: "reference/permissions#endowmentpage-home",
href: "features/custom-ui/home-pages",
title: "Home pages",
description: "Present a dedicated UI page in MetaMask for your Snap."
description: "Display a dedicated UI page in MetaMask for your Snap."
}
]}
/>
Expand Down
18 changes: 12 additions & 6 deletions snaps/learn/about-snaps/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ A Snap can communicate with MetaMask using the [Snaps API](../../reference/snaps
The Snaps API allows Snaps to extend or modify the functionality of MetaMask, and communicate with
other Snaps.

Dapps can also use certain MetaMask JSON-RPC API methods to install and communicate with Snaps.
Dapps can use the [Wallet API for Snaps](../../reference/wallet-api-for-snaps.md) to install and
communicate with Snaps.

A Snap can implement its own custom JSON-RPC API to communicate with dapps and other Snaps.

Expand All @@ -65,12 +66,17 @@ For each Snap, the user can:
- See its execution status (running, stopped, or crashed).
- Enable and disable the Snap.

Other than the settings page, a Snap can [modify the MetaMask UI](../../features/custom-ui/index.md) only
by [displaying a dialog](../../reference/snaps-api.md#snap_dialog) or
[displaying transaction insights](../../reference/entry-points.md#ontransaction).
A Snap can also display a [home page](../../features/custom-ui/home-pages.md) within MetaMask that
the user can access using the Snaps menu.

This means that most Snaps must rely on companion dapps and their custom JSON-RPC API methods to
present their data to the user.
Other than the settings page and home page, a Snap can
[modify the MetaMask UI](../../features/custom-ui/index.md) only
by displaying [dialogs](../../features/custom-ui/dialogs.md),
[transaction insights](../../reference/entry-points.md#ontransaction), or
[signature insights](../../features/signature-insights.md).

This means that many Snaps must use companion dapps and custom JSON-RPC API methods to
present data to the user.

:::note
Providing more ways for Snaps to modify the MetaMask UI is an important goal of the Snaps system,
Expand Down
7 changes: 4 additions & 3 deletions snaps/learn/best-practices/security-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ The following are guidelines for handling and signing transactions:

## Notify users

The following are guidelines for user notifications and authorizations:
The following are guidelines for user notifications, dialogs, and authorizations:

- **Transparent and consentful actions** - Before performing any of the following actions, provide a
prompt that displays detailed information about the action and asks the user to reject or accept it:
- **Transparent and consentful actions** - Before performing any of the following actions, display a
[confirmation dialog](../../features/custom-ui/dialogs.md#display-a-confirmation-dialog) that
contains detailed information about the action and asks the user to reject or accept it:
- **Modifying or reading state.** (In general, notify the user about any state changes.)
- **Switching networks or accounts.**
- **Deriving or generating key pairs, accounts, or smart contracts.**
Expand Down
6 changes: 3 additions & 3 deletions snaps/reference/entry-points.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ module.exports.onCronjob = async ({ request }) => {

## `onHomePage`

To build an embedded UI in MetaMask that any user can access through the Snaps menu, a Snap must
expose the `onHomePage` entry point.
To display a [home page](../features/custom-ui/home-pages.md) within MetaMask, a Snap must expose
the `onHomePage` entry point.
MetaMask calls the `onHomePage` handler method when the user selects the Snap name in the Snaps menu.

:::note
Expand Down Expand Up @@ -420,7 +420,7 @@ An object containing:
#### Returns

- An optional `severity` property that, if present, must be set to `SeverityLevel.Critical`.
- A content object displayed using [custom UI](../features/custom-ui/index.md) after the user
- A `content` object displayed using [custom UI](../features/custom-ui/index.md) after the user
selects the **Sign** button.
Due to current limitations of MetaMask's signature confirmation UI, the content will only be displayed if
the `severity` property is present and set to `SeverityLevel.Critical`.
Expand Down
6 changes: 3 additions & 3 deletions snaps/reference/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ See the [list of methods](../learn/about-snaps/apis.md#metamask-json-rpc-api) no

### `endowment:page-home`

To present a dedicated UI within MetaMask, a Snap must request the `endowment:page-home` permission.
This permission allows the Snap to specify a "home page" by exposing the
To display a [home page](../features/custom-ui/home-pages.md) within MetaMask, a Snap must request
the `endowment:page-home` permission.
This permission allows the Snap to present a dedicated UI by exposing the
[`onHomePage`](../reference/entry-points.md#onhomepage) entry point.
You can use any [custom UI components](../features/custom-ui/index.md) to build an embedded home page accessible through the Snaps menu.

Specify this permission in the manifest file as follows:

Expand Down
Loading
Loading