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

[Seedless-Onboarding] Add signer account to address book on login #2672

Merged
merged 2 commits into from
Oct 23, 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
23 changes: 21 additions & 2 deletions src/hooks/wallets/mpc/__tests__/useMPCWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ import { setMPCCoreKitInstance } from '../useMPC'
import { ONBOARD_MPC_MODULE_LABEL } from '@/services/mpc/module'
import { ethers } from 'ethers'
import BN from 'bn.js'
import * as addressBookSlice from '@/store/addressBookSlice'
import * as useChainId from '@/hooks/useChainId'
import { hexZeroPad } from 'ethers/lib/utils'
import * as useAddressBook from '@/hooks/useAddressBook'

/** time until mock login resolves */
const MOCK_LOGIN_TIME = 1000
/** Mock address for successful login */
const mockSignerAddress = hexZeroPad('0x1', 20)

/**
* Helper class for mocking MPC Core Kit login flow
Expand Down Expand Up @@ -67,6 +73,10 @@ class MockMPCCoreKit {
commitChanges() {
return Promise.resolve()
}

getUserInfo() {
return this.state.userInfo
}
}

describe('useMPCWallet', () => {
Expand All @@ -76,6 +86,7 @@ describe('useMPCWallet', () => {
beforeEach(() => {
jest.resetAllMocks()
setMPCCoreKitInstance(undefined)
jest.spyOn(useChainId, 'default').mockReturnValue('100')
})
afterAll(() => {
jest.useRealTimers()
Expand All @@ -94,6 +105,7 @@ describe('useMPCWallet', () => {
})

it('should throw if MPC Core Kit is not initialized', () => {
jest.spyOn(useAddressBook, 'default').mockReturnValue({})
jest.spyOn(useOnboard, 'default').mockReturnValue({} as unknown as OnboardAPI)
const { result } = renderHook(() => useMPCWallet())

Expand All @@ -102,8 +114,10 @@ describe('useMPCWallet', () => {
})

it('should handle successful log in for SFA account', async () => {
jest.spyOn(useAddressBook, 'default').mockReturnValue({})
const upsertABSpy = jest.spyOn(addressBookSlice, 'upsertAddressBookEntry')
jest.spyOn(useOnboard, 'default').mockReturnValue({} as unknown as OnboardAPI)
const connectWalletSpy = jest.fn().mockImplementation(() => Promise.resolve())
const connectWalletSpy = jest.fn().mockResolvedValue([{ accounts: [{ address: mockSignerAddress }] }])
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(connectWalletSpy)
setMPCCoreKitInstance(
new MockMPCCoreKit(COREKIT_STATUS.LOGGED_IN, {
Expand Down Expand Up @@ -135,13 +149,17 @@ describe('useMPCWallet', () => {
disableModals: true,
},
})
expect(upsertABSpy).toBeCalledWith({ address: mockSignerAddress, name: '[email protected]', chainId: '100' })
})
})

it('should handle successful log in for MFA account with device share', async () => {
jest.spyOn(useAddressBook, 'default').mockReturnValue({ [mockSignerAddress]: 'Some name' })
const upsertABSpy = jest.spyOn(addressBookSlice, 'upsertAddressBookEntry')
const mockDeviceFactor = ethers.Wallet.createRandom().privateKey.slice(2)
jest.spyOn(useOnboard, 'default').mockReturnValue({} as unknown as OnboardAPI)
const connectWalletSpy = jest.fn().mockImplementation(() => Promise.resolve())
const connectWalletSpy = jest.fn().mockResolvedValue([{ accounts: [{ address: mockSignerAddress }] }])

jest.spyOn(useOnboard, 'connectWallet').mockImplementation(connectWalletSpy)
setMPCCoreKitInstance(
new MockMPCCoreKit(
Expand Down Expand Up @@ -180,6 +198,7 @@ describe('useMPCWallet', () => {
disableModals: true,
},
})
expect(upsertABSpy).not.toHaveBeenCalled()
})
})

Expand Down
22 changes: 21 additions & 1 deletion src/hooks/wallets/mpc/useMPCWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import { SecurityQuestionRecovery } from './recovery/SecurityQuestionRecovery'
import { DeviceShareRecovery } from './recovery/DeviceShareRecovery'
import { trackEvent } from '@/services/analytics'
import { MPC_WALLET_EVENTS } from '@/services/analytics/events/mpcWallet'
import useAddressBook from '@/hooks/useAddressBook'
import { upsertAddressBookEntry } from '@/store/addressBookSlice'
import { useAppDispatch } from '@/store'
import useChainId from '@/hooks/useChainId'
import { checksumAddress } from '@/utils/addresses'

export enum MPCWalletState {
NOT_INITIALIZED,
Expand All @@ -30,6 +35,9 @@ export const useMPCWallet = (): MPCWalletHook => {
const [walletState, setWalletState] = useState(MPCWalletState.NOT_INITIALIZED)
const mpcCoreKit = useMPC()
const onboard = useOnboard()
const addressBook = useAddressBook()
const currentChainId = useChainId()
const dispatch = useAppDispatch()

const criticalResetAccount = async (): Promise<void> => {
// This is a critical function that should only be used for testing purposes
Expand Down Expand Up @@ -99,12 +107,24 @@ export const useMPCWallet = (): MPCWalletHook => {
if (mpcCoreKit.status === COREKIT_STATUS.LOGGED_IN) {
await mpcCoreKit.commitChanges()

await connectWallet(onboard, {
const wallets = await connectWallet(onboard, {
autoSelect: {
label: ONBOARD_MPC_MODULE_LABEL,
disableModals: true,
},
}).catch((reason) => console.error('Error connecting to MPC module:', reason))

// If the signer is not in the address book => add the user's email as name
if (wallets && currentChainId && wallets.length > 0) {
const address = wallets[0].accounts[0]?.address
if (address) {
const signerAddress = checksumAddress(address)
if (addressBook[signerAddress] === undefined) {
const email = mpcCoreKit.getUserInfo().email
dispatch(upsertAddressBookEntry({ address: signerAddress, chainId: currentChainId, name: email }))
}
}
}
setWalletState(MPCWalletState.READY)
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/utils/addresses.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { getAddress } from 'ethers/lib/utils'
import { isAddress } from '@ethersproject/address'

/**
* Checksums the given address
* @param address ethereum address
* @returns the checksummed address if the given address is valid otherwise returns the address unchanged
*/
export const checksumAddress = (address: string): string => {
return isAddress(address) ? getAddress(address) : address
}
Expand Down
Loading