Skip to content

Commit 08f5c48

Browse files
tomiirclaude
andauthored
feat: expose approved CAIP network IDs in useAppKitNetwork (#5570)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e0e601d commit 08f5c48

11 files changed

Lines changed: 213 additions & 24 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@reown/appkit': patch
3+
'@reown/appkit-controllers': patch
4+
---
5+
6+
Expose `approvedCaipNetworkIds` and `supportsAllNetworks` in `useAppKitNetwork` hook
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const PACKAGE_VERSION = '1.8.18'
1+
export const PACKAGE_VERSION = '1.8.19'

packages/appkit/exports/react-core.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export type { AppKitOptions }
4040
export * from '../src/library/react/index.js'
4141

4242
export function useAppKitNetwork(): UseAppKitNetworkReturn {
43-
const { caipNetwork, caipNetworkId, chainId } = useAppKitNetworkCore()
43+
const { caipNetwork, caipNetworkId, chainId, approvedCaipNetworkIds, supportsAllNetworks } =
44+
useAppKitNetworkCore()
4445

4546
async function switchNetwork(network: AppKitNetwork) {
4647
await modal?.switchNetwork(network)
@@ -50,6 +51,8 @@ export function useAppKitNetwork(): UseAppKitNetworkReturn {
5051
caipNetwork,
5152
caipNetworkId,
5253
chainId,
54+
approvedCaipNetworkIds,
55+
supportsAllNetworks,
5356
switchNetwork
5457
}
5558
}

packages/appkit/exports/react.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export * from '../src/library/react/index.js'
4747
export { useAppKitProvider } from '@reown/appkit-controllers/react'
4848

4949
export function useAppKitNetwork(): UseAppKitNetworkReturn {
50-
const { caipNetwork, caipNetworkId, chainId } = useAppKitNetworkCore()
50+
const { caipNetwork, caipNetworkId, chainId, approvedCaipNetworkIds, supportsAllNetworks } =
51+
useAppKitNetworkCore()
5152

5253
async function switchNetwork(network: AppKitNetwork) {
5354
await modal?.switchNetwork(network)
@@ -57,6 +58,8 @@ export function useAppKitNetwork(): UseAppKitNetworkReturn {
5758
caipNetwork,
5859
caipNetworkId,
5960
chainId,
61+
approvedCaipNetworkIds,
62+
supportsAllNetworks,
6063
switchNetwork
6164
}
6265
}

packages/appkit/exports/vue-core.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,46 @@ export type { AppKitOptions }
3939

4040
// -- Hooks ------------------------------------------------------------
4141
export function useAppKitNetwork(): Ref<UseAppKitNetworkReturn> {
42+
const networkState = ChainController.state.activeChain
43+
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
44+
: undefined
45+
4246
const state = ref({
4347
caipNetwork: ChainController.state.activeCaipNetwork,
4448
chainId: ChainController.state.activeCaipNetwork?.id,
4549
caipNetworkId: ChainController.state.activeCaipNetwork?.caipNetworkId,
50+
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
51+
supportsAllNetworks: networkState?.supportsAllNetworks ?? true,
4652
switchNetwork: async (network: AppKitNetwork) => {
4753
await modal?.switchNetwork(network)
4854
}
4955
})
5056

51-
const unsubscribe = ChainController.subscribeKey('activeCaipNetwork', val => {
52-
state.value.caipNetwork = val
53-
state.value.chainId = val?.id
54-
state.value.caipNetworkId = val?.caipNetworkId
55-
})
57+
const unsubscribes: (() => void)[] = []
58+
59+
unsubscribes.push(
60+
ChainController.subscribeKey('activeCaipNetwork', val => {
61+
state.value.caipNetwork = val
62+
state.value.chainId = val?.id
63+
state.value.caipNetworkId = val?.caipNetworkId
64+
65+
const ns = ChainController.state.activeChain
66+
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
67+
: undefined
68+
state.value.approvedCaipNetworkIds = ns?.approvedCaipNetworkIds
69+
state.value.supportsAllNetworks = ns?.supportsAllNetworks ?? true
70+
})
71+
)
72+
73+
unsubscribes.push(
74+
ChainController.subscribeChainProp('networkState', networkState => {
75+
state.value.approvedCaipNetworkIds = networkState?.approvedCaipNetworkIds
76+
state.value.supportsAllNetworks = networkState?.supportsAllNetworks ?? true
77+
})
78+
)
5679

5780
onUnmounted(() => {
58-
unsubscribe()
81+
unsubscribes.forEach(u => u())
5982
})
6083

6184
return state

packages/appkit/exports/vue.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,46 @@ export type { AppKitOptions }
4343

4444
// -- Hooks ------------------------------------------------------------
4545
export function useAppKitNetwork(): Ref<UseAppKitNetworkReturn> {
46+
const networkState = ChainController.state.activeChain
47+
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
48+
: undefined
49+
4650
const state = ref({
4751
caipNetwork: ChainController.state.activeCaipNetwork,
4852
chainId: ChainController.state.activeCaipNetwork?.id,
4953
caipNetworkId: ChainController.state.activeCaipNetwork?.caipNetworkId,
54+
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
55+
supportsAllNetworks: networkState?.supportsAllNetworks ?? true,
5056
switchNetwork: async (network: AppKitNetwork) => {
5157
await modal?.switchNetwork(network)
5258
}
5359
})
5460

55-
const unsubscribe = ChainController.subscribeKey('activeCaipNetwork', val => {
56-
state.value.caipNetwork = val
57-
state.value.chainId = val?.id
58-
state.value.caipNetworkId = val?.caipNetworkId
59-
})
61+
const unsubscribes: (() => void)[] = []
62+
63+
unsubscribes.push(
64+
ChainController.subscribeKey('activeCaipNetwork', val => {
65+
state.value.caipNetwork = val
66+
state.value.chainId = val?.id
67+
state.value.caipNetworkId = val?.caipNetworkId
68+
69+
const ns = ChainController.state.activeChain
70+
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
71+
: undefined
72+
state.value.approvedCaipNetworkIds = ns?.approvedCaipNetworkIds
73+
state.value.supportsAllNetworks = ns?.supportsAllNetworks ?? true
74+
})
75+
)
76+
77+
unsubscribes.push(
78+
ChainController.subscribeChainProp('networkState', networkState => {
79+
state.value.approvedCaipNetworkIds = networkState?.approvedCaipNetworkIds
80+
state.value.supportsAllNetworks = networkState?.supportsAllNetworks ?? true
81+
})
82+
)
6083

6184
onUnmounted(() => {
62-
unsubscribe()
85+
unsubscribes.forEach(u => u())
6386
})
6487

6588
return state

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,11 +2488,14 @@ export abstract class AppKitBaseClient {
24882488
public subscribeNetwork(
24892489
callback: (newState: Omit<UseAppKitNetworkReturn, 'switchNetwork'>) => void
24902490
) {
2491-
return ChainController.subscribe(({ activeCaipNetwork }) => {
2491+
return ChainController.subscribe(({ activeCaipNetwork, activeChain, chains }) => {
2492+
const networkState = activeChain ? chains.get(activeChain)?.networkState : undefined
24922493
callback({
24932494
caipNetwork: activeCaipNetwork,
24942495
chainId: activeCaipNetwork?.id,
2495-
caipNetworkId: activeCaipNetwork?.caipNetworkId
2496+
caipNetworkId: activeCaipNetwork?.caipNetworkId,
2497+
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
2498+
supportsAllNetworks: networkState?.supportsAllNetworks ?? true
24962499
})
24972500
})
24982501
}

packages/appkit/tests/library/vue.test.ts

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
33
import { defineComponent, h } from 'vue'
44

55
import type { ChainNamespace } from '@reown/appkit-common'
6-
import { ProviderController } from '@reown/appkit-controllers'
6+
import { ChainController, ProviderController } from '@reown/appkit-controllers'
77

88
import { type ConnectorType, createAppKit, useAppKitProvider } from '../../exports/vue-core.js'
9+
import { useAppKitNetwork } from '../../exports/vue.js'
910
import { mainnet } from '../mocks/Networks.js'
1011

1112
const TestComponent = defineComponent({
@@ -95,3 +96,92 @@ describe('useAppKitProvider', () => {
9596
expect(mockUnsubscribe).toHaveBeenCalled()
9697
})
9798
})
99+
100+
describe('useAppKitNetwork', () => {
101+
const NetworkTestComponent = defineComponent({
102+
setup() {
103+
const state = useAppKitNetwork()
104+
105+
return { state }
106+
},
107+
render() {
108+
return h('div', {}, [
109+
h(
110+
'div',
111+
{ 'data-testid': 'approvedCaipNetworkIds' },
112+
JSON.stringify(this.state.approvedCaipNetworkIds)
113+
),
114+
h(
115+
'div',
116+
{ 'data-testid': 'supportsAllNetworks' },
117+
JSON.stringify(this.state.supportsAllNetworks)
118+
)
119+
])
120+
}
121+
})
122+
123+
let mockUnsubscribeKey: ReturnType<typeof vi.fn>
124+
let mockUnsubscribeChainProp: ReturnType<typeof vi.fn>
125+
126+
beforeEach(() => {
127+
vi.clearAllMocks()
128+
129+
mockUnsubscribeKey = vi.fn()
130+
mockUnsubscribeChainProp = vi.fn()
131+
vi.spyOn(ChainController, 'subscribeKey').mockReturnValue(mockUnsubscribeKey)
132+
vi.spyOn(ChainController, 'subscribeChainProp').mockReturnValue(mockUnsubscribeChainProp)
133+
})
134+
135+
it('should return defaults when no chain is active', () => {
136+
ChainController.state.activeChain = undefined
137+
138+
const wrapper = mount(NetworkTestComponent)
139+
140+
expect(wrapper.get('[data-testid="supportsAllNetworks"]').text()).toBe('true')
141+
})
142+
143+
it('should return approved networks from chain networkState', () => {
144+
ChainController.state.activeChain = 'eip155'
145+
ChainController.state.chains = new Map([
146+
[
147+
'eip155',
148+
{
149+
networkState: {
150+
approvedCaipNetworkIds: ['eip155:1', 'eip155:137'],
151+
supportsAllNetworks: false
152+
}
153+
}
154+
]
155+
])
156+
157+
const wrapper = mount(NetworkTestComponent)
158+
159+
expect(wrapper.get('[data-testid="approvedCaipNetworkIds"]').text()).toBe(
160+
'["eip155:1","eip155:137"]'
161+
)
162+
expect(wrapper.get('[data-testid="supportsAllNetworks"]').text()).toBe('false')
163+
})
164+
165+
it('should subscribe to activeCaipNetwork and networkState', () => {
166+
ChainController.state.activeChain = 'eip155'
167+
ChainController.state.chains = new Map([
168+
['eip155', { networkState: { supportsAllNetworks: true } }]
169+
])
170+
171+
const wrapper = mount(NetworkTestComponent)
172+
173+
expect(ChainController.subscribeKey).toHaveBeenCalledWith(
174+
'activeCaipNetwork',
175+
expect.any(Function)
176+
)
177+
expect(ChainController.subscribeChainProp).toHaveBeenCalledWith(
178+
'networkState',
179+
expect.any(Function)
180+
)
181+
182+
wrapper.unmount()
183+
184+
expect(mockUnsubscribeKey).toHaveBeenCalled()
185+
expect(mockUnsubscribeChainProp).toHaveBeenCalled()
186+
})
187+
})

packages/controllers/exports/react.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,18 @@ export function useAppKitProvider<T>(chainNamespace: ChainNamespace) {
8080

8181
export function useAppKitNetworkCore(): Pick<
8282
UseAppKitNetworkReturn,
83-
'caipNetwork' | 'chainId' | 'caipNetworkId'
83+
'caipNetwork' | 'chainId' | 'caipNetworkId' | 'approvedCaipNetworkIds' | 'supportsAllNetworks'
8484
> {
85-
const { activeCaipNetwork } = useSnapshot(ChainController.state)
85+
const { activeCaipNetwork, activeChain, chains } = useSnapshot(ChainController.state)
86+
87+
const networkState = activeChain ? chains.get(activeChain)?.networkState : undefined
8688

8789
return {
8890
caipNetwork: activeCaipNetwork as CaipNetwork,
8991
chainId: activeCaipNetwork?.id,
90-
caipNetworkId: activeCaipNetwork?.caipNetworkId
92+
caipNetworkId: activeCaipNetwork?.caipNetworkId,
93+
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
94+
supportsAllNetworks: networkState?.supportsAllNetworks ?? true
9195
}
9296
}
9397

@@ -457,8 +461,9 @@ export function useAppKitWallets(): UseAppKitWalletsReturn {
457461
* Pre-fetches the WalletConnect URI. Call this when user selects a wallet on mobile.
458462
* Uses 'auto' cache to reuse existing valid URI or fetch new one if expired.
459463
*/
460-
async function getWcUri() {
464+
async function getWcUri(options?: { wcPayUrl?: string }) {
461465
resetWcUri()
466+
setCurrentWcPayUrl(options?.wcPayUrl)
462467
await ConnectionController.connectWalletConnect({ cache: 'auto' })
463468
}
464469

packages/controllers/src/utils/TypeUtil.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,8 @@ export type UseAppKitNetworkReturn = {
14251425
caipNetwork: CaipNetwork | undefined
14261426
chainId: number | string | undefined
14271427
caipNetworkId: CaipNetworkId | undefined
1428+
approvedCaipNetworkIds: CaipNetworkId[] | undefined
1429+
supportsAllNetworks: boolean
14281430
switchNetwork: (network: AppKitNetwork) => Promise<void>
14291431
}
14301432

0 commit comments

Comments
 (0)