Skip to content

Commit

Permalink
Move onSettingsPage example to Preinstalled example snap
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeRx committed Dec 17, 2024
1 parent 967360c commit 1d9628d
Show file tree
Hide file tree
Showing 27 changed files with 144 additions and 713 deletions.
6 changes: 2 additions & 4 deletions packages/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ The following is a list of the snaps in this directory.
- [**`packages/notifications`**](./packages/notifications): This snap
demonstrates how to use the `snap_notify` method to display notifications to
the user, either as a MetaMask notification or as a desktop notification.
- [**`packages/settings-page`**](./packages/settings-page):
This snap demonstrates how to use `endowment:page-settings` permission,
showing a settings page to the user.
- [**`packages/transaction-insights`**](./packages/transaction-insights):
This snap demonstrates how to use `endowment:transaction-insights` permission,
and provide transaction insights to the user.
Expand All @@ -90,7 +87,8 @@ The following is a list of the snaps in this directory.
how the Snaps platform handles errors thrown by snaps.
- [**`packages/preinstalled`**](./packages/preinstalled): This snap demonstrates
preinstalled snaps, i.e., snaps that are installed in the MetaMask extension
by default.
by default. It also demonstrates the use of the `endowment:page-settings` permission,
showing a settings page to the user.
- [**`packages/send-flow`**](./packages/send-flow): This snap demonstrates
a simple send flow using custom UI.
- [**`packages/wasm`**](./packages/wasm): This snap demonstrates how
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/browserify/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "i5/9SEgHydVQotkWZ7ErpPhOI2N7Cg3U+lbR5/ApQI4=",
"shasum": "4diRqHxV2Sr2wHuyoP1dL/WcSbS6HSVzxkDL+Iv0JNM=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
23 changes: 23 additions & 0 deletions packages/examples/packages/preinstalled/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,26 @@ MetaMask extension by default.

> [!NOTE]
> Preinstalled Snaps are primarily for internal use by MetaMask.
This snap also demonstrates how to use the `endowment:page-settings` permission to show a settings page that leverages custom UI components.

> [!NOTE]
> This endowment is initially restricted to preinstalled snaps only.
## Snap manifest

The manifest of this snap includes the `endowment:page-settings` permission:

```json
{
"initialPermissions": {
"endowment:page-settings": {}
}
}
```

This permission does not require any additional configuration.

## Snap usage

This snap exposes an `onSettingsPage` handler, which returns the UI to be shown.
6 changes: 4 additions & 2 deletions packages/examples/packages/preinstalled/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "WF9+BfnWRznf3otVkb8p0M38ULIIPywefZdHiAAk7jM=",
"shasum": "uDEC4wnc/rEN1OKqXidpOvejRN3h3dR85cvQLnLmJB8=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -20,7 +20,9 @@
"endowment:rpc": {
"dapps": true
},
"snap_dialog": {}
"snap_dialog": {},
"endowment:page-settings": {},
"snap_manageState": {}
},
"platformVersion": "6.13.0",
"manifestVersion": "0.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './dialog';
export * from './result';
export * from './settings';
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
type SnapComponent,
} from '@metamask/snaps-sdk/jsx';

export type SettingsPageProps = {
export type SettingsProps = {
setting1?: boolean;
setting2?: 'option1' | 'option2';
setting3?: 'option1' | 'option2';
Expand All @@ -25,7 +25,7 @@ export type SettingsPageProps = {
* @param param.setting3 - The third setting.
* @returns The settings page component.
*/
export const SettingsPage: SnapComponent<SettingsPageProps> = ({
export const Settings: SnapComponent<SettingsProps> = ({
setting1,
setting2,
setting3,
Expand Down
89 changes: 84 additions & 5 deletions packages/examples/packages/preinstalled/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { MethodNotFoundError } from '@metamask/snaps-sdk';
import { MethodNotFoundError, UserInputEventType } from '@metamask/snaps-sdk';
import type {
OnRpcRequestHandler,
OnSettingsPageHandler,
OnUserInputHandler,
} from '@metamask/snaps-sdk';

import { Dialog, Result } from './components';
import { Dialog, Result, Settings } from './components';

type SnapState = {
setting1?: boolean;
setting2?: 'option1' | 'option2';
setting3?: 'option1' | 'option2';
};

/**
* Handle incoming JSON-RPC requests from the dapp, sent through the
* `wallet_invokeSnap` method. This handler handles a single method:
*
* - `showDialog` - Opens a dialog.
* - `getSettings`: Get the settings state from the snap state.
*
* @param params - The request parameters.
* @param params.request - The JSON-RPC request object.
* @returns The JSON-RPC response.
* @see https://docs.metamask.io/snaps/reference/exports/#onrpcrequest
* @see https://docs.metamask.io/snaps/reference/rpc-api/#wallet_invokesnap
* @see https://docs.metamask.io/snaps/reference/rpc-api/#snap_notify
* @see https://docs.metamask.io/snaps/reference/snaps-api/#snap_managestate
*/
export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
switch (request.method) {
Expand All @@ -29,18 +37,62 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
},
});

case 'getSettings':
return await snap.request({
method: 'snap_manageState',
params: {
operation: 'get',
encrypted: false,
},
});

default:
// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw new MethodNotFoundError({ method: request.method });
}
};

/**
* Handle incoming settings page requests from the MetaMask clients.
*
* @returns A static panel rendered with custom UI.
* @see https://docs.metamask.io/snaps/reference/exports/#onsettingspage
*/
export const onSettingsPage: OnSettingsPageHandler = async () => {
const state: SnapState | null = await snap.request({
method: 'snap_manageState',
params: {
operation: 'get',
encrypted: false,
},
});

return {
content: (
<Settings
setting1={state?.setting1}
setting2={state?.setting2}
setting3={state?.setting3}
/>
),
};
};

/**
* Handle incoming user events coming from the MetaMask clients open interfaces.
*
* @param params - The event parameters.
* @param params.event - The event object containing the event type, name and value.
* @param params.id - The unique identifier of the open interface.
* @param params.context - The context object containing the current state of the open interface.
* @see https://docs.metamask.io/snaps/reference/exports/#onuserinput
*/
export const onUserInput: OnUserInputHandler = async ({
event,
id,
context,
}) => {
if (event.type === 'ButtonClickEvent') {
if (event.type === UserInputEventType.ButtonClickEvent) {
if (event.name === 'cancel') {
await snap.request({
method: 'snap_resolveInterface',
Expand All @@ -62,7 +114,7 @@ export const onUserInput: OnUserInputHandler = async ({
}
}

if (event.type === 'FormSubmitEvent') {
if (event.type === UserInputEventType.FormSubmitEvent) {
if (event.name === 'form') {
const value = String(event.value['custom-input']);
await snap.request({
Expand All @@ -75,4 +127,31 @@ export const onUserInput: OnUserInputHandler = async ({
});
}
}

if (
event.type === UserInputEventType.InputChangeEvent &&
(event.name === 'setting1' ||
event.name === 'setting2' ||
event.name === 'setting3')
) {
const state = await snap.request({
method: 'snap_manageState',
params: {
operation: 'get',
encrypted: false,
},
});

await snap.request({
method: 'snap_manageState',
params: {
operation: 'update',
encrypted: false,
newState: {
...state,
[event.name]: event.value,
},
},
});
}
};
18 changes: 0 additions & 18 deletions packages/examples/packages/settings-page/.depcheckrc.json

This file was deleted.

7 changes: 0 additions & 7 deletions packages/examples/packages/settings-page/.eslintrc.js

This file was deleted.

10 changes: 0 additions & 10 deletions packages/examples/packages/settings-page/CHANGELOG.md

This file was deleted.

Loading

0 comments on commit 1d9628d

Please sign in to comment.