1 | # @uniswap/token-lists (beta)
|
2 |
|
3 | [![Tests](https://github.com/Uniswap/token-lists/workflows/Tests/badge.svg)](https://github.com/Uniswap/token-lists/actions?query=workflow%3ATests)
|
4 | [![npm](https://img.shields.io/npm/v/@uniswap/token-lists)](https://unpkg.com/@uniswap/token-lists@latest/)
|
5 |
|
6 | This package includes a JSON schema for token lists, and TypeScript utilities for working with token lists.
|
7 |
|
8 | The JSON schema represents the technical specification for a token list which can be used in a dApp interface, such as the Uniswap Interface.
|
9 |
|
10 | ## What are token lists?
|
11 |
|
12 | Uniswap Token Lists is a specification for lists of token metadata (e.g. address, decimals, ...) that can be used by any dApp interfaces that needs one or more lists of tokens.
|
13 |
|
14 | Anyone can create and maintain a token list, as long as they follow the specification.
|
15 |
|
16 | Specifically an instance of a token list is a [JSON](https://www.json.org/json-en.html) blob that contains a list of
|
17 | [ERC20](https://github.com/ethereum/eips/issues/20) token metadata for use in dApp user interfaces.
|
18 | Token list JSON must validate against the [JSON schema](https://json-schema.org/) in order to be used in the Uniswap Interface.
|
19 | Tokens on token lists, and token lists themselves, are tagged so that users can easily find tokens.
|
20 |
|
21 | ## JSON Schema $id
|
22 |
|
23 | The JSON schema ID is [https://uniswap.org/tokenlist.schema.json](https://uniswap.org/tokenlist.schema.json)
|
24 |
|
25 | ## Validating token lists
|
26 |
|
27 | This package does not include code for token list validation. You can easily do this by including a library such as
|
28 | [ajv](https://ajv.js.org/) to perform the validation against the JSON schema. The schema is exported from the package
|
29 | for ease of use.
|
30 |
|
31 | ```typescript
|
32 |
|
33 | import { schema } from '@uniswap/token-lists'
|
34 | import Ajv from 'ajv'
|
35 | import addFormats from 'ajv-formats'
|
36 | import fetch from 'node-fetch'
|
37 |
|
38 | const ARBITRUM_LIST = 'https://bridge.arbitrum.io/token-list-42161.json'
|
39 |
|
40 | async function validate() {
|
41 | const ajv = new Ajv({ allErrors: true, verbose: true })
|
42 | addFormats(ajv)
|
43 | const validator = ajv.compile(schema);
|
44 | const response = await fetch(ARBITRUM_LIST)
|
45 | const data = await response.json()
|
46 | const valid = validator(data)
|
47 | if (valid) {
|
48 | return valid
|
49 | }
|
50 | if (validator.errors) {
|
51 | throw validator.errors.map(error => {
|
52 | delete error.data
|
53 | return error
|
54 | })
|
55 | }
|
56 | }
|
57 |
|
58 | validate()
|
59 | .then(console.log("Valid List."))
|
60 | .catch(console.error)
|
61 |
|
62 | ```
|
63 |
|
64 | ## Authoring token lists
|
65 |
|
66 | ### Manual
|
67 |
|
68 | The best way to manually author token lists is to use an editor that supports JSON schema validation. Most popular
|
69 | code editors do, such as [IntelliJ](https://www.jetbrains.com/help/idea/json.html#ws_json_schema_add_custom) or
|
70 | [VSCode](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings). Other editors
|
71 | can be found [here](https://json-schema.org/implementations.html#editors).
|
72 |
|
73 | The schema is registered in the [SchemaStore](https://github.com/SchemaStore/schemastore), and any file that matches
|
74 | the pattern `*.tokenlist.json` should
|
75 | [automatically utilize](https://www.jetbrains.com/help/idea/json.html#ws_json_using_schemas)
|
76 | the JSON schema for the [supported text editors](https://www.schemastore.org/json/#editors).
|
77 |
|
78 | In order for your token list to be able to be used, it must pass all JSON schema validation.
|
79 |
|
80 | ### Automated
|
81 |
|
82 | If you want to automate token listing, e.g. by pulling from a smart contract, or other sources, you can use this
|
83 | npm package to take advantage of the JSON schema for validation and the TypeScript types.
|
84 | Otherwise, you are simply working with JSON. All the usual tools apply, e.g.:
|
85 |
|
86 | ```typescript
|
87 | import { TokenList, schema } from '@uniswap/token-lists'
|
88 |
|
89 | // generate your token list however you like.
|
90 | const myList: TokenList = generateMyTokenList();
|
91 |
|
92 | // use a tool like `ajv` to validate your generated token list
|
93 | validateMyTokenList(myList, schema);
|
94 |
|
95 | // print the resulting JSON to stdout
|
96 | process.stdout.write(JSON.stringify(myList));
|
97 | ```
|
98 |
|
99 | ## Semantic versioning
|
100 |
|
101 | Lists include a `version` field, which follows [semantic versioning](https://semver.org/).
|
102 |
|
103 | List versions must follow the rules:
|
104 |
|
105 | - Increment major version when tokens are removed
|
106 | - Increment minor version when tokens are added
|
107 | - Increment patch version when tokens already on the list have minor details changed (name, symbol, logo URL, decimals)
|
108 |
|
109 | Changing a token address or chain ID is considered both a remove and an add, and should be a major version update.
|
110 |
|
111 | Note that list versioning is used to improve the user experience, but not for security, i.e. list versions are not meant
|
112 | to provide protection against malicious updates to a token list; i.e. the list semver is used as a lossy compression
|
113 | of the diff of list updates. List updates may still be diffed in the client dApp.
|
114 |
|
115 | ## Deploying your list
|
116 |
|
117 | Once you have authored the list, you can make it available at any URI. Prefer pinning your list to IPFS
|
118 | (e.g. via [pinata.cloud](https://pinata.cloud)) and referencing the list by an ENS name that resolves to the
|
119 | [contenthash](https://eips.ethereum.org/EIPS/eip-1577).
|
120 |
|
121 | If hosted on HTTPS, make sure the endpoint is configured to send an access-control-allow-origin header to avoid CORS errors.
|
122 |
|
123 | ### Linking an ENS name to the list
|
124 |
|
125 | An ENS name can be assigned to an IPFS hash via the [contenthash](https://eips.ethereum.org/EIPS/eip-1577) text record.
|
126 | This is the preferred way of referencing your list.
|
127 |
|
128 | ## Examples
|
129 |
|
130 | You can find a simple example of a token list in [test/schema/example.tokenlist.json](test/schema/example.tokenlist.json).
|
131 |
|
132 | A snapshot of the Uniswap default list encoded as a token list is found in [test/schema/bigexample.tokenlist.json](test/schema/bigexample.tokenlist.json).
|