From bdf3c1d8828f6e904299c32599dd28bce3594e3d Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:37:26 -0300 Subject: [PATCH 1/3] test: add coverage for fetchTokenList('default') bundled token path Test that the bundled @uniswap/default-token-list returns a non-empty tokens array and that all EVM-addressable entries conform to tokenSchema. The v18 list also includes Solana tokens (base58 addresses) which are expected to fail the EVM address regex and are filtered out downstream by useTokenLists via safeParse. Closes #438 --- src/hooks/useTokenLists.test.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/hooks/useTokenLists.test.ts b/src/hooks/useTokenLists.test.ts index 4a5b1ee9..ec4c5147 100644 --- a/src/hooks/useTokenLists.test.ts +++ b/src/hooks/useTokenLists.test.ts @@ -4,7 +4,7 @@ import type { ReactNode } from 'react' import { createElement } from 'react' import { zeroAddress } from 'viem' import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { Token } from '@/src/types/token' +import { type Token, tokenSchema } from '@/src/types/token' import tokenListsCache, { updateTokenListsCache } from '@/src/utils/tokenListsCache' vi.mock('@/src/utils/tokenListsCache', () => { @@ -155,6 +155,28 @@ describe('fetchTokenList', () => { expect(result.tokens).toEqual([]) warnSpy.mockRestore() }) + + describe("'default' bundled token list", () => { + it('returns a non-empty tokens array', async () => { + const result = await fetchTokenList('default') + + expect(Array.isArray(result.tokens)).toBe(true) + expect(result.tokens.length).toBeGreaterThan(0) + }) + + it('every EVM token entry conforms to tokenSchema', async () => { + const result = await fetchTokenList('default') + + // The bundled list includes non-EVM tokens (e.g. Solana with base58 addresses) + // alongside EVM tokens. Non-EVM entries are filtered out downstream by useTokenLists + // via safeParse. Here we validate only the EVM-addressable subset. + const evmTokens = result.tokens.filter(({ address }) => /^0x[a-fA-F0-9]{40}$/.test(address)) + expect(evmTokens.length).toBeGreaterThan(0) + for (const token of evmTokens) { + expect(() => tokenSchema.parse(token)).not.toThrow() + } + }) + }) }) describe('useTokenLists', () => { From 8856a10363a6517f4bcbc0c882258352e825c7a4 Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:52:57 -0300 Subject: [PATCH 2/3] docs: clarify non-EVM token filtering in useTokenLists Adds a comment explaining that tokenSchema's EVM address format drops Solana and other non-EVM tokens from the bundled list, and that adding non-EVM support requires broader changes. Also renames the related test for clarity. --- src/hooks/useTokenLists.test.ts | 2 +- src/hooks/useTokenLists.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hooks/useTokenLists.test.ts b/src/hooks/useTokenLists.test.ts index ec4c5147..2d3a83cf 100644 --- a/src/hooks/useTokenLists.test.ts +++ b/src/hooks/useTokenLists.test.ts @@ -164,7 +164,7 @@ describe('fetchTokenList', () => { expect(result.tokens.length).toBeGreaterThan(0) }) - it('every EVM token entry conforms to tokenSchema', async () => { + it('every EVM token conforms to tokenSchema', async () => { const result = await fetchTokenList('default') // The bundled list includes non-EVM tokens (e.g. Solana with base58 addresses) diff --git a/src/hooks/useTokenLists.ts b/src/hooks/useTokenLists.ts index fe57ed64..57ddc697 100644 --- a/src/hooks/useTokenLists.ts +++ b/src/hooks/useTokenLists.ts @@ -98,7 +98,10 @@ function combineTokenLists(results: Array>): T new Map( results .flatMap((result) => result.data.tokens) - // ensure that only valid tokens are consumed in runtime + // tokenSchema enforces EVM address format (0x + 40 hex chars), so non-EVM entries + // (e.g. Solana tokens from @uniswap/default-token-list v18+) are silently dropped here. + // Supporting non-EVM chains would require changes to the address schema, chain config, + // wallet integration, and contract lookup -- out of scope for this EVM-focused starter kit. .filter((token) => { const result = tokenSchema.safeParse(token) From cf364823e1b5b4023bed1daea5c7074a814dc1f2 Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:11:26 -0300 Subject: [PATCH 3/3] test: tighten default token path tests per code review - Remove redundant Array.isArray assertion (length check is sufficient) - Assert mockFetch was not called to make the contract of the 'default' path explicit and guard against future regressions --- src/hooks/useTokenLists.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useTokenLists.test.ts b/src/hooks/useTokenLists.test.ts index 2d3a83cf..d76e996e 100644 --- a/src/hooks/useTokenLists.test.ts +++ b/src/hooks/useTokenLists.test.ts @@ -160,8 +160,8 @@ describe('fetchTokenList', () => { it('returns a non-empty tokens array', async () => { const result = await fetchTokenList('default') - expect(Array.isArray(result.tokens)).toBe(true) expect(result.tokens.length).toBeGreaterThan(0) + expect(mockFetch).not.toHaveBeenCalled() }) it('every EVM token conforms to tokenSchema', async () => { @@ -175,6 +175,7 @@ describe('fetchTokenList', () => { for (const token of evmTokens) { expect(() => tokenSchema.parse(token)).not.toThrow() } + expect(mockFetch).not.toHaveBeenCalled() }) }) })