Skip to content

Commit

Permalink
fix: close modal after switching to supported network from unsupporte…
Browse files Browse the repository at this point in the history
…d network (#3352)
  • Loading branch information
svenvoskamp authored Nov 28, 2024
1 parent 960a244 commit 824f1df
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 31 deletions.
2 changes: 0 additions & 2 deletions .changeset/curly-cameras-call.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
---
'@reown/appkit-siwe': patch
'@apps/demo': patch
'@apps/gallery': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-polkadot': patch
Expand Down
20 changes: 20 additions & 0 deletions .changeset/fluffy-beans-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@reown/appkit': patch
'@reown/appkit-core': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-common': patch
'@reown/appkit-experimental': patch
'@reown/appkit-polyfills': patch
'@reown/appkit-scaffold-ui': patch
'@reown/appkit-siwe': patch
'@reown/appkit-siwx': patch
'@reown/appkit-ui': patch
'@reown/appkit-wallet': patch
---

Fix an issue when modal keeps in infinite spinning state when switching to a supported network from unsupported network view
2 changes: 0 additions & 2 deletions .changeset/long-bags-shave.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
'@reown/appkit-core': patch
'@reown/appkit-siwe': patch
'@reown/appkit-siwx': patch
'@apps/gallery': patch
'@reown/appkit-cdn': patch
'@reown/appkit-ui': patch
'@apps/demo': patch
---

Fix issue where it is not possible to switch network with MM mobile wallet
4 changes: 3 additions & 1 deletion apps/laboratory/tests/wallet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ sampleWalletTest('it should disconnect and connect to a single account', async (
})

sampleWalletTest(
'it should show switch network modal if network is not supported',
'it should show switch network modal if network is not supported and switch to supported network',
async ({ library }) => {
if (library === 'solana') {
return
Expand All @@ -203,6 +203,8 @@ sampleWalletTest(
await walletPage.enableTestnets()
await walletPage.switchNetwork('eip155:5')
await modalValidator.expectNetworkNotSupportedVisible()
await walletPage.switchNetwork('eip155:1')
await modalValidator.expectConnected()
await modalPage.closeModal()
}
)
Expand Down
8 changes: 4 additions & 4 deletions packages/appkit-new/src/tests/appkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ describe('Base', () => {
expect(AccountController.setStatus).toHaveBeenCalledWith('disconnected', 'eip155')
})

it('should show unsupported chain UI when synced chainId is not supported', async () => {
it('should set unsupported chain when synced chainId is not supported', async () => {
vi.mocked(ChainController).state = {
chains: new Map([['eip155', { namespace: 'eip155' }]]),
activeChain: 'eip155'
Expand All @@ -547,6 +547,8 @@ describe('Base', () => {

vi.spyOn(appKit as any, 'getAdapter').mockReturnValue(mockAdapter)

vi.spyOn(appKit as any, 'setUnsupportedNetwork').mockImplementation(vi.fn())

vi.spyOn(StorageUtil, 'setConnectedConnector').mockImplementation(vi.fn())
vi.spyOn(StorageUtil, 'setConnectedNamespace').mockImplementation(vi.fn())

Expand All @@ -560,11 +562,9 @@ describe('Base', () => {
return undefined
})

vi.mocked(ChainController.showUnsupportedChainUI).mockImplementation(vi.fn())

await (appKit as any).syncExistingConnection()

expect(ChainController.showUnsupportedChainUI).toHaveBeenCalled()
expect((appKit as any).setUnsupportedNetwork).toHaveBeenCalled()
})
})
describe('Base Initialization', () => {
Expand Down
51 changes: 31 additions & 20 deletions packages/appkit/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,29 @@ export class AppKit {
return null
}

private setUnsupportedNetwork(chainId: string | number) {
const namespace = this.getActiveChainNamespace()

if (namespace) {
ChainController.setActiveCaipNetwork({
id: chainId,
caipNetworkId: `${namespace}:${chainId}`,
name: 'Unknown Network',
chainNamespace: namespace,
nativeCurrency: {
name: '',
decimals: 0,
symbol: ''
},
rpcUrls: {
default: {
http: []
}
}
})
}
}

private extendCaipNetworks(options: AppKitOptions) {
const extendedNetworks = CaipNetworksUtil.extendCaipNetworks(options.networks, {
customNetworkImageUrls: options.chainImages,
Expand Down Expand Up @@ -774,7 +797,9 @@ export class AppKit {
}

if (!this.caipNetworks?.some(network => network.id === res?.chainId)) {
ChainController.showUnsupportedChainUI()
if (res?.chainId) {
this.setUnsupportedNetwork(res.chainId)
}
}
},
reconnectExternal: async ({ id, info, type, provider }) => {
Expand Down Expand Up @@ -1161,23 +1186,7 @@ export class AppKit {
const currentCaipNetwork = this.getCaipNetwork()

if (!caipNetwork) {
const namespace = this.getActiveChainNamespace() || ConstantsUtil.CHAIN.EVM
ChainController.setActiveCaipNetwork({
id: chainId,
caipNetworkId: `${namespace}:${chainId}`,
name: 'Unknown Network',
chainNamespace: namespace,
nativeCurrency: {
name: '',
decimals: 0,
symbol: ''
},
rpcUrls: {
default: {
http: []
}
}
})
this.setUnsupportedNetwork(chainId)

return
}
Expand Down Expand Up @@ -1214,7 +1223,7 @@ export class AppKit {
})
}
} else {
ChainController.showUnsupportedChainUI()
this.setUnsupportedNetwork(chainId)
}
})

Expand Down Expand Up @@ -1566,7 +1575,9 @@ export class AppKit {
}

if (!this.caipNetworks?.some(network => network.id === res?.chainId)) {
ChainController.showUnsupportedChainUI()
if (res?.chainId) {
this.setUnsupportedNetwork(res.chainId)
}
}
} else if (connectedConnector !== UtilConstantsUtil.CONNECTOR_TYPE_W3M_AUTH) {
this.setStatus('disconnected', ChainController.state.activeChain as ChainNamespace)
Expand Down
6 changes: 4 additions & 2 deletions packages/appkit/src/tests/appkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ describe('Base', () => {
expect(AccountController.setStatus).toHaveBeenCalledWith('disconnected', 'eip155')
})

it('should show unsupported chain UI when synced chainId is not supported', async () => {
it('should set unsupported chain when synced chainId is not supported', async () => {
const isClientSpy = vi.spyOn(CoreHelperUtil, 'isClient').mockReturnValue(true)
vi.mocked(ChainController).state = {
chains: new Map([['eip155', { namespace: 'eip155' }]]),
Expand All @@ -552,6 +552,8 @@ describe('Base', () => {
vi.spyOn(StorageUtil, 'setConnectedConnector').mockImplementation(vi.fn())
vi.spyOn(StorageUtil, 'setConnectedNamespace').mockImplementation(vi.fn())

vi.spyOn(appKit as any, 'setUnsupportedNetwork').mockImplementation(vi.fn())

vi.spyOn(SafeLocalStorage, 'getItem').mockImplementation((key: string) => {
if (key === SafeLocalStorageKeys.CONNECTED_CONNECTOR) {
return 'test-wallet'
Expand All @@ -566,7 +568,7 @@ describe('Base', () => {

await (appKit as any).syncExistingConnection()

expect(ChainController.showUnsupportedChainUI).toHaveBeenCalled()
expect((appKit as any).setUnsupportedNetwork).toHaveBeenCalled()
expect(isClientSpy).toHaveBeenCalled()
})
})
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/controllers/ChainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CoreHelperUtil } from '../utils/CoreHelperUtil.js'
import { ConstantsUtil } from '../utils/ConstantsUtil.js'
import { ModalController } from './ModalController.js'
import { EventsController } from './EventsController.js'
import { RouterController } from './RouterController.js'

// -- Constants ----------------------------------------- //
const accountState: AccountControllerState = {
Expand Down Expand Up @@ -241,12 +242,23 @@ export const ChainController = {
},

async switchActiveNetwork(network: CaipNetwork) {
const activeAdapter = ChainController.state.chains.get(
ChainController.state.activeChain as ChainNamespace
)

const unsupportedNetwork = !activeAdapter?.caipNetworks?.some(
caipNetwork => caipNetwork.id === network.id
)
const networkControllerClient = this.getNetworkControllerClient(network.chainNamespace)

if (networkControllerClient) {
await networkControllerClient.switchCaipNetwork(network)
}

if (unsupportedNetwork) {
RouterController.goBack()
}

this.setActiveCaipNetwork(network)

if (network) {
Expand Down
39 changes: 39 additions & 0 deletions packages/core/tests/controllers/ChainController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { ChainController } from '../../src/controllers/ChainController.js'
import { type ConnectionControllerClient } from '../../src/controllers/ConnectionController.js'
import type { NetworkControllerClient } from '../../exports/index.js'
import { RouterController } from '../../src/controllers/RouterController.js'

// -- Setup --------------------------------------------------------------------
const chainNamespace = 'eip155' as ChainNamespace
Expand Down Expand Up @@ -266,4 +267,42 @@ describe('ChainController', () => {
expect(ChainController.getAccountProp('socialProvider', chainNamespace)).toEqual(undefined)
expect(ChainController.getAccountProp('socialWindow', chainNamespace)).toEqual(undefined)
})

it('Expect modal to close after switching from unsupported network to supported network', async () => {
// Mock RouterController.goBack
const routerGoBackSpy = vi.spyOn(RouterController, 'goBack')

// Setup adapter with limited network support
const limitedEvmAdapter = {
namespace: ConstantsUtil.CHAIN.EVM,
connectionControllerClient,
networkControllerClient,
caipNetworks: [
{
id: 1,
caipNetworkId: 'eip155:1',
name: 'Ethereum',
chainNamespace: ConstantsUtil.CHAIN.EVM
}
] as unknown as CaipNetwork[]
}

ChainController.state.activeCaipNetwork = {
id: 42161,
caipNetworkId: 'eip155:42161',
name: 'Arbitrum One',
chainNamespace: ConstantsUtil.CHAIN.EVM,
nativeCurrency: {
name: 'Arbitrum',
symbol: 'ARB',
decimals: 18
}
} as unknown as CaipNetwork
ChainController.state.chains.set(ConstantsUtil.CHAIN.EVM, limitedEvmAdapter)
await ChainController.switchActiveNetwork(caipNetwork)

expect(routerGoBackSpy).toHaveBeenCalled()

routerGoBackSpy.mockRestore()
})
})

0 comments on commit 824f1df

Please sign in to comment.