Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
07b280c
add mycrypto
callil Nov 30, 2020
cf761cc
Add Set Protocol and Kyber Network
callil Dec 4, 2020
6624f54
Merge branch 'master' of https://github.com/Uniswap/tokenlists-org
callil Dec 4, 2020
2f8b70c
fix token list json
callil Dec 4, 2020
c178fe1
add gemini
ianlapham Jan 21, 2021
13f7346
Merge pull request #753 from Uniswap/gemini
ianlapham Jan 21, 2021
c08e545
add ba list
ianlapham Feb 25, 2021
0e9acae
fix mobile styles
ianlapham Feb 25, 2021
ccf7d99
update ba list endpoint
ianlapham Feb 25, 2021
62d6c73
feat: add yearn token list
banteg Apr 23, 2021
27f379c
alphabetical
haydenadams Apr 23, 2021
7d3de14
Merge pull request #931 from banteg/feat/add-yearn
callil Apr 23, 2021
0679700
add optimism
ianlapham Jul 21, 2021
7cfd1ae
Merge pull request #1110 from Uniswap/add-optimism
ianlapham Jul 21, 2021
1206c97
feat: add TickerDao token list
briansoule Dec 7, 2021
cdbf372
Update token-lists.json
briansoule Mar 29, 2022
ec51c58
Merge pull request #1241 from briansoule/patch-1
JFrankfurt Apr 15, 2022
df2d45f
Adding some multi-chain support for list view
Jun 3, 2022
68aae0a
Adding link to multi-chain convert tool
Jun 9, 2022
0d458fc
Changing column ordering on table
Jun 9, 2022
0e6ec1f
Remove extra space
Jun 9, 2022
e540a98
Update list.js
akarys92 Jun 9, 2022
1a8cd95
Making some adjustments from feedback on PR 1439
Jun 16, 2022
ac9186b
Merge branch 'ak/multi-chain-support' of https://github.com/akarys92/…
Jun 16, 2022
09074fe
Reducing toCheckSum calls
Jun 17, 2022
83dbb65
Merge pull request #1439 from akarys92/ak/multi-chain-support
JFrankfurt Jun 21, 2022
0d5290f
feat: replaced all lists w/ uni lists
cartcrom Jan 25, 2023
a88ac5b
Merge pull request #1902 from cartcrom/update_listed_lists
cartcrom Jan 25, 2023
137fc83
Revert "feat: replaced all lists w/ uni lists"
cartcrom Jan 25, 2023
6f27c0a
Merge pull request #1903 from Uniswap/revert-1902-update_listed_lists
cartcrom Jan 25, 2023
72cccd7
changing / shortening description
wanxinwanxin Jun 28, 2023
7e304a4
hooks json
Jun 28, 2023
20a4cd6
Merge pull request #2291 from mz-/updated_description
mz- Jun 28, 2023
e8f3cf0
Revert "changing / shortening description"
Jun 28, 2023
bba3412
Merge pull request #2292 from Uniswap/revert
mz- Jun 28, 2023
03d281a
Merge pull request #2293 from mz-/hooks-json
mz- Jun 28, 2023
bb5e24d
Revert "hooks json"
Jun 28, 2023
fbdc662
Merge pull request #2294 from Uniswap/revert-hooks
mz- Jun 28, 2023
e5720e1
Update default token list url
andysmith415 Aug 28, 2024
90fce7d
Merge pull request #2813 from Uniswap/as/update-default-tokenlist
andysmith415 Aug 28, 2024
b04fef5
Support solana addresses (#3182)
matteenm Oct 24, 2025
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
2 changes: 2 additions & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
22

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
"name": "token-lists",
"version": "0.1.0",
"private": true,
"engines": {
"node": "22.x"
},
"dependencies": {
"@types/node": "^14.6.1",
"@types/react": "^16.9.48",
"@types/react-dom": "^16.9.8",
"bs58": "^6.0.0",
"copy-to-clipboard": "^3.3.1",
"ethereumjs-util": "^7.0.3",
"moment": "^2.27.0",
Expand All @@ -22,8 +26,8 @@
"typescript": "^4.0.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"start": "NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
"build": "NODE_OPTIONS=--openssl-legacy-provider react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Expand Down
9 changes: 6 additions & 3 deletions src/components/card.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import styled from 'styled-components'
const StyledCard = styled(Link)`
border-radius: 8px;
padding: 1.5rem;
height: 264px;
max-width: 172px;
display: flex;
justify-content: space-between;
Expand All @@ -22,7 +21,7 @@ const StyledCard = styled(Link)`
max-width: initial;
}
@media screen and (max-width: 414px) {
width: 100%;
width: 320px;
box-sizing: border-box;
}
:hover {
Expand Down Expand Up @@ -52,6 +51,10 @@ const TokensListed = styled.span`
line-height: 150%;
`

const NameText = styled.h3`
word-wrap: break-word;
`

function getLogoURL(logoURI) {
if (logoURI?.startsWith('ipfs://')) {
return `https://ipfs.io/ipfs/${logoURI.split('//')[1]}`
Expand All @@ -77,7 +80,7 @@ export default function Card({ id, list, name }) {
}}
/>
<section>
<h3>{actualName}</h3>
<NameText>{actualName}</NameText>
<TokensListed>
{list?.tokens?.length > 0 ? `${list.tokens.length} tokens` : list === null ? 'Error' : 'Loading...'}
</TokensListed>
Expand Down
5 changes: 4 additions & 1 deletion src/components/hero.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function Header() {
Project
</span>

<p className="title">A new Ethereum token list standard.</p>
<p className="title">An Ethereum token list standard.</p>

<p style={{ fontSize: '20px', lineHeight: '150%' }} className="description" id="why-lists">
Token Lists is a community-led initiative to improve discoverability, reputation and trust in ERC20 token lists
Expand All @@ -93,6 +93,9 @@ export default function Header() {
>
{'->'} Make your own
</HoverLink>
<HoverLink target="_blank" rel="noopener noreferrer" href="https://github.com/Uniswap/token-list-bridge-utils">
{'->'} Convert to multi-chain list
</HoverLink>
<HoverLink target="_blank" rel="noopener noreferrer" href="http://community.tokenlists.org/">
{'->'} Community
</HoverLink>
Expand Down
75 changes: 66 additions & 9 deletions src/components/list-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,52 @@ import React, { useState, memo } from 'react'
import styled from 'styled-components'
import Search from './search'
import CopyHelper from './copy'
import { lookUpchain, lookupScanner, isSolanaChain } from '../utils/getChainId'

import { toChecksumAddress } from 'ethereumjs-util'
import bs58 from 'bs58'
import FilterResults from 'react-filter-search'

function isValidSolanaAddress(address) {
try {
const decoded = bs58.decode(address)
return decoded.length === 32
} catch {
return false
}
}

// For Solana: validates base58 encoding and returns as-is
// For EVM chains (default): applies checksum validation
function safeToChecksumAddress(address, chainId) {
if (!address || typeof address !== 'string') {
return address
}

// Handle Solana addresses
if (isSolanaChain(chainId)) {
if (isValidSolanaAddress(address)) {
return address // Solana addresses are case-sensitive and don't need checksum conversion
} else {
console.warn('Invalid Solana address:', address)
return address
}
}

// Handle EVM addresses
try {
return toChecksumAddress(address)
} catch (e) {
console.warn('Failed to convert address to checksum:', address, e)
return address
}
}

const TokenItem = styled.section`
display: grid;
max-width: 960px;
grid-gap: 1rem;
grid-template-columns: 1fr 128px 96px 148px;
grid-template-columns: 1fr 100px 120px 96px 148px;
margin-bottom: 1rem;
a {
color: #131313;
Expand Down Expand Up @@ -73,7 +110,21 @@ const TokenAddress = styled.span`
align-items: center;
`

const Chain = styled.span`
display: grid;
grid-template-columns: auto 16px;
grid-gap: 0.5rem;
height: fit-content;
align-items: center;
@media screen and (max-width: 960px) {
display: none;
}
`

export const ListItem = memo(function ListItem({ token }) {
const scanner = lookupScanner(token.chainId);
const tokenAddress = safeToChecksumAddress(token.address, token.chainId);
const scannerUrl = scanner === "" ? "" : scanner + tokenAddress;
return (
<TokenItem>
<TokenInfo>
Expand All @@ -82,8 +133,9 @@ export const ListItem = memo(function ListItem({ token }) {
alt={`${token.name} token icon`}
src={
!token.logoURI
? `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${toChecksumAddress(
token.address
? `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${safeToChecksumAddress(
token.address,
token.chainId
)}/logo.png`
: token.logoURI.startsWith('ipfs')
? `https://ipfs.io/ipfs/${token.logoURI.split('//')[1]}`
Expand All @@ -96,11 +148,12 @@ export const ListItem = memo(function ListItem({ token }) {
/>

<span className="hide-small">
<a style={{ textAlign: 'right' }} href={`https://etherscan.io/address/${toChecksumAddress(token.address)}`}>
<a style={{ textAlign: 'right' }} href={scannerUrl}>
{token.name}
</a>
</span>
</TokenInfo>
<Chain>{lookUpchain(token.chainId)}</Chain>
<span>{token.symbol}</span>
<TokenTagWrapper className="hide-small">
{token?.tags?.length > 0 && (
Expand All @@ -111,8 +164,8 @@ export const ListItem = memo(function ListItem({ token }) {
)}
</TokenTagWrapper>
<TokenAddress>
<a style={{ textAlign: 'right' }} href={`https://etherscan.io/address/${toChecksumAddress(token.address)}`}>
{`${toChecksumAddress(token.address)?.slice(0, 6)}...${toChecksumAddress(token.address)?.slice(38, 42)}`}
<a style={{ textAlign: 'right' }} href={scannerUrl}>
{`${tokenAddress?.slice(0, 6)}...${tokenAddress?.slice(38, 42)}`}
</a>
<CopyHelper toCopy={token.address} />
</TokenAddress>
Expand Down Expand Up @@ -148,7 +201,7 @@ const ListTitle = styled.div`
display: grid;
max-width: 960px;
grid-gap: 1rem;
grid-template-columns: 1fr 128px 96px 148px;
grid-template-columns: 1fr 100px 120px 96px 148px;
margin-bottom: 1rem;
@media screen and (max-width: 414px) {
display: none;
Expand All @@ -166,6 +219,10 @@ const ListHeader = styled.div`

export default function Tokens({ tokens }) {
const [value, setValue] = useState('')
const sortedTokens = tokens.sort((a,b) =>{
return a.symbol > b.symbol ? 1 :
a.symbol < b.symbol ? -1 : 0;
})

function handleChange(e) {
const { value } = e.target
Expand All @@ -182,17 +239,17 @@ export default function Tokens({ tokens }) {
<TokenWrapper>
<ListTitle>
<p className="hide-small">Name</p>
<p className="hide-small">Chain</p>
<p className="hide-small">Symbol</p>
<p className="hide-small">Tags</p>

<p className="hide-small" style={{ textAlign: 'right' }}>
Address
</p>
</ListTitle>

<FilterResults
value={value}
data={tokens}
data={sortedTokens}
renderResults={(results) =>
results.length === 0 ? 'None found!' : results.map((data, i) => <ListItem key={i} token={data} />)
}
Expand Down
34 changes: 33 additions & 1 deletion src/token-lists.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
"name": "Agora dataFi Tokens",
"homepage": ""
},
"https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json": {
"name": "Blockchain Association SEC Non Compliant List",
"homepage": ""
},
"defi.cmc.eth": {
"name": "CMC DeFi",
"homepage": ""
Expand Down Expand Up @@ -55,22 +59,42 @@
"name": "Furucombo",
"homepage": ""
},
"https://www.gemini.com/uniswap/manifest.json": {
"name": "Gemini Token List",
"homepage": "https://www.gemini.com/"
},
"t2crtokens.eth": {
"name": "Kleros T2CR",
"homepage": ""
},
"https://api.kyber.network/tokenlist": {
"name": "Kyber",
"homepage": ""
},
"https://messari.io/tokenlist/messari-verified": {
"name": "Messari Verified",
"homepage": ""
},
"https://uniswap.mycryptoapi.com/": {
"name": "MyCrypto",
"homepage": ""
},
"https://raw.githubusercontent.com/opynfinance/opyn-tokenlist/master/opyn-v1.tokenlist.json": {
"name": "Opyn Token List",
"homepage": ""
},
"https://static.optimism.io/optimism.tokenlist.json": {
"name": "Optimism",
"homepage": "https://optimism.io/"
},
"https://app.tryroll.com/tokens.json": {
"name": "Roll Social Money",
"homepage": ""
},
"https://raw.githubusercontent.com/SetProtocol/uniswap-tokenlist/main/set.tokenlist.json": {
"name": "Set Protocol",
"homepage": ""
},
"synths.snx.eth": {
"name": "Synthetix",
"homepage": ""
Expand All @@ -79,7 +103,11 @@
"name": "Testnet Tokens",
"homepage": ""
},
"https://gateway.ipfs.io/ipns/tokens.uniswap.org": {
"list.tkn.eth": {
"name": "TokenDao",
"homepage": "https://tkn.eth.limo"
},
"https://ipfs.io/ipns/tokens.uniswap.org": {
"name": "Uniswap Default List",
"homepage": ""
},
Expand All @@ -95,6 +123,10 @@
"name": "Wrapped Tokens",
"homepage": ""
},
"https://yearn.science/static/tokenlist.json": {
"name": "Yearn",
"homepage": "https://yearn.finance/"
},
"https://zapper.fi/api/token-list": {
"name": "Zapper Token List",
"homepage": ""
Expand Down
Loading