diff --git a/.changeset/nasty-rats-destroy.md b/.changeset/nasty-rats-destroy.md new file mode 100644 index 0000000000..39a3c2b3ce --- /dev/null +++ b/.changeset/nasty-rats-destroy.md @@ -0,0 +1,38 @@ +--- +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit-wallet': patch +'@reown/appkit-core': patch +'@apps/demo': patch +'@apps/gallery': patch +'@apps/laboratory': patch +'@examples/html-ethers': patch +'@examples/html-ethers5': patch +'@examples/html-wagmi': patch +'@examples/next-ethers': patch +'@examples/next-wagmi': patch +'@examples/react-ethers': patch +'@examples/react-ethers5': patch +'@examples/react-solana': patch +'@examples/react-wagmi': patch +'@examples/vue-ethers5': patch +'@examples/vue-solana': patch +'@examples/vue-wagmi': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-ethers': patch +'@reown/appkit-ethers5': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-solana': patch +'@reown/appkit-ui': patch +'@reown/appkit-wagmi': patch +--- + +Fixes issue where wagmi would not reconnect on an active session diff --git a/.changeset/two-cats-wave.md b/.changeset/two-cats-wave.md new file mode 100644 index 0000000000..8c1d95707a --- /dev/null +++ b/.changeset/two-cats-wave.md @@ -0,0 +1,38 @@ +--- +'@reown/appkit-adapter-wagmi': patch +'@apps/laboratory': patch +'@reown/appkit-core': patch +'@apps/demo': patch +'@apps/gallery': patch +'@examples/html-ethers': patch +'@examples/html-ethers5': patch +'@examples/html-wagmi': patch +'@examples/next-ethers': patch +'@examples/next-wagmi': patch +'@examples/react-ethers': patch +'@examples/react-ethers5': patch +'@examples/react-solana': patch +'@examples/react-wagmi': patch +'@examples/vue-ethers5': patch +'@examples/vue-solana': patch +'@examples/vue-wagmi': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-ethers': patch +'@reown/appkit-ethers5': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-solana': patch +'@reown/appkit-ui': patch +'@reown/appkit-wagmi': patch +'@reown/appkit-wallet': patch +--- + +Fixes wrong wagmi authConnector name causing issues when merging multiple authConnectors diff --git a/packages/adapters/ethers/src/client.ts b/packages/adapters/ethers/src/client.ts index e7be697bbb..82ad431a6f 100644 --- a/packages/adapters/ethers/src/client.ts +++ b/packages/adapters/ethers/src/client.ts @@ -772,7 +772,7 @@ export class EthersAdapter { authProvider.onRpcError(() => this.handleAuthRpcError()) authProvider.onRpcSuccess((_, request) => this.handleAuthRpcSuccess(_, request)) authProvider.onNotConnected(() => this.handleAuthNotConnected()) - authProvider.onIsConnected(({ preferredAccountType }) => + authProvider.onConnect(({ preferredAccountType }) => this.handleAuthIsConnected(preferredAccountType) ) authProvider.onSetPreferredAccount(({ address, type }) => { diff --git a/packages/adapters/ethers/src/tests/mocks/AuthConnector.ts b/packages/adapters/ethers/src/tests/mocks/AuthConnector.ts index 07f99eafaa..bc7d53af51 100644 --- a/packages/adapters/ethers/src/tests/mocks/AuthConnector.ts +++ b/packages/adapters/ethers/src/tests/mocks/AuthConnector.ts @@ -6,6 +6,7 @@ export const mockAuthConnector = { onRpcSuccess: vi.fn(), onNotConnected: vi.fn(), onIsConnected: vi.fn(), + onConnect: vi.fn(), onSetPreferredAccount: vi.fn(), connect: vi.fn().mockResolvedValue({ address: '0x1234567890123456789012345678901234567890', diff --git a/packages/adapters/ethers5/src/client.ts b/packages/adapters/ethers5/src/client.ts index b0aa97fb3e..b324b14c80 100644 --- a/packages/adapters/ethers5/src/client.ts +++ b/packages/adapters/ethers5/src/client.ts @@ -777,7 +777,7 @@ export class Ethers5Adapter { authProvider.onRpcError(() => this.handleAuthRpcError()) authProvider.onRpcSuccess((_, request) => this.handleAuthRpcSuccess(_, request)) authProvider.onNotConnected(() => this.handleAuthNotConnected()) - authProvider.onIsConnected(({ preferredAccountType }) => + authProvider.onConnect(({ preferredAccountType }) => this.handleAuthIsConnected(preferredAccountType) ) authProvider.onSetPreferredAccount(({ address, type }) => { diff --git a/packages/adapters/ethers5/src/tests/mocks/AuthConnector.ts b/packages/adapters/ethers5/src/tests/mocks/AuthConnector.ts index 07f99eafaa..bc7d53af51 100644 --- a/packages/adapters/ethers5/src/tests/mocks/AuthConnector.ts +++ b/packages/adapters/ethers5/src/tests/mocks/AuthConnector.ts @@ -6,6 +6,7 @@ export const mockAuthConnector = { onRpcSuccess: vi.fn(), onNotConnected: vi.fn(), onIsConnected: vi.fn(), + onConnect: vi.fn(), onSetPreferredAccount: vi.fn(), connect: vi.fn().mockResolvedValue({ address: '0x1234567890123456789012345678901234567890', diff --git a/packages/adapters/solana/src/providers/AuthProvider.ts b/packages/adapters/solana/src/providers/AuthProvider.ts index 7428a2f0e0..abcebb7e9f 100644 --- a/packages/adapters/solana/src/providers/AuthProvider.ts +++ b/packages/adapters/solana/src/providers/AuthProvider.ts @@ -229,7 +229,7 @@ export class AuthProvider extends ProviderEventEmitter implements Provider, Prov this.emit('auth_rpcError', error) }) - this.getProvider().onIsConnected(response => { + this.getProvider().onConnect(response => { this.setSession(response) const activeNamespace = this.getActiveNamespace() diff --git a/packages/adapters/solana/src/tests/mocks/AuthConnector.ts b/packages/adapters/solana/src/tests/mocks/AuthConnector.ts index 9af5874639..36e2c2a61d 100644 --- a/packages/adapters/solana/src/tests/mocks/AuthConnector.ts +++ b/packages/adapters/solana/src/tests/mocks/AuthConnector.ts @@ -4,6 +4,7 @@ export const mockAuthConnector = { onRpcRequest: vi.fn(), onRpcError: vi.fn(), onRpcSuccess: vi.fn(), + onConnect: vi.fn(), onNotConnected: vi.fn(), onIsConnected: vi.fn(), onSetPreferredAccount: vi.fn(), diff --git a/packages/adapters/wagmi/src/client.ts b/packages/adapters/wagmi/src/client.ts index 683eef9349..a3bec7dea4 100644 --- a/packages/adapters/wagmi/src/client.ts +++ b/packages/adapters/wagmi/src/client.ts @@ -22,7 +22,11 @@ import { createConfig, getConnectors } from '@wagmi/core' -import { ChainController, ConstantsUtil as CoreConstantsUtil } from '@reown/appkit-core' +import { + ChainController, + ConstantsUtil as CoreConstantsUtil, + StorageUtil +} from '@reown/appkit-core' import type UniversalProvider from '@walletconnect/universal-provider' import type { ChainAdapter } from '@reown/appkit-core' import { prepareTransactionRequest, sendTransaction as wagmiSendTransaction } from '@wagmi/core' @@ -863,7 +867,7 @@ export class WagmiAdapter implements ChainAdapter { this.appKit?.addConnector({ id: ConstantsUtil.AUTH_CONNECTOR_ID, type: 'AUTH', - name: 'Auth', + name: 'w3mAuth', provider, chain: this.chainNamespace }) @@ -947,24 +951,32 @@ export class WagmiAdapter implements ChainAdapter { } }) - provider.onIsConnected(req => { - const caipAddress = `eip155:${req.chainId}:${req.address}` as CaipAddress + provider.onIsConnected(() => { + provider.connect() + }) + + provider.onConnect(user => { + const caipAddress = `eip155:${user.chainId}:${user.address}` as CaipAddress this.appKit?.setCaipAddress(caipAddress, this.chainNamespace) - this.appKit?.setSmartAccountDeployed(Boolean(req.smartAccountDeployed), this.chainNamespace) + this.appKit?.setSmartAccountDeployed( + Boolean(user.smartAccountDeployed), + this.chainNamespace + ) this.appKit?.setPreferredAccountType( - req.preferredAccountType as W3mFrameTypes.AccountType, + user.preferredAccountType as W3mFrameTypes.AccountType, this.chainNamespace ) - this.appKit?.setLoading(false) this.appKit?.setAllAccounts( - req.accounts || [ + user.accounts || [ { - address: req.address, - type: (req.preferredAccountType || 'eoa') as W3mFrameTypes.AccountType + address: user.address, + type: (user.preferredAccountType || 'eoa') as W3mFrameTypes.AccountType } ], this.chainNamespace ) + StorageUtil.setConnectedConnector('AUTH') + this.appKit?.setLoading(false) }) provider.onGetSmartAccountEnabledNetworks(networks => { diff --git a/packages/adapters/wagmi/src/tests/client.test.ts b/packages/adapters/wagmi/src/tests/client.test.ts index ffd65f30dd..7d111b6980 100644 --- a/packages/adapters/wagmi/src/tests/client.test.ts +++ b/packages/adapters/wagmi/src/tests/client.test.ts @@ -413,7 +413,7 @@ describe('Wagmi Client', () => { expect(mockAppKit.addConnector).toHaveBeenCalledWith({ id: ConstantsUtil.AUTH_CONNECTOR_ID, type: 'AUTH', - name: 'Auth', + name: 'w3mAuth', provider: 'mockProvider', chain: 'eip155' }) @@ -438,7 +438,8 @@ describe('Wagmi Client', () => { onIsConnected: vi.fn(), onGetSmartAccountEnabledNetworks: vi.fn(), onSetPreferredAccount: vi.fn(), - rejectRpcRequests: vi.fn() + rejectRpcRequests: vi.fn(), + onConnect: vi.fn() } mockConnector = { getProvider: vi.fn().mockResolvedValue(mockProvider) diff --git a/packages/core/src/controllers/ConnectorController.ts b/packages/core/src/controllers/ConnectorController.ts index f9200aa4a5..7217bf0d0e 100644 --- a/packages/core/src/controllers/ConnectorController.ts +++ b/packages/core/src/controllers/ConnectorController.ts @@ -55,13 +55,15 @@ export const ConnectorController = { connectorsByNameMap.forEach(keyConnectors => { const firstItem = keyConnectors[0] + const isAuthConnector = firstItem?.id === 'w3mAuth' + if (keyConnectors.length > 1) { mergedConnectors.push({ name: firstItem?.name, imageUrl: firstItem?.imageUrl, imageId: firstItem?.imageId, connectors: [...keyConnectors], - type: 'MULTI_CHAIN', + type: isAuthConnector ? 'AUTH' : 'MULTI_CHAIN', // These values are just placeholders, we don't use them in multi-chain connector select screen chain: 'eip155', id: firstItem?.id || '' @@ -152,10 +154,10 @@ export const ConnectorController = { return undefined } - if (authConnector.type === 'MULTI_CHAIN' && authConnector?.connectors?.length) { - return authConnector.connectors.find(c => c.chain === activeNamespace) as - | AuthConnector - | undefined + if (authConnector?.connectors?.length) { + const connector = authConnector.connectors.find(c => c.chain === activeNamespace) + + return connector as AuthConnector | undefined } return authConnector as AuthConnector diff --git a/packages/core/tests/controllers/ConnectorController.test.ts b/packages/core/tests/controllers/ConnectorController.test.ts index b36c14b0c8..f3058a9873 100644 --- a/packages/core/tests/controllers/ConnectorController.test.ts +++ b/packages/core/tests/controllers/ConnectorController.test.ts @@ -53,6 +53,14 @@ const announcedConnector = { name: 'Announced' } as const +const announcedConnectorSolana = { + id: 'announced', + type: 'ANNOUNCED', + info: { rdns: 'announced.solana.io' }, + chain: ConstantsUtil.CHAIN.SOLANA, + name: 'Announced' +} as const + const syncDappDataSpy = vi.spyOn(authProvider, 'syncDappData') const syncThemeSpy = vi.spyOn(authProvider, 'syncTheme') @@ -179,7 +187,7 @@ describe('ConnectorController', () => { imageId: undefined, imageUrl: undefined, name: 'Auth', - type: 'MULTI_CHAIN', + type: 'AUTH', chain: 'eip155', connectors: [ { @@ -207,4 +215,56 @@ describe('ConnectorController', () => { announcedConnector ]) }) + + it('should merge connectors with the same chain', () => { + const mergedAnnouncedConnector = { + id: 'announced', + imageId: undefined, + imageUrl: undefined, + name: 'Announced', + type: 'MULTI_CHAIN', + chain: 'eip155', + connectors: [announcedConnector, announcedConnectorSolana] + } + + const mergedAuthConnector = { + id: 'w3mAuth', + imageId: undefined, + imageUrl: undefined, + name: 'Auth', + type: 'AUTH', + chain: 'eip155', + connectors: [ + { + chain: 'eip155', + id: 'w3mAuth', + name: 'Auth', + provider: { + syncDappData: syncDappDataSpy, + syncTheme: syncThemeSpy + }, + type: 'AUTH' + }, + { + chain: 'solana', + id: 'w3mAuth', + name: 'Auth', + provider: { + syncDappData: syncDappDataSpy, + syncTheme: syncThemeSpy + }, + type: 'AUTH' + } + ] + } + ConnectorController.addConnector(announcedConnectorSolana) + expect(ConnectorController.getConnectors()).toEqual([ + walletConnectConnector, + externalConnector, + metamaskConnector, + zerionConnector, + mergedAuthConnector, + mergedAnnouncedConnector + ]) + }) }) diff --git a/packages/wallet/src/W3mFrameProvider.ts b/packages/wallet/src/W3mFrameProvider.ts index 678d5c64f7..1c994d3107 100644 --- a/packages/wallet/src/W3mFrameProvider.ts +++ b/packages/wallet/src/W3mFrameProvider.ts @@ -365,12 +365,13 @@ export class W3mFrameProvider { this.rpcErrorHandler = callback } - public onIsConnected( - callback: (request: W3mFrameTypes.Responses['FrameGetUserResponse']) => void - ) { + public onIsConnected(callback: () => void) { this.w3mFrame.events.onFrameEvent(event => { - if (event.type === W3mFrameConstants.FRAME_GET_USER_SUCCESS) { - callback(event.payload) + if ( + event.type === W3mFrameConstants.FRAME_IS_CONNECTED_SUCCESS && + event.payload.isConnected + ) { + callback() } }) } @@ -389,6 +390,14 @@ export class W3mFrameProvider { }) } + public onConnect(callback: (user: W3mFrameTypes.Responses['FrameGetUserResponse']) => void) { + this.w3mFrame.events.onFrameEvent(event => { + if (event.type === W3mFrameConstants.FRAME_GET_USER_SUCCESS) { + callback(event.payload) + } + }) + } + public async getCapabilities(): Promise> { try { const capabilities = await this.request({