Skip to content

Commit

Permalink
Merge branch 'main' into fix/apkt-769-bug-solana-error-on-changing-ne…
Browse files Browse the repository at this point in the history
…twork-in-solana
  • Loading branch information
enesozturk authored Aug 8, 2024
2 parents e43b319 + 95d9b7f commit 66d64a3
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 30 deletions.
1 change: 1 addition & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm run typecheck; pnpm run lint;
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"build:demo": "pnpm build; pnpm --filter=./apps/demo build",
"build:examples": "pnpm build; pnpm --filter=./examples -r build",
"test": "turbo run test",
"test:static": "pnpm run typecheck; pnpm run lint; pnpm run prettier",
"coverage:merge": "node ./scripts/coverage-merge.js",
"coverage:summary": "node ./scripts/coverage-summary.js",
"typecheck": "turbo run typecheck",
Expand All @@ -30,25 +31,27 @@
"publish:latest": "pnpm install; pnpm build; changeset publish",
"publish:alpha": "pnpm install; pnpm build; changeset publish --tag alpha",
"publish:beta": "pnpm install; pnpm build; changeset publish --tag beta",
"publish:canary": "pnpm install; pnpm build; changeset publish --tag canary"
"publish:canary": "pnpm install; pnpm build; changeset publish --tag canary",
"prepare": "husky"
},
"devDependencies": {
"@changesets/changelog-github": "0.5.0",
"@changesets/cli": "2.27.1",
"@vitest/coverage-v8": "1.1.2",
"@typescript-eslint/eslint-plugin": "6.18.1",
"@typescript-eslint/parser": "6.18.1",
"@vitest/coverage-v8": "1.1.2",
"danger": "11.3.1",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-require-extensions": "0.1.3",
"husky": "9.0.11",
"prettier": "3.1.1",
"turbo": "2.0.6-canary.0",
"typescript": "5.3.3",
"vite": "5.2.11",
"vitest": "1.5.0",
"vite-plugin-node-polyfills": "0.22.0"
"vite-plugin-node-polyfills": "0.22.0",
"vitest": "1.5.0"
},
"packageManager": "[email protected]",
"pnpm": {
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/controllers/ApiController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const baseUrl = CoreHelperUtil.getApiUrl()
export const api = new FetchUtil({ baseUrl, clientId: null })
const entries = '40'
const recommendedEntries = '4'
const imageCountToFetch = 20

// -- Types --------------------------------------------- //
export interface ApiControllerState {
Expand Down Expand Up @@ -194,11 +195,11 @@ export const ApiController = {
exclude: exclude.join(',')
}
})
const images = data.map(w => w.image_id).filter(Boolean)
await Promise.allSettled([
...(images as string[]).map(id => ApiController._fetchWalletImage(id)),
CoreHelperUtil.wait(300)
])
const images = data
.slice(0, imageCountToFetch)
.map(w => w.image_id)
.filter(Boolean)
await Promise.allSettled((images as string[]).map(id => ApiController._fetchWalletImage(id)))

state.wallets = CoreHelperUtil.uniqueBy(
[...state.wallets, ...ApiController._filterOutExtensions(data)],
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/utils/AssetUtil.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import { ApiController } from '../controllers/ApiController.js'
import { AssetController } from '../controllers/AssetController.js'
import type { CaipNetwork, Connector, WcWallet } from './TypeUtil.js'

export const AssetUtil = {
async fetchWalletImage(imageId?: string) {
if (!imageId) {
return undefined
}

await ApiController._fetchWalletImage(imageId)

return this.getWalletImageById(imageId)
},

getWalletImageById(imageId?: string) {
if (!imageId) {
return undefined
}

return AssetController.state.walletImages[imageId]
},

getWalletImage(wallet?: WcWallet) {
if (wallet?.image_url) {
return wallet?.image_url
Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/utils/CoreHelperUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,19 @@ export const CoreHelperUtil = {
},

formatBalance(balance: string | undefined, symbol: string | undefined) {
let formattedBalance = undefined
let formattedBalance = '0.000'

if (balance === '0') {
formattedBalance = '0.000'
} else if (typeof balance === 'string') {
if (typeof balance === 'string') {
const number = Number(balance)
if (number) {
formattedBalance = number.toString().match(/^-?\d+(?:\.\d{0,3})?/u)?.[0]
const formattedValue = Math.floor(number * 1000) / 1000
if (formattedValue) {
formattedBalance = formattedValue.toString()
}
}
}

return formattedBalance ? `${formattedBalance} ${symbol ?? ''}` : `0.000 ${symbol ?? ''}`
return `${formattedBalance}${symbol ? ` ${symbol}` : ''}`
},

formatBalance2(balance: string | undefined, symbol: string | undefined) {
Expand Down
99 changes: 99 additions & 0 deletions packages/core/tests/utils/AssetUtil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { AssetController } from '../../src/controllers/AssetController.js'
import { AssetUtil } from '../../src/utils/AssetUtil.js'
import type { CaipNetwork, Connector, WcWallet } from '../../src/utils/TypeUtil.js'
import { ApiController } from '../../src/controllers/ApiController.js'

// - Mocks ---------------------------------------------------------------------
const connector: Partial<Connector> = {
imageUrl: undefined,
imageId: 'walletconnect'
}
const connectorWithImageUrl: Partial<Connector> = {
imageUrl: 'walletconnect-connector-logo-src',
imageId: 'walletconnect'
}
const network: Partial<CaipNetwork> = {
imageUrl: undefined,
imageId: 'ethereum'
}
const networkWithImageUrl: Partial<Connector> = {
imageUrl: 'ethereum-logo-src',
imageId: 'ethereum'
}
const wallet: Partial<WcWallet> = {
image_url: undefined,
image_id: 'metamask'
}
const walletWithImageUrl: Partial<WcWallet> = {
image_url: 'metamask-logo-src',
image_id: 'metamask'
}

// -- Setup --------------------------------------------------------------------
ApiController._fetchWalletImage = vi.fn().mockImplementation((walletId: string) => {
AssetController.state = {
...AssetController.state,
walletImages: {
...AssetController.state.walletImages,
[walletId]: `new-wallet-image-url-${walletId}`
}
}
})
beforeEach(() => {
AssetController.state = {
...AssetController.state,
connectorImages: {
walletconnect: 'walletconnect-connector-logo-blob-url'
},
walletImages: {
metamask: 'metamask-logo-blob-url'
},
networkImages: {
ethereum: 'ethereum-logo-blob-url'
}
}
})

// -- Tests --------------------------------------------------------------------
describe('AssetUtil', () => {
it('should get the connector image from connector object', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getConnectorImage(connectorWithImageUrl)).toBe(
'walletconnect-connector-logo-src'
)
})

it('should get the connector image from AssetController state', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getConnectorImage(connector)).toBe('walletconnect-connector-logo-blob-url')
})

it('should get the network image from network object', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getNetworkImage(networkWithImageUrl)).toBe('ethereum-logo-src')
})

it('should get the network image from AssetController state', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getNetworkImage(network)).toBe('ethereum-logo-blob-url')
})

it('should get the wallet image from wallet object', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getWalletImage(walletWithImageUrl)).toBe('metamask-logo-src')
})

it('should get the wallet image from AssetController state', () => {
// @ts-expect-error it's a partial connector object
expect(AssetUtil.getWalletImage(wallet)).toBe('metamask-logo-blob-url')
})

it('should get the wallet with image id', () => {
expect(AssetUtil.getWalletImageById(wallet.image_id)).toBe('metamask-logo-blob-url')
})

it('should fetch the wallet with image id', async () => {
expect(await AssetUtil.fetchWalletImage('rainbow-id')).toBe('new-wallet-image-url-rainbow-id')
})
})
17 changes: 17 additions & 0 deletions packages/core/tests/utils/CoreHelperUtil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, expect, it } from 'vitest'
import { CoreHelperUtil } from '../../src/utils/CoreHelperUtil.js'

// -- Tests --------------------------------------------------------------------
describe('CoreHelperUtil', () => {
it('should return format balance as expected', () => {
expect(CoreHelperUtil.formatBalance(undefined, undefined)).toBe('0.000')
expect(CoreHelperUtil.formatBalance('0', undefined)).toBe('0.000')
expect(CoreHelperUtil.formatBalance('123.456789', 'ETH')).toBe('123.456 ETH')
expect(CoreHelperUtil.formatBalance('123.456789', undefined)).toBe('123.456')
expect(CoreHelperUtil.formatBalance('0.000456789', 'BTC')).toBe('0.000 BTC')
expect(CoreHelperUtil.formatBalance('123456789.123456789', 'USD')).toBe('123456789.123 USD')
expect(CoreHelperUtil.formatBalance('abc', 'USD')).toBe('0.000 USD')
expect(CoreHelperUtil.formatBalance('', 'USD')).toBe('0.000 USD')
expect(CoreHelperUtil.formatBalance('0', 'ETH')).toBe('0.000 ETH')
})
})
1 change: 1 addition & 0 deletions packages/scaffold-ui/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export * from '../src/views/w3m-connecting-farcaster-view/index.js'

// -- Partials ------------------------------------------ //
export * from '../src/partials/w3m-all-wallets-list/index.js'
export * from '../src/partials/w3m-all-wallets-list-item/index.js'
export * from '../src/partials/w3m-all-wallets-search/index.js'
export * from '../src/partials/w3m-connecting-header/index.js'
export * from '../src/partials/w3m-connecting-wc-browser/index.js'
Expand Down
101 changes: 101 additions & 0 deletions packages/scaffold-ui/src/partials/w3m-all-wallets-list-item/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { customElement } from '@web3modal/ui'
import { LitElement, html } from 'lit'
import { property, state } from 'lit/decorators.js'
import { ifDefined } from 'lit/directives/if-defined.js'
import { AssetUtil, type WcWallet } from '@web3modal/core'
import styles from './styles.js'

@customElement('w3m-all-wallets-list-item')
export class W3mAllWalletsListItem extends LitElement {
public static override styles = styles

// -- Members ------------------------------------------- //
private observer = new IntersectionObserver(() => undefined)

// -- State & Properties -------------------------------- //
@state() private visible = false

@state() private imageSrc: string | undefined = undefined

@state() private imageLoading = false

@property() private wallet: (WcWallet & { installed: boolean }) | undefined = undefined

// -- Lifecycle ----------------------------------------- //
constructor() {
super()
this.observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.visible = true
this.fetchImageSrc()
} else {
this.visible = false
}
})
},
{ threshold: 0.01 }
)
}

public override firstUpdated() {
this.observer.observe(this)
}

public override disconnectedCallback() {
this.observer.disconnect()
}

// -- Render -------------------------------------------- //
public override render() {
return html`
<button ontouchstart>
${this.imageTemplate()}
<wui-text variant="tiny-500" color="inherit">${this.wallet?.name}</wui-text>
</button>
`
}

private imageTemplate() {
if ((!this.visible && !this.imageSrc) || this.imageLoading) {
return this.shimmerTemplate()
}

return html`
<wui-wallet-image
size="md"
imageSrc=${ifDefined(this.imageSrc)}
name=${this.wallet?.name}
.installed=${this.wallet?.installed}
badgeSize="sm"
>
</wui-wallet-image>
`
}

private shimmerTemplate() {
return html`<wui-shimmer width="56px" height="56px" borderRadius="xs"></wui-shimmer>`
}

private async fetchImageSrc() {
if (!this.wallet) {
return
}
this.imageSrc = AssetUtil.getWalletImage(this.wallet)

if (this.imageSrc) {
return
}

this.imageLoading = true
this.imageSrc = await AssetUtil.fetchWalletImage(this.wallet.image_id)
this.imageLoading = false
}
}

declare global {
interface HTMLElementTagNameMap {
'w3m-all-wallets-list-item': W3mAllWalletsListItem
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { css } from 'lit'

export default css`
button {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 76px;
row-gap: var(--wui-spacing-xs);
padding: var(--wui-spacing-xs) var(--wui-spacing-0);
background-color: var(--wui-color-gray-glass-002);
border-radius: clamp(0px, var(--wui-border-radius-xs), 20px);
will-change: background-color, color;
outline: none;
border: none;
}
button > wui-text {
color: var(--wui-color-fg-100);
max-width: var(--wui-icon-box-size-xl);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
justify-content: center;
}
button:hover:enabled {
background-color: var(--wui-color-gray-glass-005);
}
button:disabled > wui-text {
color: var(--wui-color-gray-glass-015);
}
[data-selected='true'] {
background-color: var(--wui-color-accent-glass-020);
}
@media (hover: hover) and (pointer: fine) {
[data-selected='true']:hover:enabled {
background-color: var(--wui-color-accent-glass-015);
}
}
[data-selected='true']:active:enabled {
background-color: var(--wui-color-accent-glass-010);
}
`
Loading

0 comments on commit 66d64a3

Please sign in to comment.