Skip to content

Commit

Permalink
Phantom - confirmTransaction function updates and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
zgz2020 committed Dec 17, 2024
1 parent 5cef9b2 commit 11af60d
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 118 deletions.
4 changes: 2 additions & 2 deletions wallets/phantom/src/cypress/Phantom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export default class Phantom {
* @param accounts - Optional array of account addresses to connect
* @returns True if the connection was successful
*/
async connectToDapp(accounts?: string[]): Promise<boolean> {
await this.phantomPlaywright.connectToDapp(accounts)
async connectToDapp(account?: string): Promise<boolean> {
await this.phantomPlaywright.connectToDapp(account)
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const approveTokenPermission = async (notificationPage: Page, gasSetting: GasSet
}

const rejectTokenPermission = async (notificationPage: Page) => {
await notificationPage.locator(Selectors.ActionFooter.rejectActionButton).click()
await notificationPage.locator(Selectors.ActionFooter.cancelActionButton).click()
}

export const approvePermission = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ const confirmTransaction = async (notificationPage: Page, options: GasSettings)
}
}

// By default, the `site` gas setting is used.
if (gasSetting === 'site') {
// By default, the `Average` gas setting is used.
if (gasSetting === 'Average') {
await notificationPage.locator(Selectors.ActionFooter.confirmActionButton).click()

await handleNftSetApprovalForAll(notificationPage)
Expand All @@ -38,81 +38,17 @@ const confirmTransaction = async (notificationPage: Page, options: GasSettings)
// TODO: This button can be invisible in case of a network issue. Verify this, and handle in the future.
await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.editGasFeeButton).click()

const estimationNotAvailableErrorMessage = (gasSetting: string) =>
`[ConfirmTransaction] Estimated fee is not available for the "${gasSetting}" gas setting. By default, Phantom would use the "site" gas setting in this case, however, this is not YOUR intention.`

const handleLowMediumOrAggressiveGasSetting = async (
gasSetting: string,
selectors: { button: string; maxFee: string }
) => {
if ((await notificationPage.locator(selectors.maxFee).textContent()) === '--') {
throw new Error(estimationNotAvailableErrorMessage(gasSetting))
}

await notificationPage.locator(selectors.button).click()
}

if (gasSetting === 'low') {
await handleLowMediumOrAggressiveGasSetting(gasSetting, Selectors.TransactionPage.editGasFeeMenu.lowGasFee)
} else if (gasSetting === 'market') {
await handleLowMediumOrAggressiveGasSetting(gasSetting, Selectors.TransactionPage.editGasFeeMenu.marketGasFee)
} else if (gasSetting === 'aggressive') {
await handleLowMediumOrAggressiveGasSetting(gasSetting, Selectors.TransactionPage.editGasFeeMenu.aggressiveGasFee)
} else {
await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeButton).click()

await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.maxBaseFeeInput).fill('')
await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.maxBaseFeeInput)
.fill(gasSetting.maxBaseFee.toString())

await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.priorityFeeInput)
.fill('')
await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.priorityFeeInput)
.fill(gasSetting.priorityFee.toString())

if (gasSetting.gasLimit) {
await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.gasLimitEditButton)
.click()

await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.gasLimitInput).fill('')
await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.gasLimitInput)
.fill(gasSetting.gasLimit.toString())

const gasLimitErrorLocator = notificationPage.locator(
Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.gasLimitError
)
const isGasLimitErrorHidden = await waitFor(() => gasLimitErrorLocator.isHidden(), 1_000, false) // TODO: Extract & make configurable

if (!isGasLimitErrorHidden) {
const errorText = await gasLimitErrorLocator.textContent({
timeout: 1_000 // TODO: Extract & make configurable
})

throw new Error(`[ConfirmTransaction] Invalid gas limit: ${errorText}`)
}
}

await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.advancedGasFeeMenu.saveButton).click()
const handleSlowOrFastGasSetting = async (selector: string) => {
await notificationPage.locator(selector).click()
}

// We wait until the tooltip is not visible anymore. This indicates a gas setting was changed.
// Ideally, we would wait until the edit button changes its text, i.e., "Site" -> "Aggressive", however, this is not possible right now.
// For some unknown reason, if the manual gas setting is too high (>1 ETH), the edit button displays "Site" instead of "Advanced" ¯\_(ツ)_/¯
const waitForAction = async () => {
const isTooltipVisible = await notificationPage
.locator(Selectors.TransactionPage.editGasFeeMenu.editGasFeeButtonToolTip)
.isVisible()

return !isTooltipVisible
if (gasSetting === 'Slow') {
await handleSlowOrFastGasSetting(Selectors.TransactionPage.editGasFeeMenu.slowGasFeeButton)
} else if (gasSetting === 'Fast') {
await handleSlowOrFastGasSetting(Selectors.TransactionPage.editGasFeeMenu.fastGasFeeButton)
}

// TODO: Extract & make configurable
await waitFor(waitForAction, 3_000, true)
await notificationPage.locator(Selectors.TransactionPage.editGasFeeMenu.saveButton).click()

await notificationPage.locator(Selectors.ActionFooter.confirmActionButton).click()

Expand Down Expand Up @@ -154,7 +90,7 @@ const confirmTransactionAndWaitForMining = async (walletPage: Page, notification
}

const rejectTransaction = async (notificationPage: Page) => {
await notificationPage.locator(Selectors.ActionFooter.rejectActionButton).click()
await notificationPage.locator(Selectors.ActionFooter.cancelActionButton).click()
}

export const transaction = {
Expand Down
6 changes: 3 additions & 3 deletions wallets/phantom/src/playwright/pages/NotificationPage/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class NotificationPage {
async confirmTransaction(extensionId: string, options?: { gasSetting?: GasSettings }) {
const notificationPage = await getNotificationPageAndWaitForLoad(this.page.context(), extensionId)

await transaction.confirm(notificationPage, options?.gasSetting ?? 'site')
await transaction.confirm(notificationPage, options?.gasSetting ?? 'Average')
}

async rejectTransaction(extensionId: string) {
Expand All @@ -89,7 +89,7 @@ export class NotificationPage {
async confirmTransactionAndWaitForMining(extensionId: string, options?: { gasSetting?: GasSettings }) {
const notificationPage = await getNotificationPageAndWaitForLoad(this.page.context(), extensionId)

await transaction.confirmAndWaitForMining(this.page, notificationPage, options?.gasSetting ?? 'site')
await transaction.confirmAndWaitForMining(this.page, notificationPage, options?.gasSetting ?? 'Average')
}

async approveTokenPermission(
Expand All @@ -102,7 +102,7 @@ export class NotificationPage {
await approvePermission.editTokenPermission(notificationPage, options.spendLimit)
}

await approvePermission.approve(notificationPage, options?.gasSetting ?? 'site')
await approvePermission.approve(notificationPage, options?.gasSetting ?? 'Average')
}

async rejectTokenPermission(extensionId: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
import { createDataTestSelector } from '../../createDataTestSelector'

const advancedGasFeeMenu = {
maxBaseFeeInput: createDataTestSelector('base-fee-input'),
priorityFeeInput: createDataTestSelector('priority-fee-input'),
gasLimitEditButton: createDataTestSelector('advanced-gas-fee-edit'),
gasLimitInput: createDataTestSelector('gas-limit-input'),
gasLimitError: `div:has(> ${createDataTestSelector('gas-limit-input')}) + .form-field__error`,
saveButton: '.popover-footer > button.btn-primary'
}

const lowGasFee = {
button: createDataTestSelector('edit-gas-fee-item-low'),
maxFee: `${createDataTestSelector('edit-gas-fee-item-low')} .edit-gas-item__fee-estimate`
}

const marketGasFee = {
button: createDataTestSelector('edit-gas-fee-item-medium'),
maxFee: `${createDataTestSelector('edit-gas-fee-item-medium')} .edit-gas-item__fee-estimate`
}

const aggressiveGasFee = {
button: createDataTestSelector('edit-gas-fee-item-high'),
maxFee: `${createDataTestSelector('edit-gas-fee-item-high')} .edit-gas-item__fee-estimate`
}

const editGasFeeMenu = {
editGasFeeButton: createDataTestSelector('edit-gas-fee-icon'),
editGasFeeButtonToolTip: '.edit-gas-fee-button .info-tooltip',
lowGasFee,
marketGasFee,
aggressiveGasFee,
siteSuggestedGasFeeButton: createDataTestSelector('edit-gas-fee-item-dappSuggested'),
advancedGasFeeButton: createDataTestSelector('edit-gas-fee-item-custom'),
advancedGasFeeMenu
editGasFeeButton: 'div > div p:has-text("Network Fee")',
slowGasFeeButton: 'div > div p:has-text("Slow")',
fastGasFeeButton: 'div > div p:has-text("Fast")',
saveButton: 'button:has-text("Save")'
}

const nftApproveAllConfirmationPopup = {
Expand Down
7 changes: 3 additions & 4 deletions wallets/phantom/src/type/GasSettings.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { z } from 'zod'

export const GasSettingValidation = z.union([
z.literal('low'),
z.literal('market'),
z.literal('aggressive'),
z.literal('site'),
z.literal('Slow'),
z.literal('Fast'),
z.literal('Average'),
z
.object({
maxBaseFee: z.number(),
Expand Down
30 changes: 30 additions & 0 deletions wallets/phantom/test/playwright/e2e/confirmTransaction.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { connectPhantomToTestDapp } from '../commonSteps/connectPhantomToTestDapp'
import synpress from '../synpress'

const test = synpress

const { expect } = test

test('should confirm contract deployment with default gas setting', async ({ page, phantom }) => {
connectPhantomToTestDapp(page, phantom)

await expect(page.locator('#tokenAddresses')).toBeEmpty()
await page.locator('#createToken').click()

await phantom.confirmTransaction()

await expect(page.locator('#tokenAddresses')).toContainText('Creation Failed')
})

;(['Slow', 'Fast'] as const).forEach((gasSetting) => {
test(`should confirm contract deployment with ${gasSetting} gas setting`, async ({ page, phantom }) => {
connectPhantomToTestDapp(page, phantom)

await expect(page.locator('#tokenAddresses')).toBeEmpty()
await page.locator('#createToken').click()

await phantom.confirmTransaction({ gasSetting })

await expect(page.locator('#tokenAddresses')).toContainText('Creation Failed')
})
})

0 comments on commit 11af60d

Please sign in to comment.