1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var $schema = "http://json-schema.org/draft-07/schema#";
|
6 | var $id = "https://uniswap.org/tokenlist.schema.json";
|
7 | var title = "Uniswap Token List";
|
8 | var description = "Schema for lists of tokens compatible with the Uniswap Interface";
|
9 | var 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 | };
|
287 | var type = "object";
|
288 | var additionalProperties = false;
|
289 | var 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 | };
|
363 | var required = [
|
364 | "name",
|
365 | "timestamp",
|
366 | "version",
|
367 | "tokens"
|
368 | ];
|
369 | var 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 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | function 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 |
|
407 |
|
408 |
|
409 | function 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 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 | function 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 |
|
449 |
|
450 |
|
451 |
|
452 |
|
453 | function 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 |
|
467 |
|
468 |
|
469 |
|
470 |
|
471 |
|
472 | function 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 |
|
531 |
|
532 |
|
533 |
|
534 |
|
535 | function 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 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 | function 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 |
|
577 | exports.diffTokenLists = diffTokenLists;
|
578 | exports.getVersionUpgrade = getVersionUpgrade;
|
579 | exports.isVersionUpdate = isVersionUpdate;
|
580 | exports.minVersionBump = minVersionBump;
|
581 | exports.nextVersion = nextVersion;
|
582 | exports.schema = tokenlist_schema;
|
583 | exports.versionComparator = versionComparator;
|
584 |
|