Skip to content

Commit

Permalink
fix: coinbase wallet not reconnecting (ethers/ethers5) (#3189)
Browse files Browse the repository at this point in the history
  • Loading branch information
magiziz authored Nov 6, 2024
1 parent a3cf602 commit db30b41
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 49 deletions.
24 changes: 24 additions & 0 deletions .changeset/clean-books-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit-scaffold-ui': patch
'@apps/laboratory': patch
'@reown/appkit': patch
'@reown/appkit-ui': patch
'@apps/demo': patch
'@apps/gallery': patch
'@reown/appkit-adapter-polkadot': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-common': patch
'@reown/appkit-core': patch
'@reown/appkit-experimental': patch
'@reown/appkit-polyfills': patch
'@reown/appkit-siwe': patch
'@reown/appkit-siwx': patch
'@reown/appkit-wallet': patch
---

Fixes an issue where Coinbase Wallet did not reconnect after refreshing the page when using ethers/ethers5 adapters.
12 changes: 5 additions & 7 deletions apps/laboratory/src/components/AppKitHooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ export function AppKitHooks() {
Open
</Button>

<Button
data-testid="disconnect-hook-button"
isDisabled={!isConnected}
onClick={() => disconnect()}
>
Disconnect
</Button>
{isConnected && (
<Button data-testid="disconnect-hook-button" onClick={disconnect}>
Disconnect
</Button>
)}

<Button data-testid="switch-network-hook-button" onClick={handleSwitchNetwork}>
Switch Network
Expand Down
13 changes: 9 additions & 4 deletions packages/adapters/ethers/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export class EthersAdapter {
},
[ConstantsUtil.COINBASE_SDK_CONNECTOR_ID]: {
getProvider: () => this.ethersConfig?.coinbase,
providerType: 'coinbase' as const
providerType: 'coinbaseWalletSDK' as const
},
[ConstantsUtil.AUTH_CONNECTOR_ID]: {
getProvider: () => this.authProvider,
Expand Down Expand Up @@ -325,7 +325,9 @@ export class EthersAdapter {
},

disconnect: async () => {
const provider = ProviderUtil.getProvider<UniversalProvider | Provider>('eip155')
const provider = ProviderUtil.getProvider<UniversalProvider | Provider | ProviderInterface>(
'eip155'
)
const providerId = ProviderUtil.state.providerIds['eip155']

this.appKit?.setClientId(null)
Expand All @@ -338,8 +340,11 @@ export class EthersAdapter {
[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: async () =>
await this.appKit?.universalAdapter?.connectionControllerClient?.disconnect(),

coinbaseWalletSDK: async () =>
await this.appKit?.universalAdapter?.connectionControllerClient?.disconnect(),
coinbaseWalletSDK: async () => {
if (provider && 'disconnect' in provider) {
await provider.disconnect()
}
},

[ConstantsUtil.AUTH_CONNECTOR_ID]: async () => {
await this.authProvider?.disconnect()
Expand Down
41 changes: 24 additions & 17 deletions packages/adapters/ethers/src/tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,10 @@ describe('EthersAdapter', () => {
})

describe('EthersClient - checkActiveProviders', () => {
let mockInjectedProvider: any
let mockProvider: any

beforeEach(() => {
mockInjectedProvider = {
mockProvider = {
request: vi.fn(),
on: vi.fn(),
removeListener: vi.fn()
Expand All @@ -635,31 +635,38 @@ describe('EthersAdapter', () => {
vi.spyOn(client as any, 'setupProviderListeners').mockImplementation(() => {})
})

it('should check and set active provider for injected wallet', () => {
it('should check and set active provider for injected and coinbase wallet', () => {
const mockConfig = {
injected: mockInjectedProvider,
coinbase: undefined,
injected: mockProvider,
coinbase: mockProvider,
metadata: {}
}
} as ProviderType

const providers = {
[ConstantsUtil.INJECTED_CONNECTOR_ID]: 'MetaMask',
[ConstantsUtil.COINBASE_SDK_CONNECTOR_ID]: 'Coinbase Wallet'
} as const

for (const [key, name] of Object.entries(providers)) {
vi.spyOn(SafeLocalStorage, 'getItem').mockImplementation(localStorageKey => {
if (localStorageKey === SafeLocalStorageKeys.WALLET_ID) return key
if (localStorageKey === SafeLocalStorageKeys.WALLET_NAME) return name
return undefined
})

client['checkActiveProviders'](mockConfig as ProviderType)
client['checkActiveProviders'](mockConfig)

expect(SafeLocalStorage.getItem).toHaveBeenCalledWith(SafeLocalStorageKeys.WALLET_ID)
expect(client['setProvider']).toHaveBeenCalledWith(
mockInjectedProvider,
ConstantsUtil.INJECTED_CONNECTOR_ID
)
expect(client['setupProviderListeners']).toHaveBeenCalledWith(
mockInjectedProvider,
ConstantsUtil.INJECTED_CONNECTOR_ID
)
expect(SafeLocalStorage.getItem).toHaveBeenCalledWith(SafeLocalStorageKeys.WALLET_ID)
expect(client['setProvider']).toHaveBeenCalledWith(mockProvider, key)
expect(client['setupProviderListeners']).toHaveBeenCalledWith(mockProvider, key)
}
})

it('should not set provider when wallet ID is not found', () => {
vi.spyOn(SafeLocalStorage, 'getItem').mockReturnValue(undefined)

const mockConfig = {
injected: mockInjectedProvider,
injected: mockProvider,
coinbase: undefined,
metadata: {}
}
Expand Down
13 changes: 9 additions & 4 deletions packages/adapters/ethers5/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export class Ethers5Adapter {
},
[ConstantsUtil.COINBASE_SDK_CONNECTOR_ID]: {
getProvider: () => this.ethersConfig?.coinbase,
providerType: 'coinbase' as const
providerType: 'coinbaseWalletSDK' as const
},
[ConstantsUtil.AUTH_CONNECTOR_ID]: {
getProvider: () => this.authProvider,
Expand Down Expand Up @@ -325,7 +325,9 @@ export class Ethers5Adapter {
},

disconnect: async () => {
const provider = ProviderUtil.getProvider<UniversalProvider | Provider>('eip155')
const provider = ProviderUtil.getProvider<UniversalProvider | Provider | ProviderInterface>(
'eip155'
)
const providerId = ProviderUtil.state.providerIds['eip155']

this.appKit?.setClientId(null)
Expand All @@ -338,8 +340,11 @@ export class Ethers5Adapter {
[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: async () =>
await this.appKit?.universalAdapter?.connectionControllerClient?.disconnect(),

coinbaseWalletSDK: async () =>
await this.appKit?.universalAdapter?.connectionControllerClient?.disconnect(),
coinbaseWalletSDK: async () => {
if (provider && 'disconnect' in provider) {
await provider.disconnect()
}
},

[ConstantsUtil.AUTH_CONNECTOR_ID]: async () => {
await this.authProvider?.disconnect()
Expand Down
41 changes: 24 additions & 17 deletions packages/adapters/ethers5/src/tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,10 @@ describe('EthersAdapter', () => {
})

describe('EthersClient - checkActiveProviders', () => {
let mockInjectedProvider: any
let mockProvider: any

beforeEach(() => {
mockInjectedProvider = {
mockProvider = {
request: vi.fn(),
on: vi.fn(),
removeListener: vi.fn()
Expand All @@ -638,31 +638,38 @@ describe('EthersAdapter', () => {
vi.spyOn(client as any, 'setupProviderListeners').mockImplementation(() => {})
})

it('should check and set active provider for injected wallet', () => {
it('should check and set active provider for injected and coinbase wallet', () => {
const mockConfig = {
injected: mockInjectedProvider,
coinbase: undefined,
injected: mockProvider,
coinbase: mockProvider,
metadata: {}
}
} as ProviderType

const providers = {
[ConstantsUtil.INJECTED_CONNECTOR_ID]: 'MetaMask',
[ConstantsUtil.COINBASE_SDK_CONNECTOR_ID]: 'Coinbase Wallet'
} as const

for (const [key, name] of Object.entries(providers)) {
vi.spyOn(SafeLocalStorage, 'getItem').mockImplementation(localStorageKey => {
if (localStorageKey === SafeLocalStorageKeys.WALLET_ID) return key
if (localStorageKey === SafeLocalStorageKeys.WALLET_NAME) return name
return undefined
})

client['checkActiveProviders'](mockConfig as ProviderType)
client['checkActiveProviders'](mockConfig)

expect(SafeLocalStorage.getItem).toHaveBeenCalledWith(SafeLocalStorageKeys.WALLET_ID)
expect(client['setProvider']).toHaveBeenCalledWith(
mockInjectedProvider,
ConstantsUtil.INJECTED_CONNECTOR_ID
)
expect(client['setupProviderListeners']).toHaveBeenCalledWith(
mockInjectedProvider,
ConstantsUtil.INJECTED_CONNECTOR_ID
)
expect(SafeLocalStorage.getItem).toHaveBeenCalledWith(SafeLocalStorageKeys.WALLET_ID)
expect(client['setProvider']).toHaveBeenCalledWith(mockProvider, key)
expect(client['setupProviderListeners']).toHaveBeenCalledWith(mockProvider, key)
}
})

it('should not set provider when wallet ID is not found', () => {
vi.spyOn(SafeLocalStorage, 'getItem').mockReturnValue(undefined)

const mockConfig = {
injected: mockInjectedProvider,
injected: mockProvider,
coinbase: undefined,
metadata: {}
}
Expand Down

0 comments on commit db30b41

Please sign in to comment.