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

Commit

Permalink
fix: remove page param from install snap (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpetrunic committed Dec 15, 2022
1 parent 58df2d3 commit 8343d33
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 90 deletions.
2 changes: 1 addition & 1 deletion src/metamask/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const getMetaMask = (page: DappeteerPage): Promise<Dappeteer> => {
acceptDialog: acceptDialog(page),
rejectDialog: rejectDialog(page),
invokeSnap,
installSnap,
installSnap: installSnap(page),
},
page,
});
Expand Down
6 changes: 1 addition & 5 deletions src/setup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
107 changes: 54 additions & 53 deletions src/snap/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,65 @@ export type InstallSnapOptions = {
installationSnapUrl?: string;
};

export async function installSnap(
page: DappeteerPage,
snapIdOrLocation: string,
opts: InstallSnapOptions
): Promise<string> {
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<InstallSnapResult>({
method: "wallet_enable",
params: [
{
[`wallet_snap_${opts.snapId}`]: {
version: opts.version ?? "latest",
export const installSnap =
(page: DappeteerPage) =>
async (
snapIdOrLocation: string,
opts: InstallSnapOptions
): Promise<string> => {
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<InstallSnapResult>({
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,
Expand Down
37 changes: 31 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,37 @@ export type Dappeteer = {
};
page: DappeteerPage;
snaps: {
/**
* Returns all notifications in Metamask notifications page
*/
getAllNotifications: () => Promise<NotificationList>;
invokeSnap: <R = unknown, P extends Serializable = Serializable>(
/**
* 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: <Result = unknown, Params extends Serializable = Serializable>(
page: DappeteerPage,
snapId: string,
method: string,
params?: P
) => Promise<Partial<R>>;
params?: Params
) => Promise<Partial<Result>>;

/**
*
* 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;
Expand All @@ -94,7 +112,14 @@ export type Dappeteer = {
},
installationSnapUrl?: string
) => Promise<string>;
/**
* Accepts snap_confirm dialog
*/
acceptDialog: () => Promise<void>;

/**
* Rejects snap_confirm dialog
*/
rejectDialog: () => Promise<void>;
};
};
37 changes: 12 additions & 25 deletions test/flask/snaps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand All @@ -68,7 +56,6 @@ describe("snaps", function () {
return;
}
snapId = await metamask.snaps.installSnap(
metamask.page,
this.snapServers[Snaps.METHODS_SNAP],
{
hasPermissions: true,
Expand Down

0 comments on commit 8343d33

Please sign in to comment.