Skip to content

Commit

Permalink
test: check addressbook upsert
Browse files Browse the repository at this point in the history
  • Loading branch information
schmanu committed Oct 20, 2023
1 parent df74f4e commit 99bad90
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
26 changes: 24 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,16 @@ 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 chains from '@/hooks/useChains'
import { hexZeroPad } from 'ethers/lib/utils'
import { type ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'
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 +74,10 @@ class MockMPCCoreKit {
commitChanges() {
return Promise.resolve()
}

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

describe('useMPCWallet', () => {
Expand All @@ -76,6 +87,9 @@ describe('useMPCWallet', () => {
beforeEach(() => {
jest.resetAllMocks()
setMPCCoreKitInstance(undefined)
jest
.spyOn(chains, 'useCurrentChain')
.mockReturnValue({ chainId: '100', disabledWallets: [] } as unknown as ChainInfo)
})
afterAll(() => {
jest.useRealTimers()
Expand All @@ -94,6 +108,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 +117,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 +152,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 +201,7 @@ describe('useMPCWallet', () => {
disableModals: true,
},
})
expect(upsertABSpy).not.toHaveBeenCalled()
})
})

Expand Down
19 changes: 18 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 { useCurrentChain } from '@/hooks/useChains'
import { upsertAddressBookEntry } from '@/store/addressBookSlice'
import { useAppDispatch } from '@/store'
import { ethers } from 'ethers'

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 = useCurrentChain()
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,21 @@ 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 it as the user's first name
if (wallets && currentChainId && wallets.length > 0) {
const signerAddress = ethers.utils.getAddress(wallets[0].accounts[0]?.address)
if (addressBook[signerAddress] === undefined) {
const email = mpcCoreKit.getUserInfo().email
dispatch(upsertAddressBookEntry({ address: signerAddress, chainId: currentChainId.chainId, name: email }))
}
}
setWalletState(MPCWalletState.READY)
}
}
Expand Down

0 comments on commit 99bad90

Please sign in to comment.