Skip to content

Commit

Permalink
fix: add remaining tests for WalletConnectWallet
Browse files Browse the repository at this point in the history
  • Loading branch information
iamacook committed Sep 28, 2023
1 parent cfed8b8 commit c7f0e7a
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 38 deletions.
9 changes: 6 additions & 3 deletions jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ const customJestConfig = {
testEnvironment: 'jest-environment-jsdom',
testEnvironmentOptions: { url: 'http://localhost/balances?safe=rin:0xb3b83bf204C458B461de9B0CD2739DB152b4fa5A' },
globals: {
fetch: global.fetch
}
fetch: global.fetch,
},
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
module.exports = async () => ({
...(await createJestConfig(customJestConfig)()),
transformIgnorePatterns: ['node_modules/(?!(uint8arrays)/)'],
})
173 changes: 144 additions & 29 deletions src/services/walletconnect/WalletConnectWallet.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hexZeroPad } from 'ethers/lib/utils'
import type { ProposalTypes, SessionTypes, SignClientTypes, Verify } from '@walletconnect/types'
import type { IWeb3Wallet } from '@walletconnect/web3wallet'
import type { IWeb3Wallet, Web3WalletTypes } from '@walletconnect/web3wallet'

import WalletConnectWallet from './WalletConnectWallet'

Expand All @@ -22,37 +22,25 @@ jest.mock('@walletconnect/web3wallet', () => {
},
} as unknown as IWeb3Wallet['core']

on = jest.fn()

off = jest.fn()

approveSession = jest.fn()
updateSession = jest.fn()
disconnectSession = jest.fn()

getActiveSessions = jest.fn()

respondSessionRequest = jest.fn()

emitSessionEvent = jest.fn()

updateSession = jest.fn()

approveSession = jest.fn()

events = {
emit: jest.fn(),
} as unknown as IWeb3Wallet['events']
}
on = jest.fn()
off = jest.fn()

return {
Web3Wallet: MockWeb3Wallet,
emitSessionEvent = jest.fn()
}
})

jest.mock('@walletconnect/utils', () => {
// TODO: Import actual utils from @walletconnect/utils in order to complete todo tests
return {
getSdkError: jest.fn(() => ({ message: 'error' })),
buildApprovedNamespaces: jest.fn(() => ({})),
Web3Wallet: MockWeb3Wallet,
}
})

Expand Down Expand Up @@ -110,10 +98,89 @@ describe('WalletConnectWallet', () => {
})

describe('approveSession', () => {
it.todo('should approve the session with the correct namespace')
it('should approve the session with proposed required/optional chains/methods and required events', async () => {
const approveSessionSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'approveSession')

const proposal = {
id: 123,
params: {
id: 456,
pairingTopic: 'pairingTopic',
expiry: 789,
requiredNamespaces: {
eip155: {
chains: ['eip155:1'],
methods: ['eth_sendTransaction', 'personal_sign'],
events: ['chainChanged', 'accountsChanged'],
},
},
optionalNamespaces: {
eip155: {
chains: ['eip155:43114', 'eip155:42161', 'eip155:8453', 'eip155:100', 'eip155:137', 'eip155:1101'],
// Not included as optional
methods: [
'eth_sendTransaction',
'personal_sign',
'eth_accounts',
'eth_requestAccounts',
'eth_sendRawTransaction',
'eth_sign',
'eth_signTransaction',
'eth_signTypedData',
'eth_signTypedData_v3',
'eth_signTypedData_v4',
'wallet_switchEthereumChain',
'wallet_addEthereumChain',
'wallet_getPermissions',
'wallet_requestPermissions',
'wallet_registerOnboarding',
'wallet_watchAsset',
'wallet_scanQRCode',
],
events: ['chainChanged', 'accountsChanged', 'message', 'disconnect', 'connect'],
},
},
},
} as unknown as Web3WalletTypes.SessionProposal

await wallet.approveSession(
proposal,
'69420', // Not in proposal, therefore not supported
hexZeroPad('0x123', 20),
)

const namespaces = {
eip155: {
chains: [
'eip155:1',
'eip155:43114',
'eip155:42161',
'eip155:8453',
'eip155:100',
'eip155:137',
'eip155:1101',
],
methods: ['eth_sendTransaction', 'personal_sign'],
events: ['chainChanged', 'accountsChanged'],
accounts: [
`eip155:1:${hexZeroPad('0x123', 20)}`,
`eip155:43114:${hexZeroPad('0x123', 20)}`,
`eip155:42161:${hexZeroPad('0x123', 20)}`,
`eip155:8453:${hexZeroPad('0x123', 20)}`,
`eip155:100:${hexZeroPad('0x123', 20)}`,
`eip155:137:${hexZeroPad('0x123', 20)}`,
`eip155:1101:${hexZeroPad('0x123', 20)}`,
],
},
}

expect(approveSessionSpy).toHaveBeenCalledWith({
id: 123,
namespaces,
})
})

it('should call emitSessionEvent with the correct parameters', async () => {
const approveSessionSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'approveSession')
const emitSpy = jest.spyOn(((wallet as any).web3Wallet as IWeb3Wallet).events, 'emit')

await wallet.approveSession(
Expand All @@ -136,21 +203,68 @@ describe('WalletConnectWallet', () => {
hexZeroPad('0x123', 20),
)

expect(approveSessionSpy).toHaveBeenCalled()

expect(emitSpy).toHaveBeenCalledWith('session_add')
})
})

describe('updateSession', () => {
it.todo('should update the session with the correct namespace')
it('should update the session with the correct namespace', async () => {
const updateSessionSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'updateSession')
const emitSessionEventSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'emitSessionEvent')

const session = {
topic: 'topic1',
namespaces: {
eip155: {
chains: ['eip155:1'],
accounts: [`eip155:1:${hexZeroPad('0x123', 20)}`],
events: ['chainChanged', 'accountsChanged'],
methods: [],
},
},
} as unknown as SessionTypes.Struct

it.todo('should not update the session if the chainId or account is already in the namespace')
await (wallet as any).updateSession(session, '69420', hexZeroPad('0x123', 20))

it('should call emitSessionEvent with the correct parameters', async () => {
expect(updateSessionSpy).toHaveBeenCalledWith({
topic: 'topic1',
namespaces: {
eip155: {
chains: ['eip155:69420', 'eip155:1'],
accounts: [`eip155:69420:${hexZeroPad('0x123', 20)}`, `eip155:1:${hexZeroPad('0x123', 20)}`],
events: ['chainChanged', 'accountsChanged'],
methods: [],
},
},
})

expect(emitSessionEventSpy).toHaveBeenCalledTimes(2)
})

it('should not update the session if the chainId and account is already in the namespace', async () => {
const updateSessionSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'updateSession')
const emitSessionEventSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'emitSessionEvent')

const session = {
topic: 'topic1',
namespaces: {
eip155: {
chains: ['eip155:1'],
accounts: [`eip155:1:${hexZeroPad('0x123', 20)}`],
},
},
} as unknown as SessionTypes.Struct

await (wallet as any).updateSession(session, '1', hexZeroPad('0x123', 20))

expect(updateSessionSpy).not.toHaveBeenCalled()

expect(emitSessionEventSpy).toHaveBeenCalledTimes(2)
})

it('should call emitSessionEvent with the correct parameters', async () => {
const emitSessionEventSpy = jest.spyOn((wallet as any).web3Wallet as IWeb3Wallet, 'emitSessionEvent')

await (wallet as any).updateSession(
{
topic: 'topic1',
Expand All @@ -160,8 +274,6 @@ describe('WalletConnectWallet', () => {
hexZeroPad('0x123', 20),
)

expect(updateSessionSpy).toHaveBeenCalled()

expect(emitSessionEventSpy).toHaveBeenCalledWith({
topic: 'topic1',
event: {
Expand Down Expand Up @@ -260,7 +372,10 @@ describe('WalletConnectWallet', () => {

expect(disconnectSessionSpy).toHaveBeenCalledWith({
topic: 'topic1',
reason: expect.any(Object),
reason: {
code: 6000,
message: 'User disconnected.',
},
})
})
})
Expand Down
10 changes: 4 additions & 6 deletions src/services/walletconnect/WalletConnectWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class WalletConnectWallet {
const eip155ChainIds = chainIds.map(getEip155ChainId)

// Create a list of addresses for each chainId
const eip155Accounts = chainIds.map((chainId) => `${getEip155ChainId(chainId)}:${safeAddress}`)
const eip155Accounts = eip155ChainIds.map((eip155ChainId) => `${eip155ChainId}:${safeAddress}`)

return buildApprovedNamespaces({
proposal: proposal.params,
Expand All @@ -98,6 +98,7 @@ class WalletConnectWallet {
chains: eip155ChainIds,
methods,
accounts: eip155Accounts,
// Don't include optionalNamespaces events
events: proposal.params.requiredNamespaces[EIP155]?.events || [],
},
},
Expand Down Expand Up @@ -137,14 +138,11 @@ class WalletConnectWallet {

// Add new chainId and/or account to the session namespace
if (hasNewChainId || hasNewAccount) {
const uniqueEip155ChainIds = [...new Set([newEip155ChainId, ...currentEip155ChainIds])]
const unqiueEip155Accounts = [...new Set([newEip155Account, ...currentEip155Accounts])]

const namespaces: SessionTypes.Namespaces = {
[EIP155]: {
...session.namespaces[EIP155],
chains: uniqueEip155ChainIds,
accounts: unqiueEip155Accounts,
chains: [newEip155ChainId, ...currentEip155ChainIds],
accounts: [newEip155Account, ...currentEip155Accounts],
},
}

Expand Down

0 comments on commit c7f0e7a

Please sign in to comment.