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

fix: reset sa enabled networks #2104

Merged
merged 6 commits into from
Apr 2, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ jobs:
if: always()
with:
name: screenshots
path: ./apps/laboratory/screenshots/
path: ./apps/laboratory/test-results/
retention-days: 7
5 changes: 5 additions & 0 deletions apps/laboratory/tests/email.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ testMEmail('it should switch network and sign', async ({ modalPage, modalValidat
await modalPage.approveSign()
await modalValidator.expectAcceptedSign()
})

testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator }) => {
await modalPage.disconnect()
await modalValidator.expectDisconnected()
})
37 changes: 1 addition & 36 deletions apps/laboratory/tests/shared/fixtures/w3m-email-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { ModalValidator } from '../validators/ModalValidator'
import { DeviceRegistrationPage } from '../pages/DeviceRegistrationPage'
import { Email } from '../utils/email'

const mailsacApiKey = process.env['MAILSAC_API_KEY']
Expand All @@ -17,43 +16,9 @@ export const testMEmail = base.extend<ModalFixture>({
await modalPage.load()

const email = new Email(mailsacApiKey)

const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await email.deleteAllMessages(tempEmail)
await modalPage.loginWithEmail(tempEmail)

let messageId = await email.getLatestMessageId(tempEmail)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(tempEmail, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(tempEmail)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(tempEmail)

emailBody = await email.getEmailBody(tempEmail, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.length !== 7) {
// eslint-disable-next-line no-console
console.log('Getting the OTP code from body', { previousOtp: otp })
otp = email.getOtpCodeFromBody(emailBody)
}
await modalPage.enterOTP(otp)

await modalPage.emailFlow(tempEmail, context)
await use(modalPage)
},
modalValidator: async ({ modalPage }, use) => {
Expand Down
62 changes: 17 additions & 45 deletions apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,33 @@
import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { DeviceRegistrationPage } from '../pages/DeviceRegistrationPage'
import { Email } from '../utils/email'
import { ModalWalletPage } from '../pages/ModalWalletPage'
import { ModalWalletValidator } from '../validators/ModalWalletValidator'
import type { ModalPage } from '../pages/ModalPage'

const mailsacApiKey = process.env['MAILSAC_API_KEY']
if (!mailsacApiKey) {
throw new Error('MAILSAC_API_KEY is not set')
}

// Test Modal + Smart Account
export const testModalSmartAccount = base.extend<ModalFixture>({
export const testModalSmartAccount = base.extend<ModalFixture & { slowModalPage: ModalPage }>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library, context }, use, testInfo) => {
const modalPage = new ModalWalletPage(page, library)
await modalPage.load()

const email = new Email(mailsacApiKey)

const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await email.deleteAllMessages(tempEmail)
await modalPage.loginWithEmail(tempEmail)

let messageId = await email.getLatestMessageId(tempEmail)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(tempEmail, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(tempEmail)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(tempEmail)

emailBody = await email.getEmailBody(tempEmail, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.length !== 6) {
otp = email.getOtpCodeFromBody(emailBody)
}
await modalPage.enterOTP(otp)
await modalPage.switchNetwork('Sepolia')
await modalPage.page.waitForTimeout(1500)
await use(modalPage)
},
modalPage: [
async ({ page, library, context }, use, testInfo) => {
const modalPage = new ModalWalletPage(page, library)
await modalPage.load()

const email = new Email(mailsacApiKey)
const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await modalPage.emailFlow(tempEmail, context)
await modalPage.switchNetwork('Sepolia')
await modalPage.page.waitForTimeout(1500)
await use(modalPage)
},
{ timeout: 90_000 }
],
modalValidator: async ({ modalPage }, use) => {
const modalValidator = new ModalWalletValidator(modalPage.page)
await use(modalValidator)
Expand Down
45 changes: 45 additions & 0 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import type { BrowserContext, Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { BASE_URL } from '../constants'
import { doActionAndWaitForNewPage } from '../utils/actions'
import { Email } from '../utils/email'
import { DeviceRegistrationPage } from './DeviceRegistrationPage'

const mailsacApiKey = process.env['MAILSAC_API_KEY'] || ''
if (!mailsacApiKey) {
throw new Error('MAILSAC_API_KEY is not set')
}

export type ModalFlavor = 'default' | 'siwe' | 'email' | 'wallet'

Expand Down Expand Up @@ -52,6 +59,44 @@ export class ModalPage {
return this.assertDefined(await qrCode.getAttribute('uri'))
}

async emailFlow(emailAddress: string, context: BrowserContext): Promise<void> {
await this.load()

const email = new Email(mailsacApiKey)

await email.deleteAllMessages(emailAddress)
await this.loginWithEmail(emailAddress)

let messageId = await email.getLatestMessageId(emailAddress)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(emailAddress, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(emailAddress)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(emailAddress)

emailBody = await email.getEmailBody(emailAddress, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.replace(' ', '').length !== 6) {
otp = email.getOtpCodeFromBody(emailBody)
}
await this.enterOTP(otp)
}

async loginWithEmail(email: string) {
await this.page.goto(this.url)
// Connect Button doesn't have a proper `disabled` attribute so we need to wait for the button to change the text
Expand Down
9 changes: 9 additions & 0 deletions apps/laboratory/tests/shared/pages/ModalWalletPage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-await-in-loop */
import { expect } from '@playwright/test'
import type { Page } from '@playwright/test'
import { ModalPage } from './ModalPage'

Expand Down Expand Up @@ -29,4 +30,12 @@ export class ModalWalletPage extends ModalPage {
await this.page.getByTestId('w3m-header-close').click()
await this.page.waitForTimeout(2000)
}

override async disconnect(): Promise<void> {
this.openSettings()
const disconnectBtn = this.page.getByTestId('disconnect-button')
await expect(disconnectBtn, 'Disconnect button should be visible').toBeVisible()
await expect(disconnectBtn, 'Disconnect button should be enabled').toBeEnabled()
await disconnectBtn.click({ force: true })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const testEmailsEOAAddresses = [
'0x8cD2c90E98309FcdeEd2bA0FdaC050e0284D1fD6',
'0x4446d7538f4CF5832604BE20535d954439Ff075d',
'0xbC6996C993d358989743bC74082B046da9d4d8fb',
'0x1216ff6012bcFcBaDFb4691cF586702Af9482F8C'
'0x1216ff6012bcFcBaDFb4691cF586702Af9482F8C',
// Non-smart account enabled address
'0x26760E9EbAcD6f4C47c095E7fd544C5AC093a4E3'
]

function formatAddress(address: string) {
Expand Down
22 changes: 21 additions & 1 deletion apps/laboratory/tests/smart-account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { testModalSmartAccount } from './shared/fixtures/w3m-smart-account-fixtu
import type { ModalWalletPage } from './shared/pages/ModalWalletPage'
import type { ModalWalletValidator } from './shared/validators/ModalWalletValidator'

const NOT_ENABLED_SMART_ACCOUNT_INDEX = 10

testModalSmartAccount.beforeEach(async ({ modalValidator }) => {
await modalValidator.expectConnected()
})
Expand Down Expand Up @@ -45,8 +47,26 @@ testModalSmartAccount(
const walletModalValidator = modalValidator as ModalWalletValidator

await walletModalPage.togglePreferredAccountType()
await walletModalPage.switchNetwork('Polygon')
await walletModalPage.switchNetwork('Avalanche')
await walletModalPage.openSettings()
await walletModalValidator.expectEoaAddress(testInfo.parallelIndex)
}
)

testModalSmartAccount(
'it should use an eoa when disconnecting and connecting to a not enabled address',
async ({ modalPage, modalValidator, context }) => {
const walletModalPage = modalPage as ModalWalletPage
const walletModalValidator = modalValidator as ModalWalletValidator

await walletModalPage.togglePreferredAccountType()
await walletModalPage.disconnect()
await walletModalPage.page.waitForTimeout(2500)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this absolutely required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was preventing the magic disconnect promise from resolving, but shoould work without it.
will push fix in a diff pr if possible


await walletModalPage.emailFlow('web3modal-smart-account@mailsac.com', context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract to const

await walletModalPage.switchNetwork('Sepolia')
await walletModalPage.openSettings()

await walletModalValidator.expectEoaAddress(NOT_ENABLED_SMART_ACCOUNT_INDEX)
}
)
4 changes: 3 additions & 1 deletion packages/core/src/controllers/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ type StateKey = keyof NetworkControllerState
// -- State --------------------------------------------- //
const state = proxy<NetworkControllerState>({
supportsAllNetworks: true,
isDefaultCaipNetwork: false
isDefaultCaipNetwork: false,
smartAccountEnabledNetworks: []
})

// -- Controller ---------------------------------------- //
Expand Down Expand Up @@ -141,6 +142,7 @@ export const NetworkController = {
}
state.approvedCaipNetworkIds = undefined
state.supportsAllNetworks = true
state.smartAccountEnabledNetworks = []
},

showUnsupportedChainUI() {
Expand Down
6 changes: 4 additions & 2 deletions packages/core/tests/controllers/ConnectorController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const emailProvider = {

const walletConnectConnector = {
id: 'walletConnect',
explorerId: 'walletConnect',
explorerId: 'walletConnectId',
type: 'WALLET_CONNECT'
} as const
const externalConnector = { id: 'external', type: 'EXTERNAL' } as const
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('ConnectorController', () => {

it('should return the correct connector on getConnector', () => {
ConnectorController.addConnector(zerionConnector)
expect(ConnectorController.getConnector('walletConnect', '')).toBe(undefined)
expect(ConnectorController.getConnector('walletConnectId', '')).toBe(walletConnectConnector)
expect(ConnectorController.getConnector('', 'io.metamask.com')).toBe(metamaskConnector)
expect(ConnectorController.getConnector(zerionConnector.id, '')).toBeUndefined()
expect(ConnectorController.getConnector('unknown', '')).toBeUndefined()
Expand All @@ -98,6 +98,7 @@ describe('ConnectorController', () => {
walletConnectConnector,
externalConnector,
metamaskConnector,
zerionConnector,
emailConnector
])

Expand All @@ -123,6 +124,7 @@ describe('ConnectorController', () => {
walletConnectConnector,
externalConnector,
metamaskConnector,
zerionConnector,
emailConnector,
announcedConnector
])
Expand Down
15 changes: 14 additions & 1 deletion packages/core/tests/controllers/NetworkController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ describe('NetworkController', () => {
expect(NetworkController.state).toEqual({
_client: NetworkController._getClient(),
supportsAllNetworks: true,
isDefaultCaipNetwork: false
isDefaultCaipNetwork: false,
smartAccountEnabledNetworks: []
})
})

Expand Down Expand Up @@ -64,6 +65,7 @@ describe('NetworkController', () => {
expect(NetworkController.state.caipNetwork).toEqual(undefined)
expect(NetworkController.state.approvedCaipNetworkIds).toEqual(undefined)
expect(NetworkController.state.requestedCaipNetworks).toEqual(requestedCaipNetworks)
expect(NetworkController.state.smartAccountEnabledNetworks).toEqual([])
})

it('should update state correctly on setDefaultCaipNetwork()', () => {
Expand All @@ -78,4 +80,15 @@ describe('NetworkController', () => {
expect(NetworkController.state.approvedCaipNetworkIds).toEqual(undefined)
expect(NetworkController.state.requestedCaipNetworks).toEqual(requestedCaipNetworks)
})

it('should check correctly if smart accounts are enabled on the network', () => {
NetworkController.setSmartAccountEnabledNetworks([1])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(true)
NetworkController.setSmartAccountEnabledNetworks([])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(false)
NetworkController.setSmartAccountEnabledNetworks([2])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(false)
NetworkController.setCaipNetwork({ id: 'eip155:2', name: 'Ethereum' })
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(true)
})
})
3 changes: 1 addition & 2 deletions packages/ethers/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,8 @@ export class Web3Modal extends Web3ModalScaffold {
} else if (providerType !== ConstantsUtil.EMAIL_CONNECTOR_ID) {
provider?.emit('disconnect')
} else {
this.emailProvider?.disconnect()
await this.emailProvider?.disconnect()
}
provider?.emit('disconnect')
},

signMessage: async (message: string) => {
Expand Down