Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/expose-approved-networks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@reown/appkit': patch
'@reown/appkit-controllers': patch
---

Expose `approvedCaipNetworkIds` and `supportsAllNetworks` in `useAppKitNetwork` hook
2 changes: 1 addition & 1 deletion packages/appkit/exports/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const PACKAGE_VERSION = '1.8.18'
export const PACKAGE_VERSION = '1.8.19'
5 changes: 4 additions & 1 deletion packages/appkit/exports/react-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export type { AppKitOptions }
export * from '../src/library/react/index.js'

export function useAppKitNetwork(): UseAppKitNetworkReturn {
const { caipNetwork, caipNetworkId, chainId } = useAppKitNetworkCore()
const { caipNetwork, caipNetworkId, chainId, approvedCaipNetworkIds, supportsAllNetworks } =
useAppKitNetworkCore()

async function switchNetwork(network: AppKitNetwork) {
await modal?.switchNetwork(network)
Expand All @@ -50,6 +51,8 @@ export function useAppKitNetwork(): UseAppKitNetworkReturn {
caipNetwork,
caipNetworkId,
chainId,
approvedCaipNetworkIds,
supportsAllNetworks,
switchNetwork
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/appkit/exports/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export * from '../src/library/react/index.js'
export { useAppKitProvider } from '@reown/appkit-controllers/react'

export function useAppKitNetwork(): UseAppKitNetworkReturn {
const { caipNetwork, caipNetworkId, chainId } = useAppKitNetworkCore()
const { caipNetwork, caipNetworkId, chainId, approvedCaipNetworkIds, supportsAllNetworks } =
useAppKitNetworkCore()

async function switchNetwork(network: AppKitNetwork) {
await modal?.switchNetwork(network)
Expand All @@ -57,6 +58,8 @@ export function useAppKitNetwork(): UseAppKitNetworkReturn {
caipNetwork,
caipNetworkId,
chainId,
approvedCaipNetworkIds,
supportsAllNetworks,
switchNetwork
}
}
Expand Down
35 changes: 29 additions & 6 deletions packages/appkit/exports/vue-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,46 @@ export type { AppKitOptions }

// -- Hooks ------------------------------------------------------------
export function useAppKitNetwork(): Ref<UseAppKitNetworkReturn> {
const networkState = ChainController.state.activeChain
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
: undefined

const state = ref({
caipNetwork: ChainController.state.activeCaipNetwork,
chainId: ChainController.state.activeCaipNetwork?.id,
caipNetworkId: ChainController.state.activeCaipNetwork?.caipNetworkId,
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
supportsAllNetworks: networkState?.supportsAllNetworks ?? true,
switchNetwork: async (network: AppKitNetwork) => {
await modal?.switchNetwork(network)
}
})

const unsubscribe = ChainController.subscribeKey('activeCaipNetwork', val => {
state.value.caipNetwork = val
state.value.chainId = val?.id
state.value.caipNetworkId = val?.caipNetworkId
})
const unsubscribes: (() => void)[] = []

unsubscribes.push(
ChainController.subscribeKey('activeCaipNetwork', val => {
state.value.caipNetwork = val
state.value.chainId = val?.id
state.value.caipNetworkId = val?.caipNetworkId

const ns = ChainController.state.activeChain
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
: undefined
state.value.approvedCaipNetworkIds = ns?.approvedCaipNetworkIds
state.value.supportsAllNetworks = ns?.supportsAllNetworks ?? true
})
)

unsubscribes.push(
ChainController.subscribeChainProp('networkState', networkState => {
state.value.approvedCaipNetworkIds = networkState?.approvedCaipNetworkIds
state.value.supportsAllNetworks = networkState?.supportsAllNetworks ?? true
})
)
Comment thread
cursor[bot] marked this conversation as resolved.

onUnmounted(() => {
unsubscribe()
unsubscribes.forEach(u => u())
})

return state
Expand Down
35 changes: 29 additions & 6 deletions packages/appkit/exports/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,46 @@ export type { AppKitOptions }

// -- Hooks ------------------------------------------------------------
export function useAppKitNetwork(): Ref<UseAppKitNetworkReturn> {
const networkState = ChainController.state.activeChain
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
: undefined

const state = ref({
caipNetwork: ChainController.state.activeCaipNetwork,
chainId: ChainController.state.activeCaipNetwork?.id,
caipNetworkId: ChainController.state.activeCaipNetwork?.caipNetworkId,
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
supportsAllNetworks: networkState?.supportsAllNetworks ?? true,
switchNetwork: async (network: AppKitNetwork) => {
await modal?.switchNetwork(network)
}
})

const unsubscribe = ChainController.subscribeKey('activeCaipNetwork', val => {
state.value.caipNetwork = val
state.value.chainId = val?.id
state.value.caipNetworkId = val?.caipNetworkId
})
const unsubscribes: (() => void)[] = []

unsubscribes.push(
ChainController.subscribeKey('activeCaipNetwork', val => {
state.value.caipNetwork = val
state.value.chainId = val?.id
state.value.caipNetworkId = val?.caipNetworkId

const ns = ChainController.state.activeChain
? ChainController.state.chains.get(ChainController.state.activeChain)?.networkState
: undefined
state.value.approvedCaipNetworkIds = ns?.approvedCaipNetworkIds
state.value.supportsAllNetworks = ns?.supportsAllNetworks ?? true
})
)

unsubscribes.push(
ChainController.subscribeChainProp('networkState', networkState => {
state.value.approvedCaipNetworkIds = networkState?.approvedCaipNetworkIds
state.value.supportsAllNetworks = networkState?.supportsAllNetworks ?? true
})
)

onUnmounted(() => {
unsubscribe()
unsubscribes.forEach(u => u())
})

return state
Expand Down
7 changes: 5 additions & 2 deletions packages/appkit/src/client/appkit-base-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2488,11 +2488,14 @@ export abstract class AppKitBaseClient {
public subscribeNetwork(
callback: (newState: Omit<UseAppKitNetworkReturn, 'switchNetwork'>) => void
) {
return ChainController.subscribe(({ activeCaipNetwork }) => {
return ChainController.subscribe(({ activeCaipNetwork, activeChain, chains }) => {
const networkState = activeChain ? chains.get(activeChain)?.networkState : undefined
callback({
caipNetwork: activeCaipNetwork,
chainId: activeCaipNetwork?.id,
caipNetworkId: activeCaipNetwork?.caipNetworkId
caipNetworkId: activeCaipNetwork?.caipNetworkId,
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
supportsAllNetworks: networkState?.supportsAllNetworks ?? true
})
})
}
Expand Down
92 changes: 91 additions & 1 deletion packages/appkit/tests/library/vue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
import { defineComponent, h } from 'vue'

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

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

const TestComponent = defineComponent({
Expand Down Expand Up @@ -95,3 +96,92 @@ describe('useAppKitProvider', () => {
expect(mockUnsubscribe).toHaveBeenCalled()
})
})

describe('useAppKitNetwork', () => {
const NetworkTestComponent = defineComponent({
setup() {
const state = useAppKitNetwork()

return { state }
},
render() {
return h('div', {}, [
h(
'div',
{ 'data-testid': 'approvedCaipNetworkIds' },
JSON.stringify(this.state.approvedCaipNetworkIds)
),
h(
'div',
{ 'data-testid': 'supportsAllNetworks' },
JSON.stringify(this.state.supportsAllNetworks)
)
])
}
})

let mockUnsubscribeKey: ReturnType<typeof vi.fn>
let mockUnsubscribeChainProp: ReturnType<typeof vi.fn>

beforeEach(() => {
vi.clearAllMocks()

mockUnsubscribeKey = vi.fn()
mockUnsubscribeChainProp = vi.fn()
vi.spyOn(ChainController, 'subscribeKey').mockReturnValue(mockUnsubscribeKey)
vi.spyOn(ChainController, 'subscribeChainProp').mockReturnValue(mockUnsubscribeChainProp)
})

it('should return defaults when no chain is active', () => {
ChainController.state.activeChain = undefined

const wrapper = mount(NetworkTestComponent)

expect(wrapper.get('[data-testid="supportsAllNetworks"]').text()).toBe('true')
})

it('should return approved networks from chain networkState', () => {
ChainController.state.activeChain = 'eip155'
ChainController.state.chains = new Map([
[
'eip155',
{
networkState: {
approvedCaipNetworkIds: ['eip155:1', 'eip155:137'],
supportsAllNetworks: false
}
}
]
])

const wrapper = mount(NetworkTestComponent)

expect(wrapper.get('[data-testid="approvedCaipNetworkIds"]').text()).toBe(
'["eip155:1","eip155:137"]'
)
expect(wrapper.get('[data-testid="supportsAllNetworks"]').text()).toBe('false')
})

it('should subscribe to activeCaipNetwork and networkState', () => {
ChainController.state.activeChain = 'eip155'
ChainController.state.chains = new Map([
['eip155', { networkState: { supportsAllNetworks: true } }]
])

const wrapper = mount(NetworkTestComponent)

expect(ChainController.subscribeKey).toHaveBeenCalledWith(
'activeCaipNetwork',
expect.any(Function)
)
expect(ChainController.subscribeChainProp).toHaveBeenCalledWith(
'networkState',
expect.any(Function)
)

wrapper.unmount()

expect(mockUnsubscribeKey).toHaveBeenCalled()
expect(mockUnsubscribeChainProp).toHaveBeenCalled()
})
})
13 changes: 9 additions & 4 deletions packages/controllers/exports/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,18 @@ export function useAppKitProvider<T>(chainNamespace: ChainNamespace) {

export function useAppKitNetworkCore(): Pick<
UseAppKitNetworkReturn,
'caipNetwork' | 'chainId' | 'caipNetworkId'
'caipNetwork' | 'chainId' | 'caipNetworkId' | 'approvedCaipNetworkIds' | 'supportsAllNetworks'
> {
const { activeCaipNetwork } = useSnapshot(ChainController.state)
const { activeCaipNetwork, activeChain, chains } = useSnapshot(ChainController.state)

const networkState = activeChain ? chains.get(activeChain)?.networkState : undefined

return {
caipNetwork: activeCaipNetwork as CaipNetwork,
chainId: activeCaipNetwork?.id,
caipNetworkId: activeCaipNetwork?.caipNetworkId
caipNetworkId: activeCaipNetwork?.caipNetworkId,
approvedCaipNetworkIds: networkState?.approvedCaipNetworkIds,
supportsAllNetworks: networkState?.supportsAllNetworks ?? true
}
}

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

Expand Down
2 changes: 2 additions & 0 deletions packages/controllers/src/utils/TypeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,8 @@ export type UseAppKitNetworkReturn = {
caipNetwork: CaipNetwork | undefined
chainId: number | string | undefined
caipNetworkId: CaipNetworkId | undefined
approvedCaipNetworkIds: CaipNetworkId[] | undefined
supportsAllNetworks: boolean
switchNetwork: (network: AppKitNetwork) => Promise<void>
}

Expand Down
35 changes: 33 additions & 2 deletions packages/controllers/tests/hooks/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,45 @@ describe('useAppKitNetwork', () => {
})

it('should return the correct network state', () => {
useSnapshot.mockReturnValue({ activeCaipNetwork: extendedMainnet })
useSnapshot.mockReturnValue({
activeCaipNetwork: extendedMainnet,
activeChain: 'eip155',
chains: new Map([
[
'eip155',
{
networkState: {
approvedCaipNetworkIds: ['eip155:1', 'eip155:137'],
supportsAllNetworks: false
}
}
]
])
})

const { caipNetwork, chainId } = useAppKitNetworkCore()
const { caipNetwork, chainId, approvedCaipNetworkIds, supportsAllNetworks } =
useAppKitNetworkCore()

expect(caipNetwork).toBe(extendedMainnet)
expect(chainId).toBe(1)
expect(approvedCaipNetworkIds).toEqual(['eip155:1', 'eip155:137'])
expect(supportsAllNetworks).toBe(false)
expect(useSnapshot).toHaveBeenCalledWith(ChainController.state)
})

it('should return defaults when no chain is active', () => {
useSnapshot.mockReturnValue({
activeCaipNetwork: undefined,
activeChain: undefined,
chains: new Map()
})

const { caipNetwork, approvedCaipNetworkIds, supportsAllNetworks } = useAppKitNetworkCore()

expect(caipNetwork).toBeUndefined()
expect(approvedCaipNetworkIds).toBeUndefined()
expect(supportsAllNetworks).toBe(true)
})
})

describe('useAppKitAccount', () => {
Expand Down