From 2678119efaffee748d33e90425b7c3370e01acdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Tue, 15 Nov 2022 14:21:43 +0100 Subject: [PATCH] fix: remove page param from install snap (#188) --- src/metamask/index.ts | 2 +- src/setup/index.ts | 6 +-- src/snap/install.ts | 107 ++++++++++++++++++++------------------- src/types.ts | 37 +++++++++++--- test/flask/snaps.spec.ts | 37 +++++--------- 5 files changed, 99 insertions(+), 90 deletions(-) diff --git a/src/metamask/index.ts b/src/metamask/index.ts index 84d15843..c574dd0d 100644 --- a/src/metamask/index.ts +++ b/src/metamask/index.ts @@ -59,7 +59,7 @@ export const getMetaMask = (page: DappeteerPage): Promise => { acceptDialog: acceptDialog(page), rejectDialog: rejectDialog(page), invokeSnap, - installSnap, + installSnap: installSnap(page), }, page, }); diff --git a/src/setup/index.ts b/src/setup/index.ts index d77a40a9..0d6b4a6e 100644 --- a/src/setup/index.ts +++ b/src/setup/index.ts @@ -55,11 +55,7 @@ export const initSnapEnv = async ( }); const page = dappeteer.page; - const snapId = await dappeteer.snaps.installSnap( - page, - snapIdOrLocation, - opts - ); + const snapId = await dappeteer.snaps.installSnap(snapIdOrLocation, opts); return { dappeteer, diff --git a/src/snap/install.ts b/src/snap/install.ts index b542bcdd..2f744b05 100644 --- a/src/snap/install.ts +++ b/src/snap/install.ts @@ -24,64 +24,65 @@ export type InstallSnapOptions = { installationSnapUrl?: string; }; -export async function installSnap( - page: DappeteerPage, - snapIdOrLocation: string, - opts: InstallSnapOptions -): Promise { - flaskOnly(page); - //need to open page to access window.ethereum - const installPage = await page.browser().newPage(); - await installPage.goto(opts.installationSnapUrl ?? "https://google.com"); - let snapServer: http.Server | undefined; - if (fs.existsSync(snapIdOrLocation)) { - //snap dist location - snapServer = await startSnapServer(snapIdOrLocation); - snapIdOrLocation = `local:${toUrl(snapServer.address())}`; - } - const installAction = installPage.evaluate( - (opts: { snapId: string; version?: string }) => - window.ethereum.request({ - method: "wallet_enable", - params: [ - { - [`wallet_snap_${opts.snapId}`]: { - version: opts.version ?? "latest", +export const installSnap = + (page: DappeteerPage) => + async ( + snapIdOrLocation: string, + opts: InstallSnapOptions + ): Promise => { + flaskOnly(page); + //need to open page to access window.ethereum + const installPage = await page.browser().newPage(); + await installPage.goto(opts.installationSnapUrl ?? "https://google.com"); + let snapServer: http.Server | undefined; + if (fs.existsSync(snapIdOrLocation)) { + //snap dist location + snapServer = await startSnapServer(snapIdOrLocation); + snapIdOrLocation = `local:${toUrl(snapServer.address())}`; + } + const installAction = installPage.evaluate( + (opts: { snapId: string; version?: string }) => + window.ethereum.request({ + method: "wallet_enable", + params: [ + { + [`wallet_snap_${opts.snapId}`]: { + version: opts.version ?? "latest", + }, }, - }, - ], - }), - { snapId: snapIdOrLocation, version: opts.version } - ); + ], + }), + { snapId: snapIdOrLocation, version: opts.version } + ); - await page.bringToFront(); - await page.reload(); - await clickOnButton(page, "Connect"); - if (opts.hasPermissions) { - await clickOnButton(page, "Approve & install"); - if (opts.hasKeyPermissions) { - const checkbox = await page.waitForSelector(".checkbox-label", { - visible: true, - }); - await checkbox.click(); - await clickOnButton(page, "Confirm"); + await page.bringToFront(); + await page.reload(); + await clickOnButton(page, "Connect"); + if (opts.hasPermissions) { + await clickOnButton(page, "Approve & install"); + if (opts.hasKeyPermissions) { + const checkbox = await page.waitForSelector(".checkbox-label", { + visible: true, + }); + await checkbox.click(); + await clickOnButton(page, "Confirm"); + } + } else { + await clickOnButton(page, "Install"); } - } else { - await clickOnButton(page, "Install"); - } - for (const step of opts.customSteps ?? []) { - await step(page); - } + for (const step of opts.customSteps ?? []) { + await step(page); + } - const result = await installAction; - await installPage.close({ runBeforeUnload: true }); - if (!(snapIdOrLocation in result.snaps)) { - throw new Error("Failed to install snap"); - } - snapServer.close(); - return snapIdOrLocation; -} + const result = await installAction; + await installPage.close({ runBeforeUnload: true }); + if (!(snapIdOrLocation in result.snaps)) { + throw new Error("Failed to install snap"); + } + snapServer.close(); + return snapIdOrLocation; + }; export async function isSnapInstalled( page: DappeteerPage, diff --git a/src/types.ts b/src/types.ts index eb6adc8f..50ee92de 100644 --- a/src/types.ts +++ b/src/types.ts @@ -73,19 +73,37 @@ export type Dappeteer = { }; page: DappeteerPage; snaps: { + /** + * Returns all notifications in Metamask notifications page + */ getAllNotifications: () => Promise; - invokeSnap: ( + /** + * Invoke Metamask snap method. Function will throw if there is an error while invoking snap. + * Use generic params to override result and parameter types. + * @param page Browser page where injected Metamask provider will be available. + * For most snaps, openning google.com will suffice. + * @param snapId id of your installed snap (result of invoking `installSnap` method) + * @param method snap method you wan't to invoke + * @param params required parameters of snap method + */ + invokeSnap: ( page: DappeteerPage, snapId: string, method: string, - params?: P - ) => Promise>; + params?: Params + ) => Promise>; + /** - * + * Installs snap. Function will throw if there is an error while installing snap. + * @param snapIdOrLocation either pass in snapId or full path to your snap directory + * where we can find bundled snap (you need to ensure snap is built) + * @param opts {Object} snap method you wan't to invoke + * @param opts.hasPermissions Set to true if snap uses some permissions + * @param opts.hasKeyPermissions Set to true if snap uses key permissions + * @param installationSnapUrl url of your dapp. Defaults to google.com */ installSnap: ( - page: DappeteerPage, - snapId: string, + snapIdOrLocation: string, opts: { hasPermissions: boolean; hasKeyPermissions: boolean; @@ -94,7 +112,14 @@ export type Dappeteer = { }, installationSnapUrl?: string ) => Promise; + /** + * Accepts snap_confirm dialog + */ acceptDialog: () => Promise; + + /** + * Rejects snap_confirm dialog + */ rejectDialog: () => Promise; }; }; diff --git a/test/flask/snaps.spec.ts b/test/flask/snaps.spec.ts index dbc0cd6e..b7c8008c 100644 --- a/test/flask/snaps.spec.ts +++ b/test/flask/snaps.spec.ts @@ -19,36 +19,24 @@ describe("snaps", function () { }); it("should install base snap from local server", async function (this: TestContext) { - await metamask.snaps.installSnap( - metamask.page, - this.snapServers[Snaps.BASE_SNAP], - { - hasPermissions: false, - hasKeyPermissions: false, - } - ); + await metamask.snaps.installSnap(this.snapServers[Snaps.BASE_SNAP], { + hasPermissions: false, + hasKeyPermissions: false, + }); }); it("should install permissions snap local server", async function (this: TestContext) { - await metamask.snaps.installSnap( - metamask.page, - this.snapServers[Snaps.PERMISSIONS_SNAP], - { - hasPermissions: true, - hasKeyPermissions: false, - } - ); + await metamask.snaps.installSnap(this.snapServers[Snaps.PERMISSIONS_SNAP], { + hasPermissions: true, + hasKeyPermissions: false, + }); }); it("should install keys snap from local server", async function (this: TestContext) { - await metamask.snaps.installSnap( - metamask.page, - this.snapServers[Snaps.KEYS_SNAP], - { - hasPermissions: true, - hasKeyPermissions: true, - } - ); + await metamask.snaps.installSnap(this.snapServers[Snaps.KEYS_SNAP], { + hasPermissions: true, + hasKeyPermissions: true, + }); }); describe("should test snap methods", function () { @@ -68,7 +56,6 @@ describe("snaps", function () { return; } snapId = await metamask.snaps.installSnap( - metamask.page, this.snapServers[Snaps.METHODS_SNAP], { hasPermissions: true,