Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat!: Deprecate snap_confirm and implement snap_dialog (#277)
Browse files Browse the repository at this point in the history
* refactor and implement dialog methods

* refactor tests to use snap_dialog

* update documentation

* fix comments

* fix type logic

* fix automation param in snap test
  • Loading branch information
BeroBurny committed Feb 13, 2023
1 parent 27156f7 commit 23a0121
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 123 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ async function main() {
await metaMask.snaps.invokeSnap(dappPage, snapId, "my-method")

// instruct MetaMask to accept this request
await metaMask.snaps.acceptDialog();
await metaMask.snaps.dialog.positive();

// get the notification emitter and the promise that will receive the notifications
const emitter = await metaMask.snaps.getNotificationEmitter();
Expand Down
27 changes: 17 additions & 10 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ For additional information read root [readme](../README.md)
- [snaps methods](#snaps-methods)
- [installSnap](#installSnap)
- [invokeSnap](#invokeSnap)
- [acceptDialog](#acceptDialog)
- [rejectDialog](#rejectDialog)
- [getNotificationEmitter](#getNotificationEmitter)
- [getAllNotifications](#getAllNotifications)
- [dialog](#snapDialog)
- [accept](#acceptDialog)
- [reject](#rejectDialog)
- [type](#typeDialog)

# dAppeteer setup methods

Expand Down Expand Up @@ -240,18 +242,23 @@ installs the snap. The `snapIdOrLocation` param is either the snapId or the full
## `metaMask.snaps.invokeSnap<Result = unknown, Params extends Serializable = Serializable>(page: DappeteerPage,snapId: string,method: string,params?: Params): Promise<Partial<Result>>`
invokes a MetaMask snap method. The snapId is the id of your installed snap (result of invoking `installSnap` method). This function will throw if there is an error while invoking snap.

<a name="acceptDialog"></a>
## `metaMask.snaps.acceptDialog(): Promise<void>`
accepts a snap_confirm dialog

<a name="rejectDialog"></a>
## `metaMask.snaps.rejectDialog(): Promise<void>`
rejects snap_confirm dialog

<a name="getNotificationEmitter"></a>
## `metaMask.snaps.getNotificationEmitter(): Promise<NotificationsEmitter>`
returns emitter to listen for notifications appearance in notification page

<a name="getAllNotifications"></a>
## `metaMask.snaps.getAllNotifications(): Promise<NotificationList>`
Returns all notifications in MetaMask notifications page

<a name="snapDialog"></a>
<a name="acceptDialog"></a>
## `metaMask.snaps.dialog.accept(): Promise<void>`
accepts a snap_dialog dialog

<a name="rejectDialog"></a>
## `metaMask.snaps.dialog.reject(): Promise<void>`
rejects snap_dialog dialog

<a name="typeDialog"></a>
## `metaMask.snaps.dialog.type(value: string): Promise<void>`
type value in snap_dialog dialog
6 changes: 2 additions & 4 deletions src/metamask/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Dappeteer } from "..";
import { DappeteerBrowser } from "../browser";
import { DappeteerPage } from "../page";
import { acceptDialog } from "../snap/acceptDialog";
import { rejectDialog } from "../snap/rejectDialog";
import { getAllNotifications, installSnap, invokeSnap } from "../snap";
import { getNotificationEmitter } from "../snap/getNotificationEmitter";
import { createDialogMethods } from "../snap/dialog";
import { acceptAddNetwork, rejectAddNetwork } from "./addNetwork";
import { approve } from "./approve";
import { confirmTransaction } from "./confirmTransaction";
Expand Down Expand Up @@ -64,9 +63,8 @@ export const getMetaMask = (page: DappeteerPage): Promise<Dappeteer> => {
invokeSnap,
getNotificationEmitter: getNotificationEmitter(page),
getAllNotifications: getAllNotifications(page),
acceptDialog: acceptDialog(page),
rejectDialog: rejectDialog(page),
installSnap: installSnap(page),
dialog: createDialogMethods(page),
},
page,
});
Expand Down
12 changes: 0 additions & 12 deletions src/snap/acceptDialog.ts

This file was deleted.

15 changes: 15 additions & 0 deletions src/snap/dialog/acceptDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { clickOnButton, retry } from "../../helpers";
import { DappeteerPage } from "../../page";
import { ensureIsInDialog } from "./helpers";

export const acceptDialog =
(page: DappeteerPage) => async (): Promise<void> => {
await retry(async () => {
await ensureIsInDialog(page);
await Promise.race([
clickOnButton(page, "Approve", { timeout: 1000 }),
clickOnButton(page, "Ok", { timeout: 1000 }),
clickOnButton(page, "Submit", { timeout: 1000 }),
]);
}, 5);
};
14 changes: 14 additions & 0 deletions src/snap/dialog/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DappeteerPage } from "../../page";
import { waitForOverlay } from "../../helpers";

export const ensureIsInDialog = async (page: DappeteerPage): Promise<void> => {
await page.bringToFront();
if (
await page
.waitForSelector(".snap-delineator__wrapper", { timeout: 500 })
.catch(() => false)
)
return;
await page.reload();
await waitForOverlay(page);
};
13 changes: 13 additions & 0 deletions src/snap/dialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DappeteerPage } from "../../page";
import { Dappeteer } from "../../types";
import { acceptDialog } from "./acceptDialog";
import { rejectDialog } from "./rejectDialog";
import { typeDialog } from "./typeDialog";

export const createDialogMethods = (
page: DappeteerPage
): Dappeteer["snaps"]["dialog"] => ({
accept: acceptDialog(page),
reject: rejectDialog(page),
type: typeDialog(page),
});
14 changes: 14 additions & 0 deletions src/snap/dialog/rejectDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { clickOnButton, retry } from "../../helpers";
import { DappeteerPage } from "../../page";
import { ensureIsInDialog } from "./helpers";

export const rejectDialog =
(page: DappeteerPage) => async (): Promise<void> => {
await retry(async () => {
await ensureIsInDialog(page);
await Promise.race([
clickOnButton(page, "Reject", { timeout: 1000 }),
clickOnButton(page, "Cancel", { timeout: 1000 }),
]);
}, 5);
};
12 changes: 12 additions & 0 deletions src/snap/dialog/typeDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DappeteerPage } from "../../page";
import { retry } from "../../helpers";
import { ensureIsInDialog } from "./helpers";

export const typeDialog =
(page: DappeteerPage) =>
async (value: string): Promise<void> => {
await retry(async () => {
await ensureIsInDialog(page);
await page.type(".snap-prompt input", value);
}, 5);
};
12 changes: 0 additions & 12 deletions src/snap/rejectDialog.ts

This file was deleted.

25 changes: 17 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,23 @@ export type Dappeteer = {
installationSnapUrl?: string;
}
) => Promise<string>;
/**
* Accepts snap_confirm dialog
*/
acceptDialog: () => Promise<void>;

/**
* Rejects snap_confirm dialog
*/
rejectDialog: () => Promise<void>;
dialog: {
/**
* Accepts snap_dialog dialog
*/
accept: () => Promise<void>;

/**
* Rejects snap_dialog dialog
*/
reject: () => Promise<void>;

/**
* type in snap_dialog dialog input field
* @param value {string} value that will be typed in field
*/
type: (value: string) => Promise<void>;
};
};
};
4 changes: 2 additions & 2 deletions test/flask/base-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An example Snap written in TypeScript.",
"proposedName": "Base Snap\n",
"source": {
"shasum": "DhB927XHgw6U6GsDljvg2zv4SGTruN2Ujjcyag4swgI=",
"shasum": "c3zJOCrroWks4m/x7cGUufmC/hlHwBtw8Pg52fvSVHA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -13,7 +13,7 @@
}
},
"initialPermissions": {
"snap_confirm": {},
"snap_dialog": {},
"endowment:rpc": {
"snaps": true,
"dapps": true
Expand Down
21 changes: 11 additions & 10 deletions test/flask/base-snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@ import { OnRpcRequestHandler } from "@metamask/snap-types";
declare const snap: {
request(param: {
method: string;
params: { textAreaContent: string; description: string; prompt: string }[];
params: { type: "Confirmation"; content: Object };
}): Promise<unknown>;
};

export const onRpcRequest: OnRpcRequestHandler = ({ origin, request }) => {
switch (request.method) {
case "hello":
return snap.request({
method: "snap_confirm",
params: [
{
prompt: `Hello, ${origin}!`,
description:
"This custom confirmation is just for display purposes.",
textAreaContent:
"But you can edit the snap source code to make it do something, if you want to!",
method: "snap_dialog",
params: {
type: "Confirmation",
content: {
type: "panel",
children: [
{ type: "heading", value: `Confirmation ${origin}` },
{ type: "text", value: "Text here" },
],
},
],
},
});
default:
throw new Error("Method not found.");
Expand Down
3 changes: 2 additions & 1 deletion test/flask/keys-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An example Snap written in TypeScript.",
"proposedName": "Keys Snap\n",
"source": {
"shasum": "sqDnj6sacQPifC/D9f9pWh4Cvi2gVdZJFrxikYhDqXk=",
"shasum": "c3zJOCrroWks4m/x7cGUufmC/hlHwBtw8Pg52fvSVHA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -13,6 +13,7 @@
}
},
"initialPermissions": {
"snap_dialog": {},
"snap_getBip44Entropy": [
{
"coinType": 1
Expand Down
22 changes: 10 additions & 12 deletions test/flask/keys-snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ import { OnRpcRequestHandler } from "@metamask/snap-types";
declare const snap: {
request(param: {
method: string;
params: {
type?: string;
message?: string;
prompt?: string;
description?: string;
textAreaContent?: string;
};
params: { type: "Confirmation"; content: Object };
}): Promise<unknown>;
};

export const onRpcRequest: OnRpcRequestHandler = ({ origin, request }) => {
switch (request.method) {
case "hello":
return snap.request({
method: "snap_confirm",
method: "snap_dialog",
params: {
prompt: `Hello, ${origin}!`,
description: "This custom confirmation is just for display purposes.",
textAreaContent:
"But you can edit the snap source code to make it do something, if you want to!",
type: "Confirmation",
content: {
type: "panel",
children: [
{ type: "heading", value: `Confirmation ${origin}` },
{ type: "text", value: "Text here" },
],
},
},
});
default:
Expand Down
4 changes: 2 additions & 2 deletions test/flask/methods-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An example Snap written in TypeScript.",
"proposedName": "Methods Snap\n",
"source": {
"shasum": "01KcaLPkcFwYC7sCyO7cAUWzB3GBAa4t/UXclc/mM5c=",
"shasum": "OUsE/g0W1apXjYs+eNKwbP56eQb/BPazbIsTsdNB/CA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -13,7 +13,7 @@
}
},
"initialPermissions": {
"snap_confirm": {},
"snap_dialog": {},
"snap_notify": {},
"endowment:rpc": {
"snaps": true,
Expand Down

0 comments on commit 23a0121

Please sign in to comment.