Skip to content

Commit

Permalink
Epic Seedless-onboarding (#2534)
Browse files Browse the repository at this point in the history
- Adds option to create a social signer via google
- Adds Settings page for setting up MFA via password recovery for Social signer
- Redesigns Welcome Page

---------

Co-authored-by: Usame Algan <[email protected]>
Co-authored-by: Usame Algan <[email protected]>
Co-authored-by: Michael <[email protected]>
Co-authored-by: katspaugh <[email protected]>
  • Loading branch information
5 people authored Nov 9, 2023
1 parent b2ba82d commit 798e998
Show file tree
Hide file tree
Showing 129 changed files with 6,109 additions and 640 deletions.
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING=
NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING=

# Redefine
NEXT_PUBLIC_REDEFINE_API=
NEXT_PUBLIC_REDEFINE_API=

# Social Login
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING=
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION=

2 changes: 2 additions & 0 deletions .github/workflows/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ runs:
NEXT_PUBLIC_SAFE_RELAY_SERVICE_URL_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING }}
NEXT_PUBLIC_IS_OFFICIAL_HOST: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_IS_OFFICIAL_HOST }}
NEXT_PUBLIC_REDEFINE_API: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_REDEFINE_API }}
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING }}
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING }}
NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION }}
Expand Down
25 changes: 19 additions & 6 deletions cypress/e2e/pages/create_wallet.pages.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import * as constants from '../../support/constants'

const welcomeLoginScreen = '[data-testid="welcome-login"]'
const expandMoreIcon = 'svg[data-testid="ExpandMoreIcon"]'
const nameInput = 'input[name="name"]'
const selectNetworkBtn = '[data-cy="create-safe-select-network"]'
const ownerInput = 'input[name^="owners"][name$="name"]'
const ownerAddress = 'input[name^="owners"][name$="address"]'
const thresholdInput = 'input[name="threshold"]'
export const removeOwnerBtn = 'button[aria-label="Remove owner"]'
const connectingContainer = 'div[class*="connecting-container"]'
const createNewSafeBtn = 'span[data-track="create-safe: Open stepper"]'
const createNewSafeBtn = 'span[data-track="create-safe: Continue to creation"]'
const connectWalletBtn = 'Connect wallet'

const changeNetworkWarningStr = 'Change your wallet network'
const safeAccountSetupStr = 'Safe Account setup'
const policy1_1 = '1/1 policy'
const policy1_2 = '1/1 policy'
export const walletName = 'test1-sepolia-safe'
export const defaltSepoliaPlaceholder = 'sepolia-safe'
export const defaltSepoliaPlaceholder = 'Sepolia Safe'

export function verifyPolicy1_1() {
cy.contains(policy1_1).should('exist')
cy.contains(policy1_2).should('exist')
// TOD: Need data-cy for containers
}

Expand Down Expand Up @@ -49,13 +52,23 @@ export function clickOnCreateNewSafeBtn() {
cy.get(createNewSafeBtn).click().wait(1000)
}

export function clickOnConnectWalletBtn() {
cy.get(welcomeLoginScreen).within(() => {
cy.get('button').contains(connectWalletBtn).should('be.visible').should('be.enabled').click().wait(1000)
})
}

export function typeWalletName(name) {
cy.get(nameInput).type(name).should('have.value', name)
}

export function clearWalletName() {
cy.get(nameInput).clear()
}

export function selectNetwork(network, regex = false) {
cy.wait(1000)
cy.get(selectNetworkBtn).should('be.visible').click()
cy.get(expandMoreIcon).eq(1).parents('div').eq(1).click()
cy.wait(1000)
cy.get('li').contains(network).click()
cy.get('body').click()
Expand Down Expand Up @@ -91,7 +104,7 @@ export function typeOwnerAddress(address, index, clearOnly = false) {
}

export function clickOnAddNewOwnerBtn() {
cy.contains('button', 'Add new owner').click()
cy.contains('button', 'Add new owner').click().wait(700)
}

export function addNewOwner(name, address, index) {
Expand Down
6 changes: 5 additions & 1 deletion cypress/e2e/pages/import_export.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function clickOnImportBtn() {
}

export function clickOnImportBtnDataImportModal() {
cy.contains(dataImportModalStr).parent().contains('button', 'Import').click()
cy.contains('button', 'Import').click()
}

export function uploadFile(filePath) {
Expand All @@ -44,6 +44,10 @@ export function clickOnImportedSafe(safe) {
cy.contains(safe).click()
}

export function clickOnOpenSafeListSidebar() {
cy.contains('My Safe Accounts').click()
}

export function clickOnClosePushNotificationsBanner() {
cy.waitForSelector(() => {
return cy.get('h6').contains(enablePushNotificationsStr).siblings('.MuiButtonBase-root').click({ force: true })
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/pages/load_safe.pages.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as constants from '../../support/constants'

const addExistingAccountBtnStr = 'Add existing Account'
const addExistingAccountBtnStr = 'Add existing one'
const contactStr = 'Name, address & network'
const invalidAddressFormatErrorMsg = 'Invalid address format'

Expand All @@ -16,7 +16,7 @@ const ownersConfirmationsStr = 'Owners and confirmations'
const transactionStr = 'Transactions'

export function openLoadSafeForm() {
cy.contains('button', addExistingAccountBtnStr).click()
cy.contains('a', addExistingAccountBtnStr).click()
cy.contains(contactStr)
}

Expand Down
7 changes: 4 additions & 3 deletions cypress/e2e/pages/owners.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const thresholdDropdown = 'div[aria-haspopup="listbox"]'
const thresholdOption = 'li[role="option"]'
const existingOwnerAddressInput = (index) => `input[name="owners.${index}.address"]`
const existingOwnerNameInput = (index) => `input[name="owners.${index}.name"]`
const singleOwnerNameInput = 'input[name="name"]'

const disconnectBtnStr = 'Disconnect'
const notConnectedStatus = 'Connect'
Expand Down Expand Up @@ -57,9 +58,9 @@ export function verifyExistingOwnerName(index, name) {
cy.get(existingOwnerNameInput(index)).should('have.value', name)
}

export function typeExistingOwnerName(index, name) {
cy.get(existingOwnerNameInput(index)).clear().type(name)
main.verifyInputValue(existingOwnerNameInput(index), name)
export function typeExistingOwnerName(name) {
cy.get(singleOwnerNameInput).clear().type(name)
main.verifyInputValue(singleOwnerNameInput, name)
}

export function verifyOwnerDeletionWindowDisplayed() {
Expand Down
42 changes: 28 additions & 14 deletions cypress/e2e/smoke/create_safe_simple.cy.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import * as constants from '../../support/constants'
import * as main from '../../e2e/pages/main.page'
import * as createwallet from '../pages/create_wallet.pages'

import * as owner from '../pages/owners.pages'

describe('Safe creation tests', () => {
beforeEach(() => {
cy.visit(constants.createNewSafeSepoliaUrl)
cy.visit(constants.welcomeUrl + '?chain=sep')
cy.clearLocalStorage()
main.acceptCookies()
})

it('Verify a Wallet can be connected [C56101]', () => {
owner.waitForConnectionStatus()
cy.visit(constants.welcomeUrl)
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnWalletExpandMoreIcon()
owner.clickOnDisconnectBtn()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnConnectBtn()
createwallet.clickOnConnectWalletBtn()
createwallet.connectWallet()
})

it('Verify Next button is disabled until switching to network is done [C56102]', () => {
owner.waitForConnectionStatus()
createwallet.selectNetwork(constants.networks.ethereum)
createwallet.clickOnCreateNewSafeBtn()
createwallet.checkNetworkChangeWarningMsg()
createwallet.verifyNextBtnIsDisabled()
createwallet.selectNetwork(constants.networks.sepolia)
Expand All @@ -32,43 +30,49 @@ describe('Safe creation tests', () => {

it('Verify that a new Wallet has default name related to the selected network [C56099]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
createwallet.verifyDefaultWalletName(createwallet.defaltSepoliaPlaceholder)
})

it('Verify error message is displayed if wallet name input exceeds 50 characters [C56098]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
createwallet.typeWalletName(main.generateRandomString(51))
owner.verifyErrorMsgInvalidAddress(constants.addressBookErrrMsg.exceedChars)
createwallet.clearWalletName()
})

it('Verify there is no error message is displayed if wallet name input contains less than 50 characters [C56100]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
createwallet.typeWalletName(main.generateRandomString(50))
owner.verifyValidWalletName(constants.addressBookErrrMsg.exceedChars)
})

it('Verify current connected account is shown as default owner [C56091]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
owner.verifyExistingOwnerAddress(0, constants.DEFAULT_OWNER_ADDRESS)
})

it('Verify error message is displayed if owner name input exceeds 50 characters [C56092]', () => {
owner.waitForConnectionStatus()
owner.clickOnNextBtn()
owner.typeExistingOwnerName(0, main.generateRandomString(51))
createwallet.clickOnCreateNewSafeBtn()
owner.typeExistingOwnerName(main.generateRandomString(51))
owner.verifyErrorMsgInvalidAddress(constants.addressBookErrrMsg.exceedChars)
})

it('Verify there is no error message is displayed if owner name input contains less than 50 characters [C56093]', () => {
owner.waitForConnectionStatus()
owner.clickOnNextBtn()
owner.typeExistingOwnerName(0, main.generateRandomString(50))
createwallet.clickOnCreateNewSafeBtn()
owner.typeExistingOwnerName(main.generateRandomString(50))
owner.verifyValidWalletName(constants.addressBookErrrMsg.exceedChars)
})

it('Verify Add and Remove Owner Row works as expected [C56094]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
owner.verifyNumberOfOwners(2)
Expand All @@ -82,26 +86,34 @@ describe('Safe creation tests', () => {

it('Verify Threshold Setup [C56096]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
owner.verifyNumberOfOwners(2)
createwallet.clickOnAddNewOwnerBtn()
owner.verifyNumberOfOwners(3)
owner.verifyThresholdLimit(1, 3)
createwallet.clickOnAddNewOwnerBtn()
owner.verifyNumberOfOwners(4)
owner.verifyThresholdLimit(1, 4)
createwallet.updateThreshold(3)
createwallet.removeOwner(1)
owner.verifyThresholdLimit(1, 3)
createwallet.removeOwner(1)
owner.verifyThresholdLimit(1, 2)
createwallet.updateThreshold(1)
})

it('Verify data persistence [C56103]', () => {
const ownerName = 'David'
owner.waitForConnectionStatus()
createwallet.typeWalletName(createwallet.walletName)
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
createwallet.typeOwnerName(ownerName, 1)
createwallet.typeOwnerAddress(constants.SEPOLIA_OWNER_2, 1)
owner.verifyThresholdLimit(1, 2)
owner.clickOnBackBtn()
createwallet.clearWalletName()
createwallet.typeWalletName(createwallet.walletName)
owner.clickOnNextBtn()
owner.clickOnNextBtn()
createwallet.verifySafeNameInSummaryStep(createwallet.walletName)
createwallet.verifyOwnerNameInSummaryStep(ownerName)
Expand All @@ -125,12 +137,14 @@ describe('Safe creation tests', () => {

it('Verify tip is displayed on right side for threshold 1/1 [C56097]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
createwallet.verifyPolicy1_1()
})

it('Verify address input validation rules [C56095]', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
createwallet.typeOwnerAddress(main.generateRandomString(10), 1)
Expand Down
6 changes: 3 additions & 3 deletions cypress/e2e/smoke/import_export_data.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import * as constants from '../../support/constants'
describe('Import Export Data tests', () => {
before(() => {
cy.clearLocalStorage()
cy.visit(constants.welcomeUrl)
cy.visit(constants.dataSettingsUrl)
main.acceptCookies()
file.verifyImportBtnIsVisible()
})

it('Verify Safe can be accessed after test file upload [C56111]', () => {
const filePath = '../fixtures/data_import.json'
const safe = constants.SEPOLIA_CSV_ENTRY.name

file.clickOnImportBtn()
file.uploadFile(filePath)
file.verifyImportModalData()
file.clickOnImportBtnDataImportModal()
cy.visit(constants.welcomeUrl)
file.clickOnOpenSafeListSidebar()
file.clickOnImportedSafe(safe)
file.clickOnClosePushNotificationsBanner()
})
Expand Down
1 change: 1 addition & 0 deletions cypress/support/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const requestPermissionsUrl = '/request-permissions'
export const getPermissionsUrl = '/get-permissions'
export const appSettingsUrl = '/settings/safe-apps'
export const setupUrl = '/settings/setup?safe='
export const dataSettingsUrl = '/settings/data'
export const invalidAppUrl = 'https://my-invalid-custom-app.com/manifest.json'
export const validAppUrlJson = 'https://my-valid-custom-app.com/manifest.json'
export const validAppUrl = 'https://my-valid-custom-app.com'
Expand Down
4 changes: 2 additions & 2 deletions jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ const createJestConfig = nextJest({
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],

moduleNameMapper: {
// Handle module aliases (this will be automatically configured for you soon)
'^@/(.*)$': '<rootDir>/src/$1',
'^.+\\.(svg)$': '<rootDir>/mocks/svg.js',
isows: '<rootDir>/node_modules/isows/_cjs/index.js',
},
transformIgnorePatterns: ['node_modules/(?!isows/)'],
testEnvironment: 'jest-environment-jsdom',
testEnvironmentOptions: { url: 'http://localhost/balances?safe=rin:0xb3b83bf204C458B461de9B0CD2739DB152b4fa5A' },
globals: {
Expand All @@ -25,5 +25,5 @@ const customJestConfig = {
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = async () => ({
...(await createJestConfig(customJestConfig)()),
transformIgnorePatterns: ['node_modules/(?!(uint8arrays|multiformats)/)'],
transformIgnorePatterns: ['node_modules/(?!(uint8arrays|multiformats|@web3-onboard/common)/)'],
})
2 changes: 1 addition & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const nextConfig = {
dirs: ['src'],
},
experimental: {
optimizePackageImports: ['@mui/material', '@mui/icons-material', 'lodash', 'date-fns']
optimizePackageImports: ['@mui/material', '@mui/icons-material', 'lodash', 'date-fns'],
},
webpack(config) {
config.module.rules.push({
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
"type": "module",
"version": "1.21.0",
"version": "1.22.0",
"scripts": {
"dev": "next dev",
"start": "next dev",
Expand Down Expand Up @@ -56,6 +56,7 @@
"@safe-global/safe-react-components": "^2.0.6",
"@sentry/react": "^7.74.0",
"@sentry/tracing": "^7.74.0",
"@tkey-mpc/common-types": "^8.2.2",
"@truffle/hdwallet-provider": "^2.1.4",
"@walletconnect/utils": "^2.10.2",
"@walletconnect/web3wallet": "^1.9.2",
Expand All @@ -66,7 +67,9 @@
"@web3-onboard/ledger": "2.3.2",
"@web3-onboard/trezor": "^2.4.2",
"@web3-onboard/walletconnect": "^2.4.7",
"@web3auth/mpc-core-kit": "^1.1.3",
"blo": "^1.1.1",
"bn.js": "^5.2.1",
"classnames": "^2.3.1",
"date-fns": "^2.29.2",
"ethers": "5.7.2",
Expand Down
5 changes: 5 additions & 0 deletions public/images/common/bar-chart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/images/common/check-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/images/common/lock-small.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions public/images/common/lock-warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 798e998

Please sign in to comment.