Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat(metamask): Add support for personal_sign #988

Merged
merged 1 commit into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions wallets/metamask/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"test:coverage": "vitest run --coverage",
"test:e2e:headful": "playwright test",
"test:e2e:headless": "HEADLESS=true playwright test",
"test:e2e:headless:ui": "HEADLESS=true playwright test --ui",
"test:watch": "vitest watch",
"types:check": "tsc --noEmit"
},
Expand Down
30 changes: 27 additions & 3 deletions wallets/metamask/src/metamask.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import type { BrowserContext, Page } from '@playwright/test'
import { CrashPage, HomePage, LockPage, NotificationPage, OnboardingPage } from './pages'

const NO_EXTENSION_ID_ERROR = new Error('MetaMask extensionId is not set')

export class MetaMask {
crashPage: CrashPage
onboardingPage: OnboardingPage
lockPage: LockPage
homePage: HomePage
notificationPage: NotificationPage

constructor(readonly context: BrowserContext, readonly page: Page, readonly password: string) {
constructor(
readonly context: BrowserContext,
readonly page: Page,
readonly password: string,
readonly extensionId?: string
) {
this.crashPage = new CrashPage()

this.onboardingPage = new OnboardingPage(page)
Expand All @@ -21,8 +28,11 @@ export class MetaMask {
await this.onboardingPage.importWallet(seedPhrase, this.password)
}

async connectToDapp(extensionId: string) {
await this.notificationPage.connectToDapp(extensionId)
async connectToDapp() {
if (!this.extensionId) {
throw NO_EXTENSION_ID_ERROR
}
await this.notificationPage.connectToDapp(this.extensionId)
}

async lock() {
Expand All @@ -32,4 +42,18 @@ export class MetaMask {
async unlock() {
await this.lockPage.unlock(this.password)
}

async confirmSignature() {
if (!this.extensionId) {
throw NO_EXTENSION_ID_ERROR
}
await this.notificationPage.signPersonalMessage(this.extensionId)
}

async rejectSignature() {
if (!this.extensionId) {
throw NO_EXTENSION_ID_ERROR
}
await this.notificationPage.rejectPersonalMessage(this.extensionId)
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './connectToDapp'
export * from './personalSign'
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { BrowserContext } from '@playwright/test'
import { getNotificationPage } from '../../../utils/getNotificationPage'
import Selectors from '../selectors'

const signPersonalMessage = async (context: BrowserContext, extensionId: string) => {
const notificationPage = await getNotificationPage(context, extensionId)

await notificationPage.locator(Selectors.SignaturePage.signButton).click()
}

const rejectPersonalMessage = async (context: BrowserContext, extensionId: string) => {
const notificationPage = await getNotificationPage(context, extensionId)

await notificationPage.locator(Selectors.SignaturePage.rejectButton).click()
}

export const personalSign = {
sign: signPersonalMessage,
reject: rejectPersonalMessage
}
10 changes: 9 additions & 1 deletion wallets/metamask/src/pages/NotificationPage/page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Page } from '@playwright/test'
import { connectToDapp } from './actions'
import { connectToDapp, personalSign } from './actions'

export class NotificationPage {
readonly page: Page
Expand All @@ -11,4 +11,12 @@ export class NotificationPage {
async connectToDapp(extensionId: string) {
await connectToDapp(this.page.context(), extensionId)
}

async signPersonalMessage(extensionId: string) {
await personalSign.sign(this.page.context(), extensionId)
}

async rejectPersonalMessage(extensionId: string) {
await personalSign.reject(this.page.context(), extensionId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import SignaturePage from './signaturePage'

export default {
SignaturePage
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createDataTestSelector } from '../../../utils/selectors/createDataTestSelector'

export default {
signButton: `.request-signature__footer ${createDataTestSelector('request-signature__sign')}`,
rejectButton: '.request-signature__footer button.btn-secondary'
}
33 changes: 33 additions & 0 deletions wallets/metamask/test/e2e/metamask/confirmSignature.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { testWithSynpress } from 'fixtures'
import { MetaMask, unlockForFixture } from '../../../src'

import connectedSetup from '../wallet-setup/connected.setup'

const test = testWithSynpress(connectedSetup, unlockForFixture)

const { describe, expect } = test

describe('MetaMask.confirmSignature', () => {
test('should confirm `personal_sign`', async ({ context, metamaskPage, page, extensionId }) => {
const metamask = new MetaMask(context, metamaskPage, connectedSetup.walletPassword, extensionId)

await page.goto('https://metamask.github.io/test-dapp/')

await page.locator('#personalSign').click()

await metamask.confirmSignature()

await expect(page.locator('#personalSignResult')).toHaveText(
'0xf95b3efc808585303e20573e960993cde30c7f5a0f1c25cfab0379d5a14311d17898199814c8ebe66ec80b2b11690f840bde539f862ff4f04468d2a40f15178a1b'
)

await page.locator('#personalSignVerify').click()

await expect(page.locator('#personalSignVerifySigUtilResult')).toHaveText(
'0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
)
await expect(page.locator('#personalSignVerifyECRecoverResult')).toHaveText(
'0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
)
})
})
4 changes: 2 additions & 2 deletions wallets/metamask/test/e2e/metamask/connectToDapp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ const { describe, expect } = test

describe('MetaMask.connectToDapp', () => {
test('should connect wallet to dapp', async ({ context, page, extensionId }) => {
const metamask = new MetaMask(context, page, basicSetup.walletPassword)
const metamask = new MetaMask(context, page, basicSetup.walletPassword, extensionId)

await page.goto('https://metamask.github.io/test-dapp/')

await page.locator('#connectButton').click()

await metamask.connectToDapp(extensionId)
await metamask.connectToDapp()

await expect(page.locator('#accounts')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266')
})
Expand Down
25 changes: 25 additions & 0 deletions wallets/metamask/test/e2e/metamask/rejectSignature.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { testWithSynpress } from 'fixtures'
import { MetaMask, unlockForFixture } from '../../../src'

import connectedSetup from '../wallet-setup/connected.setup'

const test = testWithSynpress(connectedSetup, unlockForFixture)

const { describe, expect } = test

describe('MetaMask.rejectSignature', () => {
test('should reject `personal_sign`', async ({ context, metamaskPage, page, extensionId }) => {
const metamask = new MetaMask(context, metamaskPage, connectedSetup.walletPassword, extensionId)

await page.goto('https://metamask.github.io/test-dapp/')

await page.locator('#personalSign').click()

await metamask.rejectSignature()

await expect(page.locator('#personalSign')).toHaveText(
'Error: MetaMask Message Signature: User denied message signature.'
)
await expect(page.locator('#personalSignResult')).toHaveText('')
})
})
25 changes: 25 additions & 0 deletions wallets/metamask/test/e2e/wallet-setup/connected.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineWalletSetup } from 'core'
import { getExtensionId } from 'fixtures'
import { MetaMask } from '../../../src'

const SEED_PHRASE = 'test test test test test test test test test test test junk'

const PASSWORD = 'Tester@1234'

export default defineWalletSetup(PASSWORD, async (context, walletPage) => {
const extensionId = await getExtensionId(context, 'MetaMask')

const metamask = new MetaMask(context, walletPage, PASSWORD, extensionId)

await metamask.importWallet(SEED_PHRASE)

const page = await context.newPage()

await page.goto('https://metamask.github.io/test-dapp/')

await page.locator('#connectButton').click()

await metamask.connectToDapp()

await page.close()
})