UNPKG

13.2 kBJavaScriptView Raw
1var $schema = "http://json-schema.org/draft-07/schema#";
2var $id = "https://uniswap.org/tokenlist.schema.json";
3var title = "Uniswap Token List";
4var description = "Schema for lists of tokens compatible with the Uniswap Interface";
5var definitions = {
6 Version: {
7 type: "object",
8 description: "The version of the list, used in change detection",
9 examples: [
10 {
11 major: 1,
12 minor: 0,
13 patch: 0
14 }
15 ],
16 additionalProperties: false,
17 properties: {
18 major: {
19 type: "integer",
20 description: "The major version of the list. Must be incremented when tokens are removed from the list or token addresses are changed.",
21 minimum: 0,
22 examples: [
23 1,
24 2
25 ]
26 },
27 minor: {
28 type: "integer",
29 description: "The minor version of the list. Must be incremented when tokens are added to the list.",
30 minimum: 0,
31 examples: [
32 0,
33 1
34 ]
35 },
36 patch: {
37 type: "integer",
38 description: "The patch version of the list. Must be incremented for any changes to the list.",
39 minimum: 0,
40 examples: [
41 0,
42 1
43 ]
44 }
45 },
46 required: [
47 "major",
48 "minor",
49 "patch"
50 ]
51 },
52 TagIdentifier: {
53 type: "string",
54 description: "The unique identifier of a tag",
55 minLength: 1,
56 maxLength: 10,
57 pattern: "^[\\w]+$",
58 examples: [
59 "compound",
60 "stablecoin"
61 ]
62 },
63 ExtensionIdentifier: {
64 type: "string",
65 description: "The name of a token extension property",
66 minLength: 1,
67 maxLength: 40,
68 pattern: "^[\\w]+$",
69 examples: [
70 "color",
71 "is_fee_on_transfer",
72 "aliases"
73 ]
74 },
75 ExtensionMap: {
76 type: "object",
77 description: "An object containing any arbitrary or vendor-specific token metadata",
78 maxProperties: 10,
79 propertyNames: {
80 $ref: "#/definitions/ExtensionIdentifier"
81 },
82 additionalProperties: {
83 $ref: "#/definitions/ExtensionValue"
84 },
85 examples: [
86 {
87 color: "#000000",
88 is_verified_by_me: true
89 },
90 {
91 "x-bridged-addresses-by-chain": {
92 "1": {
93 bridgeAddress: "0x4200000000000000000000000000000000000010",
94 tokenAddress: "0x4200000000000000000000000000000000000010"
95 }
96 }
97 }
98 ]
99 },
100 ExtensionPrimitiveValue: {
101 anyOf: [
102 {
103 type: "string",
104 minLength: 1,
105 maxLength: 42,
106 examples: [
107 "#00000"
108 ]
109 },
110 {
111 type: "boolean",
112 examples: [
113 true
114 ]
115 },
116 {
117 type: "number",
118 examples: [
119 15
120 ]
121 },
122 {
123 type: "null"
124 }
125 ]
126 },
127 ExtensionValue: {
128 anyOf: [
129 {
130 $ref: "#/definitions/ExtensionPrimitiveValue"
131 },
132 {
133 type: "object",
134 maxProperties: 10,
135 propertyNames: {
136 $ref: "#/definitions/ExtensionIdentifier"
137 },
138 additionalProperties: {
139 $ref: "#/definitions/ExtensionValueInner0"
140 }
141 }
142 ]
143 },
144 ExtensionValueInner0: {
145 anyOf: [
146 {
147 $ref: "#/definitions/ExtensionPrimitiveValue"
148 },
149 {
150 type: "object",
151 maxProperties: 10,
152 propertyNames: {
153 $ref: "#/definitions/ExtensionIdentifier"
154 },
155 additionalProperties: {
156 $ref: "#/definitions/ExtensionValueInner1"
157 }
158 }
159 ]
160 },
161 ExtensionValueInner1: {
162 anyOf: [
163 {
164 $ref: "#/definitions/ExtensionPrimitiveValue"
165 }
166 ]
167 },
168 TagDefinition: {
169 type: "object",
170 description: "Definition of a tag that can be associated with a token via its identifier",
171 additionalProperties: false,
172 properties: {
173 name: {
174 type: "string",
175 description: "The name of the tag",
176 pattern: "^[ \\w]+$",
177 minLength: 1,
178 maxLength: 20
179 },
180 description: {
181 type: "string",
182 description: "A user-friendly description of the tag",
183 pattern: "^[ \\w\\.,:]+$",
184 minLength: 1,
185 maxLength: 200
186 }
187 },
188 required: [
189 "name",
190 "description"
191 ],
192 examples: [
193 {
194 name: "Stablecoin",
195 description: "A token with value pegged to another asset"
196 }
197 ]
198 },
199 TokenInfo: {
200 type: "object",
201 description: "Metadata for a single token in a token list",
202 additionalProperties: false,
203 properties: {
204 chainId: {
205 type: "integer",
206 description: "The chain ID of the Ethereum network where this token is deployed",
207 minimum: 1,
208 examples: [
209 1,
210 42
211 ]
212 },
213 address: {
214 type: "string",
215 description: "The checksummed address of the token on the specified chain ID",
216 pattern: "^0x[a-fA-F0-9]{40}$",
217 examples: [
218 "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
219 ]
220 },
221 decimals: {
222 type: "integer",
223 description: "The number of decimals for the token balance",
224 minimum: 0,
225 maximum: 255,
226 examples: [
227 18
228 ]
229 },
230 name: {
231 type: "string",
232 description: "The name of the token",
233 minLength: 1,
234 maxLength: 40,
235 pattern: "^[ \\w.'+\\-%/À-ÖØ-öø-ÿ:&\\[\\]\\(\\)]+$",
236 examples: [
237 "USD Coin"
238 ]
239 },
240 symbol: {
241 type: "string",
242 description: "The symbol for the token; must be alphanumeric",
243 pattern: "^[a-zA-Z0-9+\\-%/$.]+$",
244 minLength: 1,
245 maxLength: 20,
246 examples: [
247 "USDC"
248 ]
249 },
250 logoURI: {
251 type: "string",
252 description: "A URI to the token logo asset; if not set, interface will attempt to find a logo based on the token address; suggest SVG or PNG of size 64x64",
253 format: "uri",
254 examples: [
255 "ipfs://QmXfzKRvjZz3u5JRgC4v5mGVbm9ahrUiB4DgzHBsnWbTMM"
256 ]
257 },
258 tags: {
259 type: "array",
260 description: "An array of tag identifiers associated with the token; tags are defined at the list level",
261 items: {
262 $ref: "#/definitions/TagIdentifier"
263 },
264 maxItems: 10,
265 examples: [
266 "stablecoin",
267 "compound"
268 ]
269 },
270 extensions: {
271 $ref: "#/definitions/ExtensionMap"
272 }
273 },
274 required: [
275 "chainId",
276 "address",
277 "decimals",
278 "name",
279 "symbol"
280 ]
281 }
282};
283var type = "object";
284var additionalProperties = false;
285var properties = {
286 name: {
287 type: "string",
288 description: "The name of the token list",
289 minLength: 1,
290 maxLength: 30,
291 pattern: "^[\\w ]+$",
292 examples: [
293 "My Token List"
294 ]
295 },
296 timestamp: {
297 type: "string",
298 format: "date-time",
299 description: "The timestamp of this list version; i.e. when this immutable version of the list was created"
300 },
301 version: {
302 $ref: "#/definitions/Version"
303 },
304 tokens: {
305 type: "array",
306 description: "The list of tokens included in the list",
307 items: {
308 $ref: "#/definitions/TokenInfo"
309 },
310 minItems: 1,
311 maxItems: 10000
312 },
313 keywords: {
314 type: "array",
315 description: "Keywords associated with the contents of the list; may be used in list discoverability",
316 items: {
317 type: "string",
318 description: "A keyword to describe the contents of the list",
319 minLength: 1,
320 maxLength: 20,
321 pattern: "^[\\w ]+$",
322 examples: [
323 "compound",
324 "lending",
325 "personal tokens"
326 ]
327 },
328 maxItems: 20,
329 uniqueItems: true
330 },
331 tags: {
332 type: "object",
333 description: "A mapping of tag identifiers to their name and description",
334 propertyNames: {
335 $ref: "#/definitions/TagIdentifier"
336 },
337 additionalProperties: {
338 $ref: "#/definitions/TagDefinition"
339 },
340 maxProperties: 20,
341 examples: [
342 {
343 stablecoin: {
344 name: "Stablecoin",
345 description: "A token with value pegged to another asset"
346 }
347 }
348 ]
349 },
350 logoURI: {
351 type: "string",
352 description: "A URI for the logo of the token list; prefer SVG or PNG of size 256x256",
353 format: "uri",
354 examples: [
355 "ipfs://QmXfzKRvjZz3u5JRgC4v5mGVbm9ahrUiB4DgzHBsnWbTMM"
356 ]
357 }
358};
359var required = [
360 "name",
361 "timestamp",
362 "version",
363 "tokens"
364];
365var tokenlist_schema = {
366 $schema: $schema,
367 $id: $id,
368 title: title,
369 description: description,
370 definitions: definitions,
371 type: type,
372 additionalProperties: additionalProperties,
373 properties: properties,
374 required: required
375};
376
377/**
378 * Comparator function that allows sorting version from lowest to highest
379 * @param versionA version A to compare
380 * @param versionB version B to compare
381 * @returns -1 if versionA comes before versionB, 0 if versionA is equal to version B, and 1 if version A comes after version B
382 */
383function versionComparator(versionA, versionB) {
384 if (versionA.major < versionB.major) {
385 return -1;
386 } else if (versionA.major > versionB.major) {
387 return 1;
388 } else if (versionA.minor < versionB.minor) {
389 return -1;
390 } else if (versionA.minor > versionB.minor) {
391 return 1;
392 } else if (versionA.patch < versionB.patch) {
393 return -1;
394 } else if (versionA.patch > versionB.patch) {
395 return 1;
396 } else {
397 return 0;
398 }
399}
400
401/**
402 * Returns true if versionB is an update over versionA
403 */
404
405function isVersionUpdate(base, update) {
406 return versionComparator(base, update) < 0;
407}
408
409var VersionUpgrade;
410
411(function (VersionUpgrade) {
412 VersionUpgrade[VersionUpgrade["NONE"] = 0] = "NONE";
413 VersionUpgrade[VersionUpgrade["PATCH"] = 1] = "PATCH";
414 VersionUpgrade[VersionUpgrade["MINOR"] = 2] = "MINOR";
415 VersionUpgrade[VersionUpgrade["MAJOR"] = 3] = "MAJOR";
416})(VersionUpgrade || (VersionUpgrade = {}));
417/**
418 * Return the upgrade type from the base version to the update version.
419 * Note that downgrades and equivalent versions are both treated as `NONE`.
420 * @param base base list
421 * @param update update to the list
422 */
423
424
425function getVersionUpgrade(base, update) {
426 if (update.major > base.major) {
427 return VersionUpgrade.MAJOR;
428 }
429
430 if (update.major < base.major) {
431 return VersionUpgrade.NONE;
432 }
433
434 if (update.minor > base.minor) {
435 return VersionUpgrade.MINOR;
436 }
437
438 if (update.minor < base.minor) {
439 return VersionUpgrade.NONE;
440 }
441
442 return update.patch > base.patch ? VersionUpgrade.PATCH : VersionUpgrade.NONE;
443}
444
445/**
446 * compares two token info key values
447 * this subset of full deep equal functionality does not work on objects or object arrays
448 * @param a comparison item a
449 * @param b comparison item b
450 */
451function compareTokenInfoProperty(a, b) {
452 if (a === b) return true;
453 if (typeof a !== typeof b) return false;
454
455 if (Array.isArray(a) && Array.isArray(b)) {
456 return a.every(function (el, i) {
457 return b[i] === el;
458 });
459 }
460
461 return false;
462}
463/**
464 * Computes the diff of a token list where the first argument is the base and the second argument is the updated list.
465 * @param base base list
466 * @param update updated list
467 */
468
469
470function diffTokenLists(base, update) {
471 var indexedBase = base.reduce(function (memo, tokenInfo) {
472 if (!memo[tokenInfo.chainId]) memo[tokenInfo.chainId] = {};
473 memo[tokenInfo.chainId][tokenInfo.address] = tokenInfo;
474 return memo;
475 }, {});
476 var newListUpdates = update.reduce(function (memo, tokenInfo) {
477 var _indexedBase$tokenInf;
478
479 var baseToken = (_indexedBase$tokenInf = indexedBase[tokenInfo.chainId]) == null ? void 0 : _indexedBase$tokenInf[tokenInfo.address];
480
481 if (!baseToken) {
482 memo.added.push(tokenInfo);
483 } else {
484 var changes = Object.keys(tokenInfo).filter(function (s) {
485 return s !== 'address' && s !== 'chainId';
486 }).filter(function (s) {
487 return !compareTokenInfoProperty(tokenInfo[s], baseToken[s]);
488 });
489
490 if (changes.length > 0) {
491 if (!memo.changed[tokenInfo.chainId]) {
492 memo.changed[tokenInfo.chainId] = {};
493 }
494
495 memo.changed[tokenInfo.chainId][tokenInfo.address] = changes;
496 }
497 }
498
499 if (!memo.index[tokenInfo.chainId]) {
500 var _memo$index$tokenInfo;
501
502 memo.index[tokenInfo.chainId] = (_memo$index$tokenInfo = {}, _memo$index$tokenInfo[tokenInfo.address] = true, _memo$index$tokenInfo);
503 } else {
504 memo.index[tokenInfo.chainId][tokenInfo.address] = true;
505 }
506
507 return memo;
508 }, {
509 added: [],
510 changed: {},
511 index: {}
512 });
513 var removed = base.reduce(function (list, curr) {
514 if (!newListUpdates.index[curr.chainId] || !newListUpdates.index[curr.chainId][curr.address]) {
515 list.push(curr);
516 }
517
518 return list;
519 }, []);
520 return {
521 added: newListUpdates.added,
522 changed: newListUpdates.changed,
523 removed: removed
524 };
525}
526
527/**
528 * Returns the minimum version bump for the given list
529 * @param baseList the base list of tokens
530 * @param updatedList the updated list of tokens
531 */
532
533function minVersionBump(baseList, updatedList) {
534 var diff = diffTokenLists(baseList, updatedList);
535 if (diff.removed.length > 0) return VersionUpgrade.MAJOR;
536 if (diff.added.length > 0) return VersionUpgrade.MINOR;
537 if (Object.keys(diff.changed).length > 0) return VersionUpgrade.PATCH;
538 return VersionUpgrade.NONE;
539}
540
541/**
542 * Returns the next version of the list given a base version and the upgrade type
543 * @param base current version
544 * @param bump the upgrade type
545 */
546
547function nextVersion(base, bump) {
548 switch (bump) {
549 case VersionUpgrade.NONE:
550 return base;
551
552 case VersionUpgrade.MAJOR:
553 return {
554 major: base.major + 1,
555 minor: 0,
556 patch: 0
557 };
558
559 case VersionUpgrade.MINOR:
560 return {
561 major: base.major,
562 minor: base.minor + 1,
563 patch: 0
564 };
565
566 case VersionUpgrade.PATCH:
567 return {
568 major: base.major,
569 minor: base.minor,
570 patch: base.patch + 1
571 };
572 }
573}
574
575export { VersionUpgrade, diffTokenLists, getVersionUpgrade, isVersionUpdate, minVersionBump, nextVersion, tokenlist_schema as schema, versionComparator };
576//# sourceMappingURL=token-lists.esm.js.map