diff --git a/src/snap/index.ts b/src/snap/index.ts index 0ce34cd3..1bb795ca 100644 --- a/src/snap/index.ts +++ b/src/snap/index.ts @@ -1,2 +1,3 @@ export { flaskOnly } from "./utils"; export { installSnap } from "./install"; +export { invokeSnap } from "./invokeSnap"; diff --git a/src/snap/install.ts b/src/snap/install.ts index e2d298aa..be1ba7d5 100644 --- a/src/snap/install.ts +++ b/src/snap/install.ts @@ -20,12 +20,13 @@ export async function installSnap( hasKeyPermissions: boolean; customSteps?: InstallStep[]; version?: string; - } + }, + installationSnapUrl: string = "https://google.com" ): Promise { flaskOnly(page); //need to open page to access window.ethereum const installPage = await page.browser().newPage(); - await installPage.goto("https://google.com"); + await installPage.goto(installationSnapUrl); const installAction = installPage.evaluate( (opts: { snapId: string; version?: string }) => window.ethereum.request<{ snaps: { [snapId: string]: {} } }>({ diff --git a/src/snap/invokeSnap.ts b/src/snap/invokeSnap.ts new file mode 100644 index 00000000..4dfb5ab6 --- /dev/null +++ b/src/snap/invokeSnap.ts @@ -0,0 +1,29 @@ +import { Page, Serializable } from "puppeteer"; +import { flaskOnly } from "./utils"; + +export async function invokeSnap< + R = unknown, + P extends Serializable = Serializable +>( + page: Page, + snapId: string, + method: string, + params: P +): ReturnType> { + flaskOnly(page); + return page.evaluate( + async (opts: { snapId: string; method: string; params: P }) => { + return window.ethereum.request({ + method: "wallet_invokeSnap", + params: [ + `${opts.snapId}`, + { + method: opts.method, + params: opts.params, + }, + ], + }); + }, + { snapId, method, params } + ); +} diff --git a/src/types.ts b/src/types.ts index eb50f756..06a275ae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,16 @@ import * as puppeteer from "puppeteer"; +import { MetaMaskInpageProvider } from "@metamask/providers"; import { Path } from "./setup/metaMaskDownloader"; import { RECOMMENDED_METAMASK_VERSION } from "./index"; +declare global { + interface Window { + ethereum: MetaMaskInpageProvider; + } +} + export type LaunchOptions = (OfficialOptions | CustomOptions) & { //install flask (canary) version of metamask. metaMaskFlask?: boolean; diff --git a/test/flask/snaps.spec.ts b/test/flask/snaps.spec.ts index 597d0f92..602ed9be 100644 --- a/test/flask/snaps.spec.ts +++ b/test/flask/snaps.spec.ts @@ -1,8 +1,14 @@ +import { expect } from "chai"; import * as dappeteer from "../../src"; -import { installSnap } from "../../src/snap"; +import { installSnap, invokeSnap } from "../../src/snap"; import { TestContext } from "../constant"; import { Snaps } from "../deploy"; import { toUrl } from "../utils/utils"; +import { clickOnButton } from "../../src/helpers"; + +function getSnapIdByName(testContext: TestContext, snapName: Snaps): string { + return `local:${toUrl(testContext.snapServers[snapName].address())}`; +} describe("snaps", function () { let metamask: dappeteer.Dappeteer; @@ -19,20 +25,16 @@ describe("snaps", function () { }); it("should install base snap from npm", async function (this: TestContext) { - await installSnap( - metamask.page, - "local:" + toUrl(this.snapServers[Snaps.BASE_SNAP].address()), - { - hasPermissions: false, - hasKeyPermissions: false, - } - ); + await installSnap(metamask.page, getSnapIdByName(this, Snaps.BASE_SNAP), { + hasPermissions: false, + hasKeyPermissions: false, + }); }); it("should install permissions snap from npm", async function (this: TestContext) { await installSnap( metamask.page, - "local:" + toUrl(this.snapServers[Snaps.PERMISSIONS_SNAP].address()), + getSnapIdByName(this, Snaps.PERMISSIONS_SNAP), { hasPermissions: true, hasKeyPermissions: false, @@ -41,13 +43,39 @@ describe("snaps", function () { }); it("should install keys snap from npm", async function (this: TestContext) { + await installSnap(metamask.page, getSnapIdByName(this, Snaps.KEYS_SNAP), { + hasPermissions: true, + hasKeyPermissions: true, + }); + }); + + it("should invoke provided snap method", async function (this: TestContext) { + const snapAddress = "http://localhost:8545"; await installSnap( metamask.page, - "local:" + toUrl(this.snapServers[Snaps.KEYS_SNAP].address()), + getSnapIdByName(this, Snaps.PERMISSIONS_SNAP), { hasPermissions: true, - hasKeyPermissions: true, - } + hasKeyPermissions: false, + }, + snapAddress + ); + + const testPage = await metamask.page.browser().newPage(); + await testPage.goto(snapAddress); + + const invokeAction = invokeSnap( + testPage, + getSnapIdByName(this, Snaps.PERMISSIONS_SNAP), + "hello", + { version: "latest" } ); + + await metamask.page.bringToFront(); + await metamask.page.reload(); + + await clickOnButton(metamask.page, "Approve"); + + expect(await invokeAction).to.equal(true); }); });