Skip to content

Commit 75dfdbd

Browse files
authored
fix: open does not throw when attempting to switch network during send flow (#4979)
1 parent 91ee33f commit 75dfdbd

File tree

5 files changed

+93
-7
lines changed

5 files changed

+93
-7
lines changed

.changeset/khaki-chairs-start.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
'@reown/appkit-controllers': patch
3+
'@reown/appkit': patch
4+
'pay-test-exchange': patch
5+
'@reown/appkit-adapter-bitcoin': patch
6+
'@reown/appkit-adapter-ethers': patch
7+
'@reown/appkit-adapter-ethers5': patch
8+
'@reown/appkit-adapter-solana': patch
9+
'@reown/appkit-adapter-wagmi': patch
10+
'@reown/appkit-utils': patch
11+
'@reown/appkit-cdn': patch
12+
'@reown/appkit-cli': patch
13+
'@reown/appkit-codemod': patch
14+
'@reown/appkit-common': patch
15+
'@reown/appkit-core': patch
16+
'@reown/appkit-experimental': patch
17+
'@reown/appkit-pay': patch
18+
'@reown/appkit-polyfills': patch
19+
'@reown/appkit-scaffold-ui': patch
20+
'@reown/appkit-siwe': patch
21+
'@reown/appkit-siwx': patch
22+
'@reown/appkit-testing': patch
23+
'@reown/appkit-ui': patch
24+
'@reown/appkit-universal-connector': patch
25+
'@reown/appkit-wallet': patch
26+
'@reown/appkit-wallet-button': patch
27+
---
28+
29+
Fixed an issue where using the `open` function with send arguments and attempting to switch networks did not throw, causing the network state to become inconsistent

packages/appkit/src/client/appkit-base-client.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ export interface OpenOptions<V extends Views | undefined = Views> {
122122
: never
123123
}
124124

125+
interface AppKitSwitchNetworkOptions {
126+
throwOnFailure?: boolean
127+
}
128+
125129
export abstract class AppKitBaseClient {
126130
protected universalProvider?: UniversalProvider
127131
protected connectionControllerClient?: ConnectionControllerClient
@@ -231,7 +235,7 @@ export abstract class AppKitBaseClient {
231235
throw new Error(`openSend: caipNetwork with chainId ${args.chainId} not found`)
232236
}
233237

234-
await this.switchNetwork(caipNetwork)
238+
await this.switchNetwork(caipNetwork, { throwOnFailure: true })
235239
}
236240

237241
try {
@@ -2159,14 +2163,17 @@ export abstract class AppKitBaseClient {
21592163
return ChainController.state.activeCaipNetwork?.id
21602164
}
21612165

2162-
public async switchNetwork(appKitNetwork: AppKitNetwork) {
2166+
public async switchNetwork(
2167+
appKitNetwork: AppKitNetwork,
2168+
{ throwOnFailure = false }: AppKitSwitchNetworkOptions = {}
2169+
) {
21632170
const network = this.getCaipNetworks().find(n => n.id === appKitNetwork.id)
21642171
if (!network) {
21652172
AlertController.open(ErrorUtil.ALERT_ERRORS.SWITCH_NETWORK_NOT_FOUND, 'error')
21662173

21672174
return
21682175
}
2169-
await ChainController.switchActiveNetwork(network)
2176+
await ChainController.switchActiveNetwork(network, { throwOnFailure })
21702177
}
21712178

21722179
public getWalletProvider() {

packages/appkit/tests/client/appkit-base-client.test.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
22
import type { MockInstance } from 'vitest'
33

44
import { ConstantsUtil } from '@reown/appkit-common'
5-
import type { ChainNamespace } from '@reown/appkit-common'
5+
import type { CaipNetwork, ChainNamespace } from '@reown/appkit-common'
66
import {
77
AlertController,
88
ApiController,
@@ -444,4 +444,43 @@ describe('AppKitBaseClient.open', () => {
444444

445445
expect(result).toEqual({ hash: '0xabc123def456' })
446446
})
447+
448+
it('it should throw an error if failed to switch network', async () => {
449+
const mockArgs = {
450+
assetAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
451+
amount: '1.0',
452+
namespace: 'eip155' as ChainNamespace,
453+
chainId: '1',
454+
to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6'
455+
}
456+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
457+
...ChainController.state,
458+
activeChain: 'eip155',
459+
activeCaipAddress: 'eip155:137:0x1234567890123456789012345678901234567890',
460+
chains: new Map([
461+
[
462+
'eip155',
463+
{
464+
accountState: {
465+
caipAddress: 'eip155:137:0x1234567890123456789012345678901234567890'
466+
}
467+
}
468+
]
469+
]) as unknown as Map<ChainNamespace, ChainAdapter>
470+
})
471+
472+
vi.spyOn(baseClient as any, 'getCaipNetwork').mockReturnValue({ id: 137 } as CaipNetwork)
473+
vi.spyOn(ChainController, 'getCaipNetworkById').mockReturnValue({
474+
id: 1,
475+
chainNamespace: 'eip155'
476+
} as CaipNetwork)
477+
478+
vi.spyOn(ChainController, 'switchActiveNetwork').mockRejectedValue(
479+
new Error('Failed to switch')
480+
)
481+
482+
await expect(baseClient.open({ view: 'WalletSend', arguments: mockArgs })).rejects.toThrow(
483+
'Failed to switch'
484+
)
485+
})
447486
})

packages/appkit/tests/client/public-methods.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,9 @@ describe('Base Public methods', () => {
733733
await appKit.switchNetwork(mainnet)
734734

735735
expect(switchActiveNetwork).toHaveBeenCalledWith(
736+
mainnet,
736737
expect.objectContaining({
737-
id: mainnet.id,
738-
name: mainnet.name
738+
throwOnFailure: false
739739
})
740740
)
741741

packages/controllers/src/controllers/ChainController.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ export interface ChainControllerState {
6363

6464
type ChainControllerStateKey = keyof ChainControllerState
6565

66+
export interface SwitchActiveNetworkOptions {
67+
throwOnFailure?: boolean
68+
}
69+
6670
// -- State --------------------------------------------- //
6771
const state = proxy<ChainControllerState>({
6872
chains: proxyMap<ChainNamespace, ChainAdapter>(),
@@ -410,7 +414,10 @@ const controller = {
410414
}
411415
},
412416

413-
async switchActiveNetwork(network: CaipNetwork) {
417+
async switchActiveNetwork(
418+
network: CaipNetwork,
419+
{ throwOnFailure = false }: SwitchActiveNetworkOptions = {}
420+
) {
414421
const namespace = ChainController.state.activeChain
415422

416423
if (!namespace) {
@@ -434,6 +441,10 @@ const controller = {
434441
ModalController.close()
435442
}
436443
} catch (error) {
444+
if (throwOnFailure) {
445+
throw error
446+
}
447+
437448
RouterController.goBack()
438449
}
439450

0 commit comments

Comments
 (0)