UNPKG

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