Skip to content

Commit

Permalink
feat: walletconnect certified (#3206)
Browse files Browse the repository at this point in the history
  • Loading branch information
magiziz authored Nov 10, 2024
1 parent 66fdcf7 commit f4ce9d4
Show file tree
Hide file tree
Showing 29 changed files with 510 additions and 70 deletions.
24 changes: 24 additions & 0 deletions .changeset/spicy-mice-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'@reown/appkit-scaffold-ui': patch
'@apps/laboratory': patch
'@reown/appkit-core': patch
'@apps/gallery': patch
'@reown/appkit-ui': patch
'@apps/demo': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-polkadot': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-common': patch
'@reown/appkit-experimental': patch
'@reown/appkit-polyfills': patch
'@reown/appkit-siwe': patch
'@reown/appkit-siwx': patch
'@reown/appkit-wallet': patch
---

Added walletconnect certified badge in all wallets view.
27 changes: 27 additions & 0 deletions apps/gallery/stories/composites/wui-certified-switch.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Meta } from '@storybook/web-components'
import '@reown/appkit-ui/src/composites/wui-certified-switch'
import type { WuiCertifiedSwitch } from '@reown/appkit-ui/src/composites/wui-certified-switch'
import { html } from 'lit'
import '../../components/gallery-container'

type Component = Meta<WuiCertifiedSwitch>

export default {
title: 'Composites/wui-certified-switch',
args: {
checked: false
},
argTypes: {
checked: {
control: { type: 'boolean' }
}
}
} as Component

export const Default: Component = {
render: args => html`
<gallery-container width="88" height="44">
<wui-certified-switch ?checked=${args.checked}></wui-certified-switch>
</gallery-container>
`
}
27 changes: 27 additions & 0 deletions apps/gallery/stories/composites/wui-switch.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Meta } from '@storybook/web-components'
import '@reown/appkit-ui/src/composites/wui-switch'
import type { WuiSwitch } from '@reown/appkit-ui/src/composites/wui-switch'
import { html } from 'lit'
import '../../components/gallery-container'

type Component = Meta<WuiSwitch>

export default {
title: 'Composites/wui-switch',
args: {
checked: false
},
argTypes: {
checked: {
control: { type: 'boolean' }
}
}
} as Component

export const Default: Component = {
render: args => html`
<gallery-container width="32" height="32">
<wui-switch ?checked=${args.checked}></wui-switch>
</gallery-container>
`
}
6 changes: 6 additions & 0 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,12 @@ export class ModalPage {
await allWalletsListSearchItem.click()
}

async clickCertifiedToggle() {
const certifiedSwitch = this.page.getByTestId('wui-certified-switch')
await expect(certifiedSwitch).toBeVisible()
await certifiedSwitch.click()
}

async clickTabWebApp() {
const tabWebApp = this.page.getByTestId('tab-webapp')
await expect(tabWebApp).toBeVisible()
Expand Down
5 changes: 5 additions & 0 deletions apps/laboratory/tests/shared/validators/ModalValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ export class ModalValidator {
expect(queryParameters[key]).toBe(value)
}

async expectAllWalletsListSearchItem(id: string) {
const allWalletsListSearchItem = this.page.getByTestId(`wallet-search-item-${id}`)
await expect(allWalletsListSearchItem).toBeVisible()
}

async expectNoSocials() {
const socialList = this.page.getByTestId('wui-list-social')
await expect(socialList).toBeHidden()
Expand Down
20 changes: 20 additions & 0 deletions apps/laboratory/tests/wallet-features.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ let context: BrowserContext
/* eslint-enable init-declarations */

const ABSOLUTE_WALLET_ID = 'bfa6967fd05add7bb2b19a442ac37cedb6a6b854483729194f5d7185272c5594'
const METAMASK_WALLET_ID = 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96'

// -- Setup --------------------------------------------------------------------
const walletFeaturesTest = test.extend<{ library: string }>({
Expand Down Expand Up @@ -102,4 +103,23 @@ walletFeaturesTest('it should open web app wallet', async () => {
key: 'uri',
value: copiedLink
})
await page.closeModal()
})

walletFeaturesTest('it should search for a certified wallet', async () => {
await page.openConnectModal()
await validator.expectAllWallets()
await page.openAllWallets()
await page.clickCertifiedToggle()
await page.page.waitForTimeout(500)
await validator.expectAllWalletsListSearchItem(METAMASK_WALLET_ID)

// Try searching for a certified wallet while toggle is on
await page.search('MetaMask')
await validator.expectAllWalletsListSearchItem(METAMASK_WALLET_ID)

// Try searching for a certified wallet while toggle is off
await page.clickCertifiedToggle()
await page.search('MetaMask')
await validator.expectAllWalletsListSearchItem(METAMASK_WALLET_ID)
})
39 changes: 23 additions & 16 deletions packages/core/src/controllers/ApiController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { AssetController } from './AssetController.js'
import { ConnectorController } from './ConnectorController.js'
import { OptionsController } from './OptionsController.js'
import { ChainController } from './ChainController.js'
import { EventsController } from './EventsController.js'

// -- Helpers ------------------------------------------- //
const baseUrl = CoreHelperUtil.getApiUrl()
Expand Down Expand Up @@ -56,13 +57,13 @@ export const ApiController = {
return subKey(state, key, callback)
},

_getApiHeaders() {
_getSdkProperties() {
const { projectId, sdkType, sdkVersion } = OptionsController.state

return {
'x-project-id': projectId,
'x-sdk-type': sdkType || 'appkit',
'x-sdk-version': sdkVersion || 'html-wagmi-4.2.2'
projectId,
st: sdkType || 'appkit',
sv: sdkVersion || 'html-wagmi-4.2.2'
}
},

Expand All @@ -76,31 +77,31 @@ export const ApiController = {

async _fetchWalletImage(imageId: string) {
const imageUrl = `${api.baseUrl}/getWalletImage/${imageId}`
const blob = await api.getBlob({ path: imageUrl, headers: ApiController._getApiHeaders() })
const blob = await api.getBlob({ path: imageUrl, params: ApiController._getSdkProperties() })
AssetController.setWalletImage(imageId, URL.createObjectURL(blob))
},

async _fetchNetworkImage(imageId: string) {
const imageUrl = `${api.baseUrl}/public/getAssetImage/${imageId}`
const blob = await api.getBlob({ path: imageUrl, headers: ApiController._getApiHeaders() })
const blob = await api.getBlob({ path: imageUrl, params: ApiController._getSdkProperties() })
AssetController.setNetworkImage(imageId, URL.createObjectURL(blob))
},

async _fetchConnectorImage(imageId: string) {
const imageUrl = `${api.baseUrl}/public/getAssetImage/${imageId}`
const blob = await api.getBlob({ path: imageUrl, headers: ApiController._getApiHeaders() })
const blob = await api.getBlob({ path: imageUrl, params: ApiController._getSdkProperties() })
AssetController.setConnectorImage(imageId, URL.createObjectURL(blob))
},

async _fetchCurrencyImage(countryCode: string) {
const imageUrl = `${api.baseUrl}/public/getCurrencyImage/${countryCode}`
const blob = await api.getBlob({ path: imageUrl, headers: ApiController._getApiHeaders() })
const blob = await api.getBlob({ path: imageUrl, params: ApiController._getSdkProperties() })
AssetController.setCurrencyImage(countryCode, URL.createObjectURL(blob))
},

async _fetchTokenImage(symbol: string) {
const imageUrl = `${api.baseUrl}/public/getTokenImage/${symbol}`
const blob = await api.getBlob({ path: imageUrl, headers: ApiController._getApiHeaders() })
const blob = await api.getBlob({ path: imageUrl, params: ApiController._getSdkProperties() })
AssetController.setTokenImage(symbol, URL.createObjectURL(blob))
},

Expand Down Expand Up @@ -134,8 +135,8 @@ export const ApiController = {
if (featuredWalletIds?.length) {
const { data } = await api.get<ApiGetWalletsResponse>({
path: '/getWallets',
headers: ApiController._getApiHeaders(),
params: {
...ApiController._getSdkProperties(),
page: '1',
entries: featuredWalletIds?.length
? String(featuredWalletIds.length)
Expand All @@ -156,8 +157,8 @@ export const ApiController = {
const exclude = [...(excludeWalletIds ?? []), ...(featuredWalletIds ?? [])].filter(Boolean)
const { data, count } = await api.get<ApiGetWalletsResponse>({
path: '/getWallets',
headers: ApiController._getApiHeaders(),
params: {
...ApiController._getSdkProperties(),
page: '1',
chains: ChainController.state.activeCaipNetwork?.caipNetworkId,
entries: recommendedEntries,
Expand Down Expand Up @@ -190,8 +191,8 @@ export const ApiController = {
].filter(Boolean)
const { data, count } = await api.get<ApiGetWalletsResponse>({
path: '/getWallets',
headers: ApiController._getApiHeaders(),
params: {
...ApiController._getSdkProperties(),
page: String(page),
entries,
chains: ChainController.state.activeCaipNetwork?.caipNetworkId,
Expand All @@ -216,8 +217,8 @@ export const ApiController = {
async searchWalletByIds({ ids }: { ids: string[] }) {
const { data } = await api.get<ApiGetWalletsResponse>({
path: '/getWallets',
headers: ApiController._getApiHeaders(),
params: {
...ApiController._getSdkProperties(),
page: '1',
entries: String(ids.length),
chains: ChainController.state.activeCaipNetwork?.caipNetworkId,
Expand All @@ -234,21 +235,27 @@ export const ApiController = {
}
},

async searchWallet({ search }: Pick<ApiGetWalletsRequest, 'search'>) {
async searchWallet({ search, badge }: Pick<ApiGetWalletsRequest, 'search' | 'badge'>) {
const { includeWalletIds, excludeWalletIds } = OptionsController.state
state.search = []
const { data } = await api.get<ApiGetWalletsResponse>({
path: '/getWallets',
headers: ApiController._getApiHeaders(),
params: {
...ApiController._getSdkProperties(),
page: '1',
entries: '100',
search: search?.trim(),
badge_type: badge,
chains: ChainController.state.activeCaipNetwork?.caipNetworkId,
include: includeWalletIds?.join(','),
exclude: excludeWalletIds?.join(',')
}
})
EventsController.sendEvent({
type: 'track',
event: 'SEARCH_WALLET',
properties: { badge: badge ?? '', search: search ?? '' }
})
const images = data.map(w => w.image_id).filter(Boolean)
await Promise.allSettled([
...(images as string[]).map(id => ApiController._fetchWalletImage(id)),
Expand Down Expand Up @@ -280,7 +287,7 @@ export const ApiController = {
async fetchAnalyticsConfig() {
const { isAnalyticsEnabled } = await api.get<ApiGetAnalyticsConfigResponse>({
path: '/getAnalyticsConfig',
headers: ApiController._getApiHeaders()
params: ApiController._getSdkProperties()
})
OptionsController.setFeatures({ analytics: isAnalyticsEnabled })
}
Expand Down
24 changes: 20 additions & 4 deletions packages/core/src/controllers/SnackController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CoreHelperUtil } from '../utils/CoreHelperUtil.js'
export interface SnackControllerState {
message: string
variant: 'error' | 'success' | 'loading'
svg?: { iconColor: string; icon: string }
open: boolean
}

Expand All @@ -15,6 +16,7 @@ type StateKey = keyof SnackControllerState
const state = proxy<SnackControllerState>({
message: '',
variant: 'success',
svg: undefined,
open: false
})

Expand All @@ -27,33 +29,47 @@ export const SnackController = {
},

showLoading(message: SnackControllerState['message']) {
this._showMessage(message, 'loading')
this._showMessage({ message, variant: 'loading' })
},

showSuccess(message: SnackControllerState['message']) {
this._showMessage(message, 'success')
this._showMessage({ message, variant: 'success' })
},

showSvg(message: SnackControllerState['message'], svg: NonNullable<SnackControllerState['svg']>) {
this._showMessage({ message, svg })
},

showError(message: unknown) {
const errorMessage = CoreHelperUtil.parseError(message)
this._showMessage(errorMessage, 'error')
this._showMessage({ message: errorMessage, variant: 'error' })
},

hide() {
state.open = false
},

_showMessage(message: SnackControllerState['message'], variant: SnackControllerState['variant']) {
_showMessage({
message,
svg,
variant = 'success'
}: {
message: SnackControllerState['message']
svg?: SnackControllerState['svg']
variant?: SnackControllerState['variant']
}) {
if (state.open) {
state.open = false
setTimeout(() => {
state.message = message
state.variant = variant
state.svg = svg
state.open = true
}, 150)
} else {
state.message = message
state.variant = variant
state.svg = svg
state.open = true
}
}
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/utils/TypeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export type Metadata = {
export interface WcWallet {
id: string
name: string
badge_type?: BadgeType
homepage?: string
image_id?: string
image_url?: string
Expand All @@ -133,6 +134,7 @@ export interface ApiGetWalletsRequest {
chains: string
entries: number
search?: string
badge?: BadgeType
include?: string[]
exclude?: string[]
}
Expand Down Expand Up @@ -735,6 +737,14 @@ export type Event =
name: string
}
}
| {
type: 'track'
event: 'SEARCH_WALLET'
properties: {
badge: string
search: string
}
}
// Onramp Types
export type DestinationWallet = {
address: string
Expand Down Expand Up @@ -999,3 +1009,5 @@ export type UseAppKitNetworkReturn = {
caipNetworkId: CaipNetworkId | undefined
switchNetwork: (network: AppKitNetwork) => void
}

export type BadgeType = 'none' | 'certified'
Loading

0 comments on commit f4ce9d4

Please sign in to comment.