Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: filter out the duplicate wallets when there is both injected and recent #3446

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
23 changes: 23 additions & 0 deletions .changeset/warm-ligers-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@reown/appkit-scaffold-ui': patch
'@apps/builder': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-cli': 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-ui': patch
'@reown/appkit-wallet': patch
'@reown/appkit-wallet-button': patch
---

Filter out when there is duplicate wallet items in recents and injected wallets
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
import type { WcWallet } from '@reown/appkit-core'
import { AssetUtil, RouterController, StorageUtil } from '@reown/appkit-core'
import { AssetUtil, ConnectorController, RouterController, StorageUtil } from '@reown/appkit-core'
import { customElement } from '@reown/appkit-ui'
import { LitElement, html } from 'lit'
import { property } from 'lit/decorators.js'
import { property, state } from 'lit/decorators.js'
import { ifDefined } from 'lit/directives/if-defined.js'

@customElement('w3m-connect-recent-widget')
export class W3mConnectRecentWidget extends LitElement {
// -- Members ------------------------------------------- //
private unsubscribe: (() => void)[] = []

// -- State & Properties -------------------------------- //
@property() public tabIdx?: number = undefined

@state() private connectors = ConnectorController.state.connectors

// -- Lifecycle ----------------------------------------- //
public constructor() {
super()
this.unsubscribe.push(
ConnectorController.subscribeKey('connectors', val => (this.connectors = val))
)
}

// -- Render -------------------------------------------- //
public override render() {
const recent = StorageUtil.getRecentWallets()
const recentWallets = StorageUtil.getRecentWallets()
const filteredRecentWallets = recentWallets.filter(
wallet =>
!this.connectors.some(
connector => connector.id === wallet.id || connector.name === wallet.name
)
)

if (!recent?.length) {
if (!filteredRecentWallets.length) {
this.style.cssText = `display: none`

return null
}

return html`
<wui-flex flexDirection="column" gap="xs">
${recent.map(
${filteredRecentWallets.map(
wallet => html`
<wui-list-wallet
imageSrc=${ifDefined(AssetUtil.getWalletImage(wallet))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class W3mConnectingWcView extends LitElement {
if (wcLinking) {
StorageUtil.setWalletConnectDeepLink(wcLinking)
}

if (recentWallet) {
StorageUtil.setAppKitRecent(recentWallet)
}
Expand Down
120 changes: 120 additions & 0 deletions packages/scaffold-ui/test/partials/w3m-connect-recent-widget.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { W3mConnectRecentWidget } from '../../src/partials/w3m-connect-recent-widget'
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { fixture } from '@open-wc/testing'
import { html } from 'lit'
import { ConnectorController, RouterController, StorageUtil } from '@reown/appkit-core'

describe('W3mConnectRecentWidget', () => {
const mockRecentWallets = [
{ id: 'recent1', name: 'Recent Wallet 1' },
{ id: 'recent2', name: 'Recent Wallet 2' }
]

const mockConnectors = [
{ id: 'connector1', name: 'Connector 1' },
{ id: 'recent1', name: 'Recent Wallet 1' } // Matching wallet
]

let subscribeCallback: (connectors: any) => void

beforeEach(() => {
subscribeCallback = vi.fn()

vi.spyOn(StorageUtil, 'getRecentWallets').mockReturnValue(mockRecentWallets)

vi.spyOn(ConnectorController, 'state', 'get').mockReturnValue({
connectors: mockConnectors
} as any)

vi.spyOn(ConnectorController, 'subscribeKey').mockImplementation((_, callback) => {
subscribeCallback = callback
return () => undefined
})
})

afterEach(() => {
vi.clearAllMocks()
})

it('should render filtered recent wallets when there are matching connectors', async () => {
const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget></w3m-connect-recent-widget>`
)

const walletElements = element.shadowRoot?.querySelectorAll('wui-list-wallet')
expect(walletElements?.length).toBe(1)

const walletName = walletElements?.[0]?.getAttribute('name')
expect(walletName).toBe('Recent Wallet 2')
})

it('should render all recent wallets when there are no matching connectors', async () => {
vi.spyOn(ConnectorController, 'state', 'get').mockReturnValue({
connectors: [{ id: 'connector1', name: 'Connector 1' }]
} as any)

const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget></w3m-connect-recent-widget>`
)

const walletElements = element.shadowRoot?.querySelectorAll('wui-list-wallet')
expect(walletElements?.length).toBe(2)

const walletNames = Array.from(walletElements || []).map(el => el.getAttribute('name'))
expect(walletNames).toContain('Recent Wallet 1')
expect(walletNames).toContain('Recent Wallet 2')
})

it('should not render widget when there are no recent wallets', async () => {
vi.spyOn(StorageUtil, 'getRecentWallets').mockReturnValue([])

const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget></w3m-connect-recent-widget>`
)

expect(element.style.display).toBe('none')
expect(element.shadowRoot?.querySelector('wui-flex')).toBeNull()
})

it('should handle wallet click and navigate to connecting view', async () => {
const routerSpy = vi.spyOn(RouterController, 'push')

const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget></w3m-connect-recent-widget>`
)

const walletElement = element.shadowRoot?.querySelector('wui-list-wallet')
walletElement?.click()

expect(routerSpy).toHaveBeenCalledWith('ConnectingWalletConnect', {
wallet: mockRecentWallets[1]
})
})

it('should respect tabIdx property', async () => {
const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget .tabIdx=${2}></w3m-connect-recent-widget>`
)

const walletElement = element.shadowRoot?.querySelector('wui-list-wallet')
expect(walletElement?.getAttribute('tabIdx')).toBe('2')
})

it('should update when connectors change', async () => {
const element: W3mConnectRecentWidget = await fixture(
html`<w3m-connect-recent-widget></w3m-connect-recent-widget>`
)

expect(element.shadowRoot?.querySelectorAll('wui-list-wallet').length).toBe(1)

vi.spyOn(ConnectorController, 'state', 'get').mockReturnValue({
connectors: [{ id: 'connector1', name: 'Connector 1' }]
} as any)

subscribeCallback([{ id: 'connector1', name: 'Connector 1' }])

await element.updateComplete

expect(element.shadowRoot?.querySelectorAll('wui-list-wallet').length).toBe(2)
})
})
Loading