Skip to content
Open
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
11 changes: 11 additions & 0 deletions .changeset/fix-solana-switch-network-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@reown/appkit-adapter-solana": patch
"@reown/appkit": patch
---

fix(solana): sync walletProvider after switchNetwork for non-AUTH providers

`useAppKitProvider` returned a stale provider after calling `switchNetwork` because
the Solana adapter never emitted a `switchNetwork` event for WalletConnect and
standard wallet providers, and the base client's `switchNetwork` handler never
called `syncProvider`. Both are now fixed.
15 changes: 15 additions & 0 deletions packages/adapters/solana/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
CoreHelperUtil,
type Provider as CoreProvider,
OptionsController,
ProviderController,
StorageUtil,
WcHelpersUtil
} from '@reown/appkit-controllers'
Expand Down Expand Up @@ -508,6 +509,20 @@ export class SolanaAdapter extends AdapterBlueprint<SolanaProvider> {
new SolanaConnection(caipNetwork.rpcUrls.default.http[0], this.connectionSettings)
)
}

/*
* super.switchNetwork() only emits 'switchNetwork' for AUTH providers.
* For WalletConnect and standard wallet providers we must emit it here so
* the base-client can re-sync the provider state via syncProvider().
*/
const providerType = ProviderController.getProviderId(caipNetwork.chainNamespace)
if (providerType !== 'AUTH') {
const address = ChainController.state.chains.get(caipNetwork.chainNamespace)?.accountState
?.address
if (address) {
this.emit('switchNetwork', { chainId: caipNetwork.id, address })
}
}
}

// We use listenSolanaProviderEvents instead of listenProviderEvents
Expand Down
48 changes: 48 additions & 0 deletions packages/adapters/solana/src/tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,54 @@ describe('SolanaAdapter', () => {
expect(switchNetworkSpy).toHaveBeenCalled()
expect(SolStoreUtil.setConnection).toHaveBeenCalled()
})

it('should emit switchNetwork event for WalletConnect provider', async () => {
const wcProvider = mockUniversalProvider()
ProviderController.setProvider(mockCaipNetworks[0].chainNamespace, wcProvider)
ProviderController.setProviderId(mockCaipNetworks[0].chainNamespace, 'WALLET_CONNECT')

ChainController.state.chains.get('solana')!.accountState!.address = '0xTestAddress'

const emitSpy = vi.spyOn(adapter, 'emit')

await adapter.switchNetwork({ caipNetwork: mockCaipNetworks[0] })

expect(SolStoreUtil.setConnection).toHaveBeenCalled()
expect(emitSpy).toHaveBeenCalledWith('switchNetwork', {
chainId: mockCaipNetworks[0].id,
address: '0xTestAddress'
})
})

it('should emit switchNetwork event for standard wallet provider', async () => {
ProviderController.setProvider(mockCaipNetworks[0].chainNamespace, mockProvider)
ProviderController.setProviderId(mockCaipNetworks[0].chainNamespace, 'ANNOUNCED')

ChainController.state.chains.get('solana')!.accountState!.address = '0xTestAddress'

const emitSpy = vi.spyOn(adapter, 'emit')

await adapter.switchNetwork({ caipNetwork: mockCaipNetworks[0] })

expect(SolStoreUtil.setConnection).toHaveBeenCalled()
expect(emitSpy).toHaveBeenCalledWith('switchNetwork', {
chainId: mockCaipNetworks[0].id,
address: '0xTestAddress'
})
})

it('should not emit switchNetwork event when no account address is present', async () => {
ProviderController.setProvider(mockCaipNetworks[0].chainNamespace, mockProvider)
ProviderController.setProviderId(mockCaipNetworks[0].chainNamespace, 'ANNOUNCED')

ChainController.state.chains.get('solana')!.accountState!.address = undefined

const emitSpy = vi.spyOn(adapter, 'emit')

await adapter.switchNetwork({ caipNetwork: mockCaipNetworks[0] })

expect(emitSpy).not.toHaveBeenCalledWith('switchNetwork', expect.anything())
})
})

describe('SolanaAdapter - connectWalletConnect', () => {
Expand Down
13 changes: 13 additions & 0 deletions packages/appkit/src/client/appkit-base-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,19 @@ export abstract class AppKitBaseClient {
} else {
this.setUnsupportedNetwork(chainId)
}

const currentProvider = ProviderController.getProvider(chainNamespace)
const currentProviderId = ProviderController.getProviderId(chainNamespace)
const currentConnectorId = ConnectorController.getConnectorId(chainNamespace)

if (currentProvider && currentProviderId && currentConnectorId) {
this.syncProvider({
id: currentConnectorId,
type: currentProviderId,
provider: currentProvider,
chainNamespace
})
}
})

adapter.on('disconnect', () => {
Expand Down
Loading