├── .gitignore
├── .travis.yml
├── LICENSE
├── Procfile
├── README.md
├── config
├── custom-environment-variables.json
├── default.json
├── development.example.json
└── test.example.json
├── package-lock.json
├── package.json
├── src
├── App.ts
├── Server.ts
├── common
│ ├── Config.ts
│ ├── Utils.ts
│ └── tokens
│ │ └── contracts.ts
├── controllers
│ ├── AppCheck.ts
│ ├── Collectibles
│ │ └── CollectiblesController.ts
│ ├── DAppsController.ts
│ ├── Interfaces
│ │ ├── ITokenInfo.ts
│ │ ├── ITokenPriceController.ts
│ │ ├── Servers.ts
│ │ └── Ticker.ts
│ ├── RedirectController.ts
│ ├── TickerController.ts
│ ├── TokenInfo.ts
│ └── TokenPriceController.ts
├── models
│ ├── Currency
│ │ ├── CurrencyCoefficientModel.ts
│ │ └── TickerModel.ts
│ ├── DAppCategory.ts
│ ├── DAppModel.ts
│ └── Database.ts
└── routes
│ └── ApiRoutes.ts
├── test
└── App.test.ts
├── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore project IDE files
2 | .idea
3 | .vscode
4 |
5 | # Ignore node_modules
6 | node_modules
7 |
8 | # Ignore Mac OS X files
9 | .DS_Store
10 |
11 | # Ignore local notes folder
12 | notes
13 | apidoc
14 |
15 | # Ignore local logs
16 | *.log
17 |
18 | dist
19 |
20 | docker/data/
21 |
22 | # Ignore config enviroment
23 | config/test.json
24 | config/development.json
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "9.5.0"
4 |
5 | cache:
6 | directories:
7 | - "node_modules"
8 |
9 | before_script:
10 | - npm run docs
11 | - npm run build
12 |
13 | after_success:
14 | - bash <(curl -s https://copilot.blackducksoftware.com/ci/travis/scripts/upload)
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 | {one line to give the program's name and a brief idea of what it does.}
635 | Copyright (C) {year} {name of author}
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | {project} Copyright (C) {year} {fullname}
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: npm run docs && npm run build && node dist/Server
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :cloud: Trust Ray :cloud:
2 |
3 | [](https://greenkeeper.io/)
4 |
5 | [](https://travis-ci.org/TrustWallet/trust-ray)
6 | [](https://github.com/fastlane/fastlane/blob/master/LICENSE)
7 | [](http://hits.dwyl.io/rip32700/TrustWallet/trust-wallet-backend)
8 | [](https://copilot.blackducksoftware.com/github/repos/TrustWallet/trust-ray/branches/token_endpoint)
9 |
10 |
11 | API for the Trust Ethereum Wallet.
12 |
13 | ## Features
14 |
15 | * Parsing entire blockchain
16 | * Retrieving transactions with operations field for ERC20 contract actions
17 | * Retrieving ERC20 token balances
18 | * Push notification service (not yet implemented)
19 |
20 | ## API [wiki](https://github.com/TrustWallet/trust-ray/wiki/API)
21 |
22 |
23 | ## Deploy on Heroku
24 | [](https://www.heroku.com/deploy/?template=https://github.com/TrustWallet/trust-wallet-backend)
25 |
26 | ## Locally (without docker)
27 | * Install required modules:
28 | ```$ npm install```
29 | * Compile TypeScript:
30 | ```$ npm run build```
31 | * Start the app:
32 | ```$ node dist/server.js```
33 | * Run tests:
34 | ```$ npm run build && npm test```
35 |
36 | ## Docker containers
37 | Install docker and docker-compose.
38 |
39 | Set in *~/.bashrc*
40 | ```export COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml```
41 |
42 | Set in .env
43 | ```MONGODB_URI=mongodb://mongodb:27017/trust-wallet```
44 |
45 | Dev tool:
46 |
47 | * Run build for npm install and build
48 | ```./trust build```
49 |
50 | * Start app in docker
51 | ```./trust run```
52 |
53 | * Stop docker containers
54 | ```./trust stop```
55 |
56 | * App logs
57 | ```./trust logs```
58 |
59 | ## Authors
60 |
61 | * [Philipp Rieger](https://github.com/rip32700)
62 | * [Michael Scoff](https://github.com/michaelScoff)
63 | * [Mykola Radchenko](https://github.com/kolya182)
64 |
65 |
66 | ## Contributing
67 |
68 | We intend for this project to be an educational resource: we are excited to
69 | share our wins, mistakes, and methodology of iOS development as we work
70 | in the open. Our primary focus is to continue improving the app for our users in
71 | line with our roadmap.
72 |
73 | The best way to submit feedback and report bugs is to open a GitHub issue.
74 | Please be sure to include your operating system, device, version number, and
75 | steps to reproduce reported bugs. Keep in mind that all participants will be
76 | expected to follow our code of conduct.
77 |
78 | ## Code of Conduct
79 |
80 | We aim to share our knowledge and findings as we work daily to improve our
81 | product, for our community, in a safe and open space. We work as we live, as
82 | kind and considerate human beings who learn and grow from giving and receiving
83 | positive, constructive feedback. We reserve the right to delete or ban any
84 | behavior violating this base foundation of respect.
85 |
--------------------------------------------------------------------------------
/config/custom-environment-variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "MONGO": {
3 | "URI": "MONGODB_URI"
4 | }
5 | }
--------------------------------------------------------------------------------
/config/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "MONGO": {
3 | "URI": "mongodb://localhost:27017/trust-wallet"
4 | }
5 | }
--------------------------------------------------------------------------------
/config/development.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "MONGO": {
3 | "URI": "MONGODB_URI"
4 | }
5 | }
--------------------------------------------------------------------------------
/config/test.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "MONGO": {
3 | "URI": "FILL_ME_IN"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "trust-api",
3 | "version": "0.1.0",
4 | "private": true,
5 | "description": "API Trust Wallet infrastructure.",
6 | "author": "Trust Wallet Team",
7 | "scripts": {
8 | "start": "cross-env NODE_ENV=development npm run watch-ts && npm run tslint",
9 | "build": "tsc",
10 | "watch-ts": "tsc-watch --onSuccess \"nodemon dist/Server.js\"",
11 | "test": "cross-env NODE_ENV=test mocha --recursive --require ts-node/register 'test/**/*.test.ts' --exit",
12 | "tslint": "tslint -c tslint.json -p tsconfig.json",
13 | "tslint-fix": "tslint -c tslint.json -p tsconfig.json --fix",
14 | "debug": "npm run build && npm run watch-debug",
15 | "serve-debug": "nodemon --inspect dist/Server.js",
16 | "watch-debug": "concurrently -k -p \"[{name}]\" -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold,green.bold\" \"npm run watch-ts\" \"npm run serve-debug\"",
17 | "docs": "apidoc -i ./src/routes -o ./apidoc/"
18 | },
19 | "engines": {
20 | "node": "9.5.0",
21 | "npm": "5.6.0"
22 | },
23 | "dependencies": {
24 | "async": "^2.1.2",
25 | "axios": "^0.17.1",
26 | "bluebird": "^3.5.1",
27 | "body-parser": "^1.15.2",
28 | "chai": "^4.1.2",
29 | "chai-http": "^3.0.0",
30 | "coinmarketcap-api": "^2.3.2",
31 | "concurrently": "^3.4.0",
32 | "config": "^1.29.4",
33 | "connect-mongo": "^2.0.0",
34 | "cors": "^2.8.4",
35 | "errorhandler": "^1.4.3",
36 | "express": "^4.14.0",
37 | "express-validator": "^4.3.0",
38 | "fs": "0.0.2",
39 | "lodash": "^4.17.10",
40 | "mocha": "^5.0.0",
41 | "mongoose": "^5.0.0",
42 | "mongoose-paginate": "^5.0.3",
43 | "morgan": "^1.7.0",
44 | "qs": "^6.5.2",
45 | "request": "^2.78.0",
46 | "ts-node": "^5.0.0",
47 | "tsc-watch": "^1.0.10",
48 | "tslint": "^5.0.0",
49 | "typescript": "^2.7.2",
50 | "web3": "^1.0.0-beta.24",
51 | "winston": "^2.4.0",
52 | "xss-filters": "^1.2.7"
53 | },
54 | "devDependencies": {
55 | "@types/async": "^2.0.40",
56 | "@types/bluebird": "^3.5.19",
57 | "@types/body-parser": "^1.16.2",
58 | "@types/chai": "^4.0.4",
59 | "@types/config": "0.0.34",
60 | "@types/connect-mongo": "0.0.35",
61 | "@types/errorhandler": "0.0.32",
62 | "@types/express": "^4.0.35",
63 | "@types/express-session": "1.15.6",
64 | "@types/jquery": "^3.2.17",
65 | "@types/mocha": "^2.2.44",
66 | "@types/mongodb": "^3.0.1",
67 | "@types/mongoose": "^4.7.24",
68 | "@types/mongoose-paginate": "^5.0.6",
69 | "@types/morgan": "^1.7.35",
70 | "@types/node": "^9.4.6",
71 | "@types/lodash": "^4.14.116",
72 | "@types/qs": "^6.5.1",
73 | "@types/request": "2.47.0",
74 | "@types/winston": "^2.3.7",
75 | "@types/xss-filters": "0.0.27",
76 | "apidoc": "^0.17.6",
77 | "cross-env": "^5.1.3",
78 | "nodemon": "^1.14.3"
79 | },
80 | "apidoc": {
81 | "name": "Trust API documentation",
82 | "version": "0.1.0",
83 | "description": "API consumed by the Trust Wallet",
84 | "apidoc": {
85 | "titel": "Title",
86 | "url": "https://http://public.trustwalletapp.com/"
87 | },
88 | "sampleUrl": "https://public.trustwalletapp.com"
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/App.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as express from "express";
3 | import * as bodyParser from "body-parser";
4 | import * as logger from "morgan";
5 | import * as errorHandler from "errorhandler";
6 | import { Database } from "./models/Database";
7 | import { router } from "./routes/ApiRoutes";
8 | import expressValidator = require("express-validator");
9 | import * as fs from "fs";
10 | import * as winston from "winston";
11 |
12 | const config = require("config");
13 | const cors = require("cors");
14 | const port = process.env.PORT || 8003;
15 |
16 | export class App {
17 |
18 | public app: any;
19 | public db: Database;
20 |
21 |
22 | constructor() {
23 | // create app
24 | this.app = express();
25 |
26 | // configure
27 | this.configureMiddleware();
28 |
29 | // setup database
30 | this.setupDatabase();
31 |
32 | // add routes
33 | this.addRoutes();
34 |
35 | // eventually start
36 | this.launch();
37 | }
38 |
39 |
40 | private configureMiddleware() {
41 | this.app.use(cors());
42 | this.app.set("port", port);
43 | this.app.use(logger("dev"));
44 | this.app.use(logger("common", {stream: fs.createWriteStream("./access.log", {flags: "a"})}));
45 | this.app.use(bodyParser.json());
46 | this.app.use(bodyParser.urlencoded({ extended: true }));
47 | this.app.use(expressValidator());
48 |
49 | // configure winston logger
50 | winston.add(
51 | winston.transports.File, {
52 | filename: "trustwallet.log",
53 | level: "info",
54 | json: true,
55 | eol: "\r\n",
56 | timestamp: true
57 | }
58 | );
59 |
60 | // remove for production
61 | this.app.use(errorHandler());
62 | }
63 |
64 | private setupDatabase() {
65 | this.db = new Database(config.get("MONGO.URI"));
66 | this.db.connect();
67 | }
68 |
69 | private addRoutes() {
70 | this.app.use("/", router);
71 | }
72 |
73 | private launch() {
74 | this.app.listen(this.app.get("port"), () => {
75 | winston.info(("App is running at http://localhost:%d in %s mode"), this.app.get("port"), this.app.get("env"));
76 | winston.info("Press CTRL-C to stop\n");
77 | });
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Server.ts:
--------------------------------------------------------------------------------
1 | import { App } from "./App";
2 |
3 | const app = new App();
--------------------------------------------------------------------------------
/src/common/Config.ts:
--------------------------------------------------------------------------------
1 | const Web3 = require("web3");
2 | // const config = require("config");
3 |
4 | export class Config {
5 | // static network = "" //config.get("RPC_SERVER");
6 | // static web3 = new Web3(new Web3.providers.HttpProvider(Config.network));
7 | }
8 |
--------------------------------------------------------------------------------
/src/common/Utils.ts:
--------------------------------------------------------------------------------
1 | import { Response } from "express";
2 |
3 | /**
4 | * Fills the status and JSOn data into a response object.
5 | * @param res response object
6 | * @param status of the response
7 | * @param content of the response
8 | */
9 | export function sendJSONresponse(res: Response, status: number, content: any) {
10 | res.status(status);
11 | res.json(content);
12 | }
13 |
14 | /**
15 | * Converts a number given as string containing scientific
16 | * notation to regular number, e.g.:
17 | * 1.105898485e+22 to 11058984850000000000000
18 | *
19 | * @param {string} numberString
20 | * @returns {string}
21 | */
22 | export function removeScientificNotationFromNumbString(numberString: string): string {
23 | const numb = +numberString;
24 | const data = String(numb).split(/[eE]/);
25 |
26 | if (data.length == 1)
27 | return data[0];
28 |
29 | let z = "";
30 | const sign = numb < 0 ? "-" : "";
31 | const str = data[0].replace(".", "");
32 | let mag = Number(data[1]) + 1;
33 |
34 | if (mag < 0) {
35 | z = sign + "0.";
36 | while (mag++)
37 | z += "0";
38 | return z + str.replace(/^\-/, "");
39 | }
40 | mag -= str.length;
41 | while (mag--)
42 | z += "0";
43 | return str + z;
44 | }
45 |
46 | export function setDelay(t: number): Promise {
47 | return new Promise((resolve) => {
48 | setTimeout(resolve, t);
49 | });
50 | }
51 |
52 | interface Array {
53 | flatMap(callback: (t: T) => Array): Array
54 | }
55 |
56 | Object.defineProperty(Array.prototype, "flatMap", {
57 | value: function(f: Function) {
58 | return this.reduce((ys: any, x: any) => {
59 | return ys.concat(f.call(this, x))
60 | }, [])
61 | },
62 | enumerable: false,
63 | })
64 |
--------------------------------------------------------------------------------
/src/common/tokens/contracts.ts:
--------------------------------------------------------------------------------
1 | export const contracts = {
2 | "0x1d462414fe14cf489c7a21cac78509f4bf8cd7c0": {
3 | id: "canyacoin"
4 | },
5 | "0x5f3789907b35dce5605b00c0be0a7ecdbfa8a841": {
6 | id: "content-and-ad-network",
7 | },
8 | "0xdd974d5c2e2928dea5f71b9825b8b646686bd200": {
9 | id: "kyber-network"
10 | },
11 | "0x1234567461d3f8db749681774bd869c83d51c93": {
12 | id: "bitclave"
13 | },
14 | "0x13f1b7fdfbe1fc66676d56483e21b1ecb40b58e2": {
15 | id: "accelerator-network"
16 | },
17 | "0x8aa33a7899fcc8ea5fbe6a608a109c3893a1b8b2": {
18 | id: "dao-casino"
19 | },
20 | "0xfae4ee59cdd86e3be9e8b90b53aa866327d7c090": {
21 | id: "cpchain"
22 | },
23 | "0xe0c72452740414d861606a44ccd5ea7f96488278": {
24 | id: "encryptotel-eth"
25 | },
26 | "0x2ae965cd3d2b6d186e87d9586fc3bdbfc667cacc": {
27 | id: "global-jobcoin"
28 | },
29 | "0xb70835d7822ebb9426b56543e391846c107bd32c": {
30 | id: "game"
31 | },
32 | "0x888666ca69e0f178ded6d75b5726cee99a87d698": {
33 | id: "iconomi"
34 | },
35 | "0x647f274b3a7248d6cf51b35f08e7e7fd6edfb271": {
36 | id: "maggie"
37 | },
38 | "0x449574c69f3a658794829ed81639a7a9ece041e1": {
39 | id: "neo-gold"
40 | },
41 | "0xcfb98637bcae43c13323eaa1731ced2b716962fd": {
42 | id: "nimiq"
43 | },
44 | "09800417b097c61b9fd26b3ddde4238304a110d5": {
45 | id: "qbao"
46 | },
47 | "0x7dc4f41294697a7903c4027f6ac528c5d14cd7eb": {
48 | id: "remicoin"
49 | },
50 | "0x6f6deb5db0c4994a8283a01d6cfeeb27fc3bbe9c": {
51 | id: "smartbillions"
52 | },
53 | "0x2c4e8f2d746113d0696ce89b35f0d8bf88e0aeca": {
54 | id: "ost"
55 | },
56 | "0x5e4abe6419650ca839ce5bb7db422b881a6064bb": {
57 | id: "wi-coin"
58 | },
59 | "0x78b039921e84e726eb72e7b1212bb35504c645ca": {
60 | id: "sether"
61 | },
62 | "0x226bb599a12c826476e3a771454697ea52e9e220": {
63 | id: "propy"
64 | },
65 | "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0": {
66 | id: "eos"
67 | },
68 | "0xf230b790e05390fc8295f4d3f60332c93bed42e2": {
69 | id: "tron"
70 | },
71 | "0xdac17f958d2ee523a2206206994597c13d831ec7": {
72 | id: "tether"
73 | },
74 | "0xd850942ef8811f2a866692a623011bde52a462c1": {
75 | id: "vechain"
76 | },
77 | "0xd26114cd6ee289accf82350c8d8487fedb8a0c07": {
78 | id: "omisego"
79 | },
80 | "0xb5a5f22694352c15b00323844ad545abb2b11028": {
81 | id: "icon"
82 | },
83 | "0xb8c77482e45f1f44de1745f52c74426c631bdd52": {
84 | id: "binance-coin"
85 | },
86 | "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a": {
87 | id: "digixdao"
88 | },
89 | "0xd4fa1460f537bb9085d22c7bccb5dd450ef28e3a": {
90 | id: "populous"
91 | },
92 | "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2": {
93 | id: "maker"
94 | },
95 | "0x744d70fdbe2ba4cf95131626614a1763df805b9e": {
96 | id: "status"
97 | },
98 | "0x168296bb09e24a88805cb9c33356536b980d3fc5": {
99 | id: "rchain"
100 | },
101 | "0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d": {
102 | id: "aeternity"
103 | },
104 | "0xb7cb1c96db6b22b0d3d9536e0108d062bd488f74": {
105 | id: "waltonchain"
106 | },
107 | "0xe94327d07fc17907b4db788e5adf2ed424addff6": {
108 | id: "augur"
109 | },
110 | "0xcb97e65f07da24d46bcdd078ebebd7c6e6e3d750": {
111 | id: "bytom"
112 | },
113 | "0xe41d2489571d322189246dafa5ebde1f4699f498": {
114 | id: "0x"
115 | },
116 | "0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374": {
117 | id: "veritaseum"
118 | },
119 | "0x05f4a42e251f2d52b8ed15e9fedaacfcef1fad27": {
120 | id: "zilliqa"
121 | },
122 | "0x0d8775f648430679a709e98d2b0cb6250d2887ef": {
123 | id: "basic-attention-token"
124 | },
125 | "0x419c4db4b9e25d6db2ad9691ccb832c8d9fda05e": {
126 | id: "dragonchain"
127 | },
128 | "0xa74476443119a942de498590fe1f2454d7d4ac0d": {
129 | id: "golem-network-tokens"
130 | },
131 | "0x5af2be193a6abca9c8817001f45744777db30756": {
132 | id: "ethos"
133 | },
134 | "0x618e75ac90b12c6049ba3b27f5d5f8651b0037f6": {
135 | id: "qash"
136 | },
137 | "0x4ceda7906a5ed2179785cd3a40a69ee8bc99c466": {
138 | id: "aion"
139 | },
140 | "0x5d65d971895edc438f465c17db6992698a52318d": {
141 | id: "nebulas-token"
142 | },
143 | "0x419d0d8bdd9af5e606ae2232ed285aff190e711b": {
144 | id: "funfair"
145 | },
146 | "0x48f775efbe4f5ece6e0df2f7b5932df56823b990": {
147 | id: "revain"
148 | },
149 | "0xef68e7c694f40c8202821edf525de3782458639f": {
150 | id: "loopring"
151 | },
152 | "0xbf2179859fc6d5bee9bf9158632dc51678a4100e": {
153 | id: "aelf"
154 | },
155 | "0x514910771af9ca656af840dff83e8264ecf986ca": {
156 | id: "chainlink"
157 | },
158 | "0x00e4dd9c3c32cbb2b6533abd0c8f6a33965e81e9": {
159 | id: "dentacoin"
160 | },
161 | "0x818fc6c2ec5986bc6e2cbf00939d90556ab12ce5": {
162 | id: "kin"
163 | },
164 | "0x4156d3342d5c385a87d264f90653733592000581": {
165 | id: "salt"
166 | },
167 | "0xfa1a856cfa3409cfa145fa4e20eb270df3eb21ab": {
168 | id: "iostoken"
169 | },
170 | "0x9992ec3cf6a55b00978cddf2b27bc6882d88d1ec": {
171 | id: "polymath-network"
172 | },
173 | "0x3597bfd533a99c9aa083587b074434e61eb0a258": {
174 | id: "dent"
175 | },
176 | "0x595832f8fc6bf59c85c527fec3740a1b7a361269": {
177 | id: "power-ledger"
178 | },
179 | "0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c": {
180 | id: "bancor"
181 | },
182 | "0xb97048628db6b661d4c2aa833e95dbe1a905b280": {
183 | id: "tenx"
184 | },
185 | "0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac": {
186 | id: "storj"
187 | },
188 | "0x8f8221afbb33998d8584a2b05749ba73c37a938a": {
189 | id: "request-network"
190 | },
191 | "0xf0ee6b27b759c9893ce4f094b49ad28fd15a23e4": {
192 | id: "enigma-project"
193 | },
194 | "0x68d57c9a1c35f63e2c83ee8e49a64e9d70528d25": {
195 | id: "sirin-labs-token"
196 | },
197 | "0x8eb24319393716668d768dcec29356ae9cffe285": {
198 | id: "singularitynet"
199 | },
200 | "0xb63b606ac810a52cca15e44bb630fd42d8d1d83d": {
201 | id: "monaco"
202 | },
203 | "0x12480e24eb5bec1a9d4369cab6a80cad3c0a377a": {
204 | id: "substratum"
205 | },
206 | "0xd4c435f5b09f855c3317c8524cb1f586e42795fa": {
207 | id: "cindicator"
208 | },
209 | "0x103c3a209da59d3e7c4a89307e66521e081cfdf0": {
210 | id: "genesis-vision"
211 | },
212 | "0xe3818504c1b32bf1557b16c238b2e01fd3149c17": {
213 | id: "pillar"
214 | },
215 | "0x6810e776880c02933d47db1b9fc05908e5386b96": {
216 | id: "gnosis-gno"
217 | },
218 | "0x41e5560054824ea6b0732e656e3ad64e20e94e45": {
219 | id: "civic"
220 | },
221 | "0x99ea4db9ee77acd40b119bd1dc4e33e1c070b80d": {
222 | id: "quantstamp"
223 | },
224 | "0xd0a4b8946cb52f0661273bfbc6fd0e0c75fc6433": {
225 | id: "storm"
226 | },
227 | "0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c": {
228 | id: "enjin-coin"
229 | },
230 | "0x255aa6df07540cb5d3d297f0d0d4d84cb52bc8e6": {
231 | id: "raiden-network-token"
232 | },
233 | "0x90528aeb3a2b736b780fd1b6c478bb7e1d643170": {
234 | id: "xpa"
235 | },
236 | "0x7c5a0ce9267ed19b22f8cae653f198e3e8daf098": {
237 | id: "santiment"
238 | },
239 | "0x3883f5e181fccaf8410fa61e12b59bad963fb645": {
240 | id: "theta-token"
241 | },
242 | "0xf433089366899d83a9f26a773d59ec7ecf30355e": {
243 | id: "metal"
244 | },
245 | "0x960b236a07cf122663c4303350609a66a7b288c0": {
246 | id: "aragon"
247 | },
248 | "0x607f4c5bb672230e8672085532f7e901544a7375": {
249 | id: "rlc"
250 | },
251 | "0x0f5d2fb29fb7d3cfee444a200298f468908cc942": {
252 | id: "decentraland"
253 | },
254 | "0xc42209accc14029c1012fb5680d95fbd6036e2a0": {
255 | id: "paypie"
256 | },
257 | "0x39bb259f66e1c59d5abef88375979b4d20d98022": {
258 | id: "wax"
259 | },
260 | "0xd234bf2410a0009df9c3c63b610c09738f18ccd7": {
261 | id: "dynamic-trading-rights"
262 | },
263 | "0xb91318f35bdb262e9423bc7c7c2a3a93dd93c92c": {
264 | id: "nuls"
265 | },
266 | "0x46b9ad944d1059450da1163511069c718f699d31": {
267 | id: "credits"
268 | },
269 | "0x0e0989b1f9b8a38983c2ba8053269ca62ec9b195": {
270 | id: "poet"
271 | },
272 | "0xb98d4c97425d9908e66e53a6fdf673acca0be986": {
273 | id: "arcblock"
274 | },
275 | "0x340d2bde5eb28c1eed91b2f790723e3b160613b7": {
276 | id: "blockv"
277 | },
278 | "0x3833dda0aeb6947b98ce454d89366cba8cc55528": {
279 | id: "sophiatx"
280 | },
281 | "0x1844b21593262668b7248d0f57a220caaba46ab9": {
282 | id: "oyster"
283 | },
284 | "0xd0352a019e9ab9d757776f532377aaebd36fd541": {
285 | id: "fusion"
286 | },
287 | "0x38c6a68304cdefb9bec48bbfaaba5c5b47818bb2": {
288 | id: "high-performance-blockchain"
289 | },
290 | "0x08711d3b02c8758f2fb3ab4e80228418a7f8e39c": {
291 | id: "edgeless"
292 | },
293 | "0x20e94867794dba030ee287f1406e100d03c84cd3": {
294 | id: "dew"
295 | },
296 | "0x4470bb87d77b963a013db939be332f927f2b992e": {
297 | id: "adx-net"
298 | },
299 | "0xf7920b0768ecb20a123fac32311d07d193381d6f": {
300 | id: "time-new-bank"
301 | },
302 | "0xd780ae2bf04cd96e577d3d014762f831d97129d0": {
303 | id: "envion"
304 | },
305 | "0x80fb784b7ed66730e8b1dbd9820afd29931aab03": {
306 | id: "ethlend"
307 | },
308 | "0x26e75307fc0c021472feb8f727839531f112f317": {
309 | id: "c20"
310 | },
311 | "0x5732046a883704404f284ce41ffadd5b007fd668": {
312 | id: "bluzelle"
313 | },
314 | "0xb3104b4b9da82025e8b9f8fb28b3553ce2f67069": {
315 | id: "bibox-token"
316 | },
317 | "0x85e076361cc813a908ff672f9bad1541474402b2": {
318 | id: "telcoin"
319 | },
320 | "0xe8ff5c9c75deb346acac493c463c8950be03dfba": {
321 | id: "vibe"
322 | },
323 | "0x42d6622dece394b54999fbd73d108123806f6a18": {
324 | id: "spankchain"
325 | },
326 | "0xa5fd1a791c4dfcaacc963d4f73c6ae5824149ea7": {
327 | id: "jibrel-network"
328 | },
329 | "0x983f6d60db79ea8ca4eb9968c6aff8cfa04b3c63": {
330 | id: "sonm"
331 | },
332 | "0x4dc3643dbc642b72c158e7f3d2ff232df61cb6ce": {
333 | id: "amber"
334 | },
335 | "0x66186008c1050627f979d464eabb258860563dbe": {
336 | id: "medishares"
337 | },
338 | "0x667088b212ce3d06a1b553a7221e1fd19000d9af": {
339 | id: "wings"
340 | },
341 | "0x671abbe5ce652491985342e85428eb1b07bc6c64": {
342 | id: "quantum-resistant-ledger"
343 | },
344 | "0x0cf0ee63788a0849fe5297f3407f701e122cc023": {
345 | id: "streamr-datacoin"
346 | },
347 | "0xf970b8e36e23f7fc3fd752eea86f8be8d83375a6": {
348 | id: "ripio-credit-network"
349 | },
350 | "0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1": {
351 | id: "melon"
352 | },
353 | "0x5e6b6d9abad9093fdc861ea1600eba1b355cd940": {
354 | id: "iot-chain"
355 | },
356 | "0xced4e93198734ddaff8492d525bd258d49eb388e": {
357 | id: "eidoo"
358 | },
359 | "0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f": {
360 | id: "origintrail"
361 | },
362 | "0x1c4481750daa5ff521a2a7490d9981ed46465dbd": {
363 | id: "blockmason"
364 | },
365 | "0x70a72833d6bf7f508c8224ce59ea1ef3d0ea3a38": {
366 | id: "utrust"
367 | },
368 | "0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009": {
369 | id: "singulardtv"
370 | },
371 | "0x9e3319636e2126e3c0bc9e3134aec5e1508a46c7": {
372 | id: "universa"
373 | },
374 | "0x558ec3152e2eb2174905cd19aea4e34a23de9ad6": {
375 | id: "bread"
376 | },
377 | "0x5b2e4a700dfbc560061e957edec8f6eeeb74a320": {
378 | id: "ins-ecosystem"
379 | },
380 | "0x40395044ac3c0c57051906da938b54bd6557f212": {
381 | id: "mobilego"
382 | },
383 | "0x55f93985431fc9304077687a35a1ba103dc1e081": {
384 | id: "smartmesh"
385 | },
386 | "0x1a7a8bd9106f2b8d977e08582dc7d24c723ab0db": {
387 | id: "appcoins"
388 | },
389 | "0xe7775a6e9bcf904eb39da2b68c5efb4f9360e08c": {
390 | id: "taas"
391 | },
392 | "0x4cf488387f035ff08c371515562cba712f9015d4": {
393 | id: "wepower"
394 | },
395 | "0xf85feea2fdd81d51177f6b8f35f0e6734ce45f5f": {
396 | id: "cybermiles"
397 | },
398 | "0x27054b13b1b798b345b591a4d22e6562d47ea75a": {
399 | id: "airswap"
400 | },
401 | "0xea38eaa3c86c8f9b751533ba2e562deb9acded40": {
402 | id: "etherparty"
403 | },
404 | "0x957c30ab0426e0c93cd8241e2c60392d08c6ac8e": {
405 | id: "modum"
406 | },
407 | "0xc5bbae50781be1669306b9e001eff57a2957b09d": {
408 | id: "gifto"
409 | },
410 | "0x27695e09149adc738a978e9a678f99e4c39e9eb9": {
411 | id: "kickico"
412 | },
413 | "0x72dd4b6bd852a3aa172be4d6c5a6dbec588cf131": {
414 | id: "naga"
415 | },
416 | "0x6c2adc2073994fb2ccc5032cc2906fa221e9b391": {
417 | id: "delphy"
418 | },
419 | "0x554c20b7c486beee439277b4540a434566dc4c02": {
420 | id: "decision-token"
421 | },
422 | "0x0abdace70d3790235af448c88547603b945604ea": {
423 | id: "district0x"
424 | },
425 | "0xfa05a73ffe78ef8f1a739473e462c54bae6567d9": {
426 | id: "lunyr"
427 | },
428 | "0xd0d6d6c5fe4a677d343cc433536bb717bae167dd": {
429 | id: "adtoken"
430 | },
431 | "0xb2f7eb1f2c37645be61d73953035360e768d81e6": {
432 | id: "cobinhood"
433 | },
434 | "0x08f5a9235b08173b7569f83645d2c7fb55e8ccd8": {
435 | id: "tierion"
436 | },
437 | "0xcbcc0f036ed4788f63fc0fee32873d6a7487b908": {
438 | id: "humaniq"
439 | },
440 | "0x5136c98a80811c3f46bdda8b5c4555cfd9f812f0": {
441 | id: "indahash"
442 | },
443 | "0x12fef5e57bf45873cd9b62e9dbd7bfb99e32d73e": {
444 | id: "cofound-it"
445 | },
446 | "0x45245bc59219eeaaf6cd3f382e078a461ff9de7b": {
447 | id: "bankex"
448 | },
449 | "0xc0eb85285d83217cd7c891702bcbc0fc401e2d9d": {
450 | id: "hive-project"
451 | },
452 | "0x80a7e048f37a50500351c204cb407766fa3bae7f": {
453 | id: "crypterium"
454 | },
455 | "0xaaaf91d9b90df800df4f55c205fd6989c977e73a": {
456 | id: "tokencard"
457 | },
458 | "0x96a65609a7b84e8842732deb08f56c3e21ac6f8a": {
459 | id: "centra"
460 | },
461 | "0x88a3e4f35d64aad41a6d4030ac9afe4356cb84fa": {
462 | id: "presearch"
463 | },
464 | "0x24692791bc444c5cd0b81e3cbcaba4b04acd1f3b": {
465 | id: "unikoin-gold"
466 | },
467 | "0x2c974b2d0ba1716e644c1fc59982a89ddd2ff724": {
468 | id: "viberate"
469 | },
470 | "0x41dbecc1cdc5517c6f76f6a6e836adbee2754de3": {
471 | id: "medical-chain"
472 | },
473 | "0x92e52a1a235d9a103d970901066ce910aacefd37": {
474 | id: "ucash"
475 | },
476 | "0x81c9151de0c8bafcd325a57e3db5a5df1cebf79c": {
477 | id: "datum"
478 | },
479 | "0x9b11efcaaa1890f6ee52c6bb7cf8153ac5d74139": {
480 | id: "attention-token-of-media"
481 | },
482 | "0xd65960facb8e4a2dfcb2c2212cb2e44a02e2a57e": {
483 | id: "soarcoin"
484 | },
485 | "0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8": {
486 | id: "everex"
487 | },
488 | "0x327682779bab2bf4d1337e8974ab9de8275a7ca8": {
489 | id: "blockport"
490 | },
491 | "0x1776e1f26f98b1a5df9cd347953a26dd3cb46671": {
492 | id: "numeraire"
493 | },
494 | "0x516e5436bafdc11083654de7bb9b95382d08d5de": {
495 | id: "ormeus-coin"
496 | },
497 | "0x12b306fa98f4cbb8d4457fdff3a0a0a56f07ccdf": {
498 | id: "spectre-dividend"
499 | },
500 | "0x12b19d3e2ccc14da04fae33e63652ce469b3f2fd": {
501 | id: "grid"
502 | },
503 | "0x9e88613418cf03dca54d6a2cf6ad934a78c7a17a": {
504 | id: "swarm-fund"
505 | },
506 | "0x6781a0f84c7e9e846dcb84a9a5bd49333067b104": {
507 | id: "zap"
508 | },
509 | "0x0b76544f6c413a555f309bf76260d1e02377c02a": {
510 | id: "internet-node-token"
511 | },
512 | "0xba9d4199fab4f26efe3551d490e3821486f135ba": {
513 | id: "swissborg"
514 | },
515 | "0xaf4dce16da2877f8c9e00544c93b62ac40631f16": {
516 | id: "monetha"
517 | },
518 | "0x9e96604445ec19ffed9a5e8dd7b50a29c899a10c": {
519 | id: "coss"
520 | },
521 | "0xf4134146af2d511dd5ea8cdb1c4ac88c57d60404": {
522 | id: "suncontract"
523 | },
524 | "0xae73b38d1c9a8b274127ec30160a4927c4d71824": {
525 | id: "stk"
526 | },
527 | "0x107c4504cd79c5d2696ea0030a8dd4e92601b82e": {
528 | id: "bloomtoken"
529 | },
530 | "0x7a41e0517a5eca4fdbc7fbeba4d4c47b9ff6dc63": {
531 | id: "zeusshield"
532 | },
533 | "0xba5f11b16b155792cf3b2e6880e8706859a8aeb6": {
534 | id: "aeron"
535 | },
536 | "0xcb94be6f13a1182e4a4b6140cb7bf2025d28e41b": {
537 | id: "trust"
538 | },
539 | "0xdf6ef343350780bf8c3410bf062e0c015b1dd671": {
540 | id: "blackmoon"
541 | },
542 | "0xfec0cf7fe078a500abf15f1284958f22049c2c7e": {
543 | id: "maecenas"
544 | },
545 | "0xfb2f26f266fb2805a387230f2aa0a331b4d96fba": {
546 | id: "dadi"
547 | },
548 | "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359": {
549 | id: "dai"
550 | },
551 | "0x4092678e4e78230f46a1534c0fbc8fa39780892b": {
552 | id: "odyssey"
553 | },
554 | "0x07e3c70653548b04f0a75970c1f81b4cbbfb606f": {
555 | id: "agrello-delta"
556 | },
557 | "0xd01db73e047855efb414e6202098c4be4cd2423b": {
558 | id: "uquid-coin"
559 | },
560 | "0x04f2e7221fdb1b52a68169b25793e51478ff0329": {
561 | id: "cappasity"
562 | },
563 | "0xf7b098298f7c69fc14610bf71d5e02c60792894c": {
564 | id: "guppy"
565 | },
566 | "0x4cc19356f2d37338b9802aa8e8fc58b0373296e7": {
567 | id: "selfkey"
568 | },
569 | "0xaa0bb10cec1fa372eb3abc17c933fc6ba863dd9e": {
570 | id: "hi-mutual-society"
571 | },
572 | "0xea1f346faf023f974eb5adaf088bbcdf02d761f4": {
573 | id: "blocktix"
574 | },
575 | "0x7728dfef5abd468669eb7f9b48a7f70a501ed29d": {
576 | id: "paragon"
577 | },
578 | "0x80bc5512561c7f85a3a9508c7df7901b370fa1df": {
579 | id: "trade-token"
580 | },
581 | "0x264dc2dedcdcbb897561a57cba5085ca416fb7b4": {
582 | id: "qunqun"
583 | },
584 | "0xc27a2f05fa577a83ba0fdb4c38443c0718356501": {
585 | id: "lamden"
586 | },
587 | "0x68aa3f232da9bdc2343465545794ef3eea5209bd": {
588 | id: "mothership"
589 | },
590 | "0x82b0e50478eeafde392d45d1259ed1071b6fda81": {
591 | id: "encrypgen"
592 | },
593 | "0x461733c17b0755ca5649b6db08b3e213fcf22546": {
594 | id: "atn"
595 | },
596 | "0x0bb217e40f8a5cb79adf04e1aab60e5abd0dfc1e": {
597 | id: "swftcoin"
598 | },
599 | "0xe50365f5d679cb98a1dd62d6f6e58e59321bcddf": {
600 | id: "latoken"
601 | },
602 | "0xcdcfc0f66c522fd086a1b725ea3c0eeb9f9e8814": {
603 | id: "aurora-dao"
604 | },
605 | "0x51db5ad35c671a87207d88fc11d593ac0c8415bd": {
606 | id: "moeda-loyalty-points"
607 | },
608 | "0x6425c6be902d692ae2db752b3c268afadb099d3b": {
609 | id: "restart-energy-mwat"
610 | },
611 | "0xe2fb6529ef566a080e6d23de0bd351311087d567": {
612 | id: "covesting"
613 | },
614 | "0x64cdf819d3e75ac8ec217b3496d7ce167be42e80": {
615 | id: "insurepal"
616 | },
617 | "0x701c244b988a513c945973defa05de933b23fe1d": {
618 | id: "oax"
619 | },
620 | "0xaf30d2a7e90d7dc361c8c4585e9bb7d2f6f15bc7": {
621 | id: "firstblood"
622 | },
623 | "0x9af4f26941677c706cfecf6d3379ff01bb85d5ab": {
624 | id: "domraider"
625 | },
626 | "0x3d1ba9be9f66b8ee101911bc36d3fb562eac2244": {
627 | id: "rivetz"
628 | },
629 | "0x2d0e95bd4795d7ace0da3c0ff7b706a5970eb9d3": {
630 | id: "all-sports"
631 | },
632 | "0x13f11c9905a08ca76e3e853be63d4f0944326c72": {
633 | id: "divi"
634 | },
635 | "0xfca47962d45adfdfd1ab2d972315db4ce7ccf094": {
636 | id: "ixledger"
637 | },
638 | "0xa823e6722006afe99e91c30ff5295052fe6b8e32": {
639 | id: "neumark"
640 | },
641 | "0x5d51fcced3114a8bb5e90cdd0f9d682bcbcc5393": {
642 | id: "b2bx"
643 | },
644 | "0xb24754be79281553dc1adc160ddf5cd9b74361a4": {
645 | id: "rialto"
646 | },
647 | "0xbdc5bac39dbe132b1e030e898ae3830017d7d969": {
648 | id: "snovio"
649 | },
650 | "0x1234567461d3f8db7496581774bd869c83d51c93": {
651 | id: "bitclave"
652 | },
653 | "0x1961b3331969ed52770751fc718ef530838b6dee": {
654 | id: "bitdegree"
655 | },
656 | "0xea610b1153477720748dc13ed378003941d84fab": {
657 | id: "alis"
658 | },
659 | "0xac3da587eac229c9896d919abc235ca4fd7f72c1": {
660 | id: "target-coin"
661 | },
662 | "0x0abefb7611cb3a01ea3fad85f33c3c934f8e2cf4": {
663 | id: "farad"
664 | },
665 | "0x94298f1e0ab2dfad6eeffb1426846a3c29d98090": {
666 | id: "mybit-token"
667 | },
668 | "0x52a7cb918c11a16958be40cba7e31e32a499a465": {
669 | id: "fidentiax"
670 | },
671 | "0xb9e7f8568e08d5659f5d29c4997173d84cdf2607": {
672 | id: "swarm-city"
673 | },
674 | "0x7654915a1b82d6d2d0afc37c52af556ea8983c7e": {
675 | id: "investfeed"
676 | },
677 | "0x263c618480dbe35c300d8d5ecda19bbb986acaed": {
678 | id: "olympus-labs"
679 | },
680 | "0x5e6016ae7d7c49d347dcf834860b9f3ee282812b": {
681 | id: "eztoken"
682 | },
683 | "0x006bea43baa3f7a6f765f14f10a1a1b08334ef45": {
684 | id: "stox"
685 | },
686 | "0x6531f133e6deebe7f2dce5a0441aa7ef330b4e53": {
687 | id: "chronobank"
688 | },
689 | "0xc324a2f6b05880503444451b8b27e6f9e63287cb": {
690 | id: "exchange-union"
691 | },
692 | "0x27dce1ec4d3f72c3e457cc50354f1f975ddef488": {
693 | id: "airtoken"
694 | },
695 | "0x3137619705b5fc22a3048989f983905e456b59ab": {
696 | id: "everus"
697 | },
698 | "0x9af2c6b1a28d3d6bc084bd267f70e90d49741d5b": {
699 | id: "axpire"
700 | },
701 | "0x881ef48211982d01e2cb7092c915e647cd40d85c": {
702 | id: "open-trading-network"
703 | },
704 | "0x9e6b2b11542f2bc52f3029077ace37e8fd838d7f": {
705 | id: "hacken"
706 | },
707 | "0xdd6c68bb32462e01705011a4e2ad1a60740f217f": {
708 | id: "hubii-network"
709 | },
710 | "0x4df812f6064def1e5e029f1ca858777cc98d2d81": {
711 | id: "xaurum"
712 | },
713 | "0x83984d6142934bb535793a82adb0a46ef0f66b6d": {
714 | id: "remme"
715 | },
716 | "0x9b68bfae21df5a510931a262cecf63f41338f264": {
717 | id: "decent-bet"
718 | },
719 | "0x3136ef851592acf49ca4c825131e364170fa32b3": {
720 | id: "coinfi"
721 | },
722 | "0x8ae4bf2c33a8e667de34b54938b0ccd03eb8cc06": {
723 | id: "patientory"
724 | },
725 | "0x29d75277ac7f0335b2165d0895e8725cbf658d73": {
726 | id: "bitdice"
727 | },
728 | "0x45e42d659d9f9466cd5df622506033145a9b89bc": {
729 | id: "nexium"
730 | },
731 | "0x2fa32a39fc1c399e0cc7b2935868f5165de7ce97": {
732 | id: "payfair"
733 | },
734 | "0xd8912c10681d8b21fd3742244f44658dba12264e": {
735 | id: "pluton"
736 | },
737 | "0x9af839687f6c94542ac5ece2e317daae355493a1": {
738 | id: "hydro-protocol"
739 | },
740 | "0xeb7c20027172e5d143fb030d50f91cece2d1485d": {
741 | id: "ebtcnew"
742 | },
743 | "0x56ba2ee7890461f463f7be02aac3099f6d5811a8": {
744 | id: "blockcat"
745 | },
746 | "0xa645264c5603e96c3b0b078cdab68733794b0a71": {
747 | id: "mysterium"
748 | },
749 | "0x85089389c14bd9c77fc2b8f0c3d1dc3363bf06ef": {
750 | id: "sportyco"
751 | },
752 | "0xba2184520a1cc49a6159c57e61e1844e085615b6": {
753 | id: "hellogold"
754 | },
755 | "0xe3fedaecd47aa8eab6b23227b0ee56f092c967a9": {
756 | id: "primas"
757 | },
758 | "0x5e3346444010135322268a4630d2ed5f8d09446c": {
759 | id: "lockchain"
760 | },
761 | "0x0affa06e7fbe5bc9a764c979aa66e8256a631f02": {
762 | id: "polybius"
763 | },
764 | "0x5b0751713b2527d7f002c0c4e2a37e1219610a6b": {
765 | id: "ethorse"
766 | },
767 | "0x4e0603e2a27a30480e5e3a4fe548e29ef12f64be": {
768 | id: "credo"
769 | },
770 | "0x814e0908b12a99fecf5bc101bb5d0b8b5cdf7d26": {
771 | id: "measurable-data-token"
772 | },
773 | "0xff603f43946a3a28df5e6a73172555d8c8b02386": {
774 | id: "oneroot-network"
775 | },
776 | "0x5f53f7a8075614b699baad0bc2c899f4bad8fbbf": {
777 | id: "rebl"
778 | },
779 | "0x8a854288a5976036a725879164ca3e91d30c6a1b": {
780 | id: "get-protocol"
781 | },
782 | "0x999967e2ec8a74b7c8e9db19e039d920b31d39d0": {
783 | id: "tiesdb"
784 | },
785 | "0xbc86727e770de68b1060c91f6bb6945c73e10388": {
786 | id: "ink-protocol"
787 | },
788 | "0xd2d6158683aee4cc838067727209a0aaf4359de3": {
789 | id: "bounty0x"
790 | },
791 | "0xaadb05f449072d275833baf7c82e8fca4ee46575": {
792 | id: "spectre-utility"
793 | },
794 | "0x539efe69bcdd21a83efd9122571a64cc25e0282b": {
795 | id: "ethereum-blue"
796 | },
797 | "0xf77f4810e7521298a6e2a04f82a6c3492706d74f": {
798 | id: "coinmeet"
799 | },
800 | "0xb6ee9668771a79be7967ee29a63d4184f8097143": {
801 | id: "cargox"
802 | },
803 | "0x3839d8ba312751aa0248fed6a8bacb84308e20ed": {
804 | id: "bezop"
805 | },
806 | "0xc8c6a31a4a806d3710a7b38b7b296d2fabccdba8": {
807 | id: "elixir"
808 | },
809 | "0x72adadb447784dd7ab1f472467750fc485e4cb2d": {
810 | id: "worldcore"
811 | },
812 | "0x7b22938ca841aa392c93dbb7f4c42178e3d65e88": {
813 | id: "astro"
814 | },
815 | "0xa6a840e50bcaa50da017b91a0d86b8b2d41156ee": {
816 | id: "echolink"
817 | },
818 | "0x0d88ed6e74bbfd96b831231638b66c05571e824f": {
819 | id: "aventus"
820 | },
821 | "0xea5f88e54d982cbb0c441cde4e79bc305e5b43bc": {
822 | id: "pareto-network"
823 | },
824 | "0x2604fa406be957e542beb89e6754fcde6815e83f": {
825 | id: "playkey"
826 | },
827 | "0x0f4ca92660efad97a9a70cb0fe969c755439772c": {
828 | id: "leverj"
829 | },
830 | "0x37e8789bb9996cac9156cd5f5fd32599e6b91289": {
831 | id: "aidcoin"
832 | },
833 | "0x621d78f2ef2fd937bfca696cabaf9a779f59b3ed": {
834 | id: "dcorp"
835 | },
836 | "0x83eea00d838f92dec4d1475697b9f4d3537b56e3": {
837 | id: "voisecom"
838 | },
839 | "0xf689bb4b063683a9ffd7a9295106f1e47c095809": {
840 | id: "jet8"
841 | },
842 | "0xa5f8fc0921880cb7342368bd128eb8050442b1a1": {
843 | id: "block-array"
844 | },
845 | "0xf04a8ac553fcedb5ba99a64799155826c136b0be": {
846 | id: "flixxo"
847 | },
848 | "0x705ee96c1c160842c92c1aecfcffccc9c412e3d9": {
849 | id: "clearpoll"
850 | },
851 | "0xff18dbc487b4c2e3222d115952babfda8ba52f5f": {
852 | id: "life"
853 | },
854 | "0x8dd5fbce2f6a956c3022ba3663759011dd51e73e": {
855 | id: "trueusd"
856 | },
857 | "0xf05a9382a4c3f29e2784502754293d88b835109c": {
858 | id: "real-estate-tokens"
859 | },
860 | "0xa7f976c360ebbed4465c2855684d1aae5271efa9": {
861 | id: "trueflip"
862 | },
863 | "0x923108a439c4e8c2315c4f6521e5ce95b44e9b4c": {
864 | id: "devery"
865 | },
866 | "0x9720b467a710382a232a32f540bdced7d662a10b": {
867 | id: "vezt"
868 | },
869 | "0xe477292f1b3268687a29376116b0ed27a9c76170": {
870 | id: "herocoin"
871 | },
872 | "0x5554e04e76533e1d14c52f05beef6c9d329e1e30": {
873 | id: "autonio"
874 | },
875 | "0x74ceda77281b339142a36817fa5f9e29412bab85": {
876 | id: "eroscoin"
877 | },
878 | "0x9c23d67aea7b95d80942e3836bcdf7e708a747c2": {
879 | id: "locicoin"
880 | },
881 | "0x3a92bd396aef82af98ebc0aa9030d25a23b11c6b": {
882 | id: "tokenbox"
883 | },
884 | "0x17fd666fa0784885fa1afec8ac624d9b7e72b752": {
885 | id: "flik"
886 | },
887 | "0xa8006c4ca56f24d6836727d106349320db7fef82": {
888 | id: "internxt"
889 | },
890 | "0xb62d18dea74045e822352ce4b3ee77319dc5ff2f": {
891 | id: "eventchain"
892 | },
893 | "0x8effd494eb698cc399af6231fccd39e08fd20b15": {
894 | id: "lampix"
895 | },
896 | "0x4355fc160f74328f9b383df2ec589bb3dfd82ba0": {
897 | id: "opus"
898 | },
899 | "0xac3211a5025414af2866ff09c23fc18bc97e79b1": {
900 | id: "dovu"
901 | },
902 | "0x672a1ad4f667fb18a333af13667aa0af1f5b5bdd": {
903 | id: "verify"
904 | },
905 | "0x0ebb614204e47c09b6c3feb9aaecad8ee060e23e": {
906 | id: "cryptopay"
907 | },
908 | "0x24ddff6d8b8a42d835af3b440de91f3386554aa4": {
909 | id: "iungo"
910 | },
911 | "0x55648de19836338549130b1af587f16bea46f66b": {
912 | id: "publica"
913 | },
914 | "0xfd8971d5e8e1740ce2d0a84095fca4de729d0c16": {
915 | id: "zilla"
916 | },
917 | "0x93e682107d1e9defb0b5ee701c71707a4b2e46bc": {
918 | id: "mcap"
919 | },
920 | "0xaef38fbfbf932d1aef3b808bc8fbd8cd8e1f8bc5": {
921 | id: "creditbit"
922 | },
923 | "0x2baac9330cf9ac479d819195794d79ad0c7616e3": {
924 | id: "adbank"
925 | },
926 | "0x519475b31653e46d20cd09f9fdcf3b12bdacb4f5": {
927 | id: "viuly"
928 | },
929 | "0x1063ce524265d5a3a624f4914acd573dd89ce988": {
930 | id: "aigang"
931 | },
932 | "0xea097a2b1db00627b2fa17460ad260c016016977": {
933 | id: "upfiring"
934 | },
935 | "0x9002d4485b7594e3e850f0a206713b305113f69e": {
936 | id: "hawala-today"
937 | },
938 | "0xd7631787b4dcc87b1254cfd1e5ce48e96823dee8": {
939 | id: "sociall"
940 | },
941 | "0xf44745fbd41f6a1ba151df190db0564c5fcc4410": {
942 | id: "copytrack"
943 | },
944 | "0x5c543e7ae0a1104f78406c340e9c64fd9fce5170": {
945 | id: "vslice"
946 | },
947 | "0x30cecb5461a449a90081f5a5f55db4e048397bab": {
948 | id: "tracto"
949 | },
950 | "0xcc34366e3842ca1bd36c1f324d15257960fcc801": {
951 | id: "bonpay"
952 | },
953 | "0x05c7065d644096a4e4c3fe24af86e36de021074b": {
954 | id: "lendconnect"
955 | },
956 | "0xf6cfe53d6febaeea051f400ff5fc14f0cbbdaca1": {
957 | id: "digipulse"
958 | },
959 | "0x78b7fada55a64dd895d8c8c35779dd8b67fa8a05": {
960 | id: "atlant"
961 | },
962 | "0x422866a8f0b032c5cf1dfbdef31a20f4509562b0": {
963 | id: "adshares"
964 | },
965 | "0xd3c00772b24d997a812249ca637a921e81357701": {
966 | id: "wild-crypto"
967 | },
968 | "0xe81d72d14b1516e68ac3190a46c93302cc8ed60f": {
969 | id: "coinlancer"
970 | },
971 | "0x1b22c32cd936cb97c28c5690a0695a82abf688e6": {
972 | id: "mywish"
973 | },
974 | "0xf8e386eda857484f5a12e4b5daa9984e06e73705": {
975 | id: "indorse-token"
976 | },
977 | "0xe2d82dc7da0e6f882e96846451f4fabcc8f90528": {
978 | id: "jesus-coin"
979 | },
980 | "0x8b1f49491477e0fb46a29fef53f1ea320d13c349": {
981 | id: "micromoney"
982 | },
983 | "0x8f0921f30555624143d427b340b1156914882c10": {
984 | id: "flypme"
985 | },
986 | "0xb802b24e0637c2b87d2e8b7784c055bbe921011a": {
987 | id: "ethereum-movie-venture"
988 | },
989 | "0xd341d1680eeee3255b8c4c75bcce7eb57f144dae": {
990 | id: "ongsocial"
991 | },
992 | "0x84119cb33e8f590d75c2d6ea4e6b0741a7494eda": {
993 | id: "giga-watt-token"
994 | },
995 | "0x39013f961c378f02c2b82a6e1d31e9812786fd9d": {
996 | id: "speed-mining-service"
997 | },
998 | "0x1183f92a5624d68e85ffb9170f16bf0443b4c242": {
999 | id: "qvolta"
1000 | },
1001 | "0x1500205f50bf3fd976466d0662905c9ff254fc9c": {
1002 | id: "bitboost"
1003 | },
1004 | "0x0371a82e4a9d0a4312f3ee2ac9c6958512891372": {
1005 | id: "student-coin"
1006 | },
1007 | "0xe8a1df958be379045e2b46a31a98b93a2ecdfded": {
1008 | id: "ethersportz"
1009 | },
1010 | "0x44197a4c44d6a059297caf6be4f7e172bd56caaf": {
1011 | id: "eltcoin"
1012 | },
1013 | "0x2bdc0d42996017fce214b21607a515da41a9e0c5": {
1014 | id: "skincoin"
1015 | },
1016 | "0xe64509f0bf07ce2d29a7ef19a8a9bc065477c1b4": {
1017 | id: "piplcoin"
1018 | },
1019 | "0x7703c35cffdc5cda8d27aa3df2f9ba6964544b6e": {
1020 | id: "pylon-network"
1021 | },
1022 | "0xe120c1ecbfdfea7f0a8f0ee30063491e8c26fedf": {
1023 | id: "suretly"
1024 | },
1025 | "0x26d5bd2dfeda983ecd6c39899e69dae6431dffbb": {
1026 | id: "erc20"
1027 | },
1028 | "0x0835ecd15ddf08d4786304d71b4672dc5c40f011": {
1029 | id: "pluscoin"
1030 | },
1031 | "0x02725836ebf3ecdb1cdf1c7b02fcbbfaa2736af8": {
1032 | id: "bitair"
1033 | },
1034 | "0x47dd62d4d075dead71d0e00299fc56a2d747bebb": {
1035 | id: "equal"
1036 | },
1037 | "0x2daee1aa61d60a252dc80564499a69802853583a": {
1038 | id: "authorship"
1039 | },
1040 | "0xab95e915c123fded5bdfb6325e35ef5515f1ea69": {
1041 | id: "xenon"
1042 | },
1043 | "0x809826cceab68c387726af962713b64cb5cb3cca": {
1044 | id: "nucleus-vision"
1045 | },
1046 | "0xafc39788c51f0c1ff7b55317f3e70299e521fff6": {
1047 | id: "ebitcoin-cash"
1048 | },
1049 | "0x28c8d01ff633ea9cd8fc6a451d7457889e698de6": {
1050 | id: "ethereum-gold"
1051 | },
1052 | "0x9a0242b7a33dacbe40edb927834f96eb39f8fbcb": {
1053 | id: "babb"
1054 | },
1055 | "0xe25bcec5d3801ce3a794079bf94adf1b8ccd802d": {
1056 | id: "matrix-ai-network"
1057 | },
1058 | "0xda6cb58a0d0c01610a29c5a65c303e13e885887c": {
1059 | id: "carvertical"
1060 | },
1061 | "0x63b992e6246d88f07fc35a056d2c365e6d441a3d": {
1062 | id: "soma"
1063 | },
1064 | "0xd5527579226e4ebc8864906e49d05d4458ccf47f": {
1065 | id: "kubera-coin"
1066 | },
1067 | "0x7d5edcd23daa3fb94317d32ae253ee1af08ba14d": {
1068 | id: "ethbet"
1069 | },
1070 | "0x9214ec02cb71cba0ada6896b8da260736a67ab10": {
1071 | id: "real"
1072 | },
1073 | "0x5d21ef5f25a985380b65c8e943a0082feda0db84": {
1074 | id: "ethereumcash"
1075 | },
1076 | "0x27f610bf36eca0939093343ac28b1534a721dbb4": {
1077 | id: "wandx"
1078 | },
1079 | "0x662abcad0b7f345ab7ffb1b1fbb9df7894f18e66": {
1080 | id: "cartaxi-token"
1081 | },
1082 | "0x1a95b271b0535d15fa49932daba31ba612b52946": {
1083 | id: "minereum"
1084 | },
1085 | "0x8727c112c712c4a03371ac87a74dd6ab104af768": {
1086 | id: "jetcoin"
1087 | },
1088 | "0x06147110022b768ba8f99a8f385df11a151a9cc8": {
1089 | id: "ace"
1090 | },
1091 | "0xcb5a05bef3257613e984c17dbcf039952b6d883f": {
1092 | id: "sugar-exchange"
1093 | },
1094 | "0x859a9c0b44cb7066d956a958b0b82e54c9e44b4b": {
1095 | id: "iethereum"
1096 | },
1097 | "0xeee2d00eb7deb8dd6924187f5aa3496b7d06e62a": {
1098 | id: "tigereum"
1099 | },
1100 | "0x6ccb56947ea1d6efdc81acfbacd8263ddfa9b202": {
1101 | id: "royal-kingdom-coin"
1102 | },
1103 | "0x49aec0752e68d0282db544c677f6ba407ba17ed7": {
1104 | id: "billionaire-token"
1105 | },
1106 | "0x6aac8cb9861e42bf8259f5abdc6ae3ae89909e11": {
1107 | id: "bitcoin-red"
1108 | },
1109 | "0x814964b1bceaf24e26296d031eadf134a2ca4105": {
1110 | id: "newbium"
1111 | },
1112 | "0xb45a50545beeab73f38f31e5973768c421805e5e": {
1113 | id: "trackr"
1114 | },
1115 | "0x9e77d5a1251b6f7d456722a6eac6d2d5980bd891": {
1116 | id: "brat"
1117 | },
1118 | "0x8a99ed8a1b204903ee46e733f2c1286f6d20b177": {
1119 | id: "fujinto"
1120 | },
1121 | "0x73b534fb6f07381a29a60b01eed5ae57d4ee24d7": {
1122 | id: "senderon"
1123 | },
1124 | "0xaec98a708810414878c3bcdf46aad31ded4a4557": {
1125 | id: "300-token"
1126 | },
1127 | "0x5102791ca02fc3595398400bfe0e33d7b6c82267": {
1128 | id: "leadcoin"
1129 | },
1130 | "0x4d8fc1453a0f359e99c9675954e656d80d996fbf": {
1131 | id: "bee-token"
1132 | },
1133 | "0xc7579bb99af590ec71c316e1ac4436c535039594": {
1134 | id: "titanium-blockchain"
1135 | },
1136 | "0x9a005c9a89bd72a4bd27721e7a09a3c11d2b03c4": {
1137 | id: "startercoin"
1138 | },
1139 | "0x2956356cd2a2bf3202f771f50d3d14a367b48070": {
1140 | id: "weth"
1141 | },
1142 | "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": {
1143 | id: "weth"
1144 | },
1145 | "0x14839bf22810f09fb163af69bd21bd5476f445cd": {
1146 | id: "confido"
1147 | },
1148 | "0x679badc551626e01b23ceecefbc9b877ea18fc46": {
1149 | id: "ccore"
1150 | },
1151 | "0xee609fe292128cad03b786dbb9bc2634ccdbe7fc": {
1152 | id: "postoken"
1153 | },
1154 | "0x2233799ee2683d75dfefacbcd2a26c78d34b470d": {
1155 | id: "network-token"
1156 | },
1157 | "0xca29db4221c111888a7e80b12eac8a266da3ee0d": {
1158 | id: "bolenum"
1159 | },
1160 | "0xd0929d411954c47438dc1d871dd6081f5c5e149c": {
1161 | id: "refereum"
1162 | },
1163 | "0x039b5649a59967e3e936d7471f9c3700100ee1ab": {
1164 | id: "kucoin-shares"
1165 | },
1166 | "0x106aa49295b525fcf959aa75ec3f7dcbf5352f1c": {
1167 | id: "rock"
1168 | },
1169 | "0xeda8b016efa8b1161208cf041cd86972eee0f31e": {
1170 | id: "iht-real-estate-protocol"
1171 | },
1172 | "0xf3db7560e820834658b590c96234c333cd3d5e5e": {
1173 | id: "coinpoker"
1174 | },
1175 | "0xffe8196bc259e8dedc544d935786aa4709ec3e64": {
1176 | id: "hedge"
1177 | },
1178 | "0x2ccbff3a042c68716ed2a2cb0c544a9f1d1935e1": {
1179 | id: "dmarket"
1180 | },
1181 | "0x336f646f87d9f6bc6ed42dd46e8b3fd9dbd15c22": {
1182 | id: "crystal-clear"
1183 | },
1184 | "0x5c3a228510d246b78a3765c20221cbf3082b44a4": {
1185 | id: "storiqa"
1186 | },
1187 | "0x954b5de09a55e59755acbda29e1eb74a45d30175": {
1188 | id: "fluz-fluz"
1189 | },
1190 | "0x07a58629aaf3e1a0d07d8f43114b76bd5eee3b91": {
1191 | id: "guaranteed-ethurance-token-extra"
1192 | },
1193 | "0xa4e8c3ec456107ea67d3075bf9e3df3a75823db0": {
1194 | id: "loom-network"
1195 | },
1196 | "0xc011a72400e58ecd99ee497cf89e3775d4bd732f": {
1197 | id: "havven"
1198 | },
1199 | "0x1122b6a0e00dce0563082b6e2953f3a943855c1f": {
1200 | id: "centrality"
1201 | },
1202 | "0x151202c9c18e495656f372281f493eb7698961d5": {
1203 | id: "debitum-network"
1204 | },
1205 | "0xfd107b473ab90e8fbd89872144a3dc92c40fa8c9": {
1206 | id: "lala-world"
1207 | },
1208 | "0xef2463099360a085f1f10b076ed72ef625497a06": {
1209 | id: "sharpe-platform-token"
1210 | },
1211 | "0xe25b0bba01dc5630312b6a21927e578061a13f55": {
1212 | id: "shipchain"
1213 | },
1214 | "0xe5f166c0d8872b68790061317bb6cca04582c912": {
1215 | id: "te-food"
1216 | },
1217 | "0xdd16ec0f66e54d453e6756713e533355989040e4": {
1218 | id: "tokenomy"
1219 | },
1220 | "0xa9ec9f5c1547bd5b0247cf6ae3aab666d10948be": {
1221 | id: "spherepay"
1222 | },
1223 | "0xd49ff13661451313ca1553fd6954bd1d9b6e02b9": {
1224 | id: "electrifyasia"
1225 | },
1226 | "0x8b353021189375591723e7384262f45709a3c3dc": {
1227 | id: "tomochain"
1228 | },
1229 | "0xabbbb6447b68ffd6141da77c18c7b5876ed6c5ab": {
1230 | id: "datx"
1231 | },
1232 | "0x1b957dc4aefeed3b4a2351a6a6d5cbfbba0cecfa": {
1233 | id: "hoqu"
1234 | },
1235 | "0x5b26c5d0772e5bbac8b3182ae9a13f9bb2d03765": {
1236 | id: "education-ecosystem"
1237 | },
1238 | "0x622dffcc4e83c64ba959530a5a5580687a57581b": {
1239 | id: "cube"
1240 | },
1241 | "0xc72fe8e3dd5bef0f9f31f259399f301272ef2a2d": {
1242 | id: "insights-network"
1243 | },
1244 | "0x57ad67acf9bf015e4820fbd66ea1a21bed8852ec": {
1245 | id: "lympo"
1246 | },
1247 | "0x5c743a35e903f6c584514ec617acee0611cf44f3": {
1248 | id: "experty"
1249 | },
1250 | "0xf2eab3a2034d3f6b63734d2e08262040e3ff7b48": {
1251 | id: "candy"
1252 | },
1253 | "0x1e797ce986c3cff4472f7d38d5c4aba55dfefe40": {
1254 | id: "blockcdn"
1255 | },
1256 | "0x71d01db8d6a2fbea7f8d434599c237980c234e4c": {
1257 | id: "gladius-token"
1258 | },
1259 | "0xe469c4473af82217b30cf17b10bcdb6c8c796e75": {
1260 | id: "exrnchain"
1261 | },
1262 | "0x36905fc93280f52362a1cbab151f25dc46742fb5": {
1263 | id: "bottos"
1264 | },
1265 | "0x408e41876cccdc0f92210600ef50372656052a38": {
1266 | id: "republic-protocol"
1267 | },
1268 | "0x998b3b82bc9dba173990be7afb772788b5acb8bd": {
1269 | id: "banca"
1270 | },
1271 | "0xee8bd1502c3e9f6c543781467c01592ac51cfbb8": {
1272 | id: "titanium-bar"
1273 | },
1274 | "0x355a458d555151d3b27f94227960ade1504e526a": {
1275 | id: "stockchain"
1276 | },
1277 | "0x2f8472dd7ecf7ca760c8f6b45db20ca7cf52f8d7": {
1278 | id: "bitstation"
1279 | },
1280 | "0x001f0aa5da15585e5b2305dbab2bac425ea71007": {
1281 | id: "ip-exchange"
1282 | },
1283 | "0x63e634330a20150dbb61b15648bc73855d6ccf07": {
1284 | id: "blocklancer"
1285 | },
1286 | "0x28dee01d53fed0edf5f6e310bf8ef9311513ae40": {
1287 | id: "blitzpredict"
1288 | },
1289 | "0x6f259637dcd74c767781e37bc6133cd6a68aa161": {
1290 | id: "huobi-token"
1291 | },
1292 | "0x584b44853680ee34a0f337b712a8f66d816df151": {
1293 | id: "aidoc"
1294 | },
1295 | "0x6745fab6801e376cd24f03572b9c9b0d4edddccf": {
1296 | id: "sense"
1297 | },
1298 | "0x286bda1413a2df81731d4930ce2f862a35a609fe": {
1299 | id: "wabi"
1300 | },
1301 | "0x6aeb95f06cda84ca345c2de0f3b7f96923a44f4c": {
1302 | id: "rentberry"
1303 | },
1304 | "0x23b75bc7aaf28e2d6628c3f424b3882f8f072a3c": {
1305 | id: "vice-industry-token"
1306 | },
1307 | "0x4270bb238f6dd8b1c3ca01f96ca65b2647c06d3c": {
1308 | id: "fortuna"
1309 | },
1310 | "0x4de2573e27e648607b50e1cfff921a33e4a34405": {
1311 | id: "lendroid-support-token"
1312 | },
1313 | "0xa15c7ebe1f07caf6bff097d8a589fb8ac49ae5b3": {
1314 | id: "pundi-x"
1315 | },
1316 | "0x41ab1b6fcbb2fa9dced81acbdec13ea6315f2bf2": {
1317 | id: "xinfin-network"
1318 | },
1319 | "0xac838aee2f650a6b970ecea56d4651653c1f84a1": {
1320 | id: "clearcoin"
1321 | },
1322 | "0xbf52f2ab39e26e0951d2a02b49b7702abe30406a": {
1323 | id: "odem"
1324 | },
1325 | "0x814f67fa286f7572b041d041b1d99b432c9155ee": {
1326 | id: "dragon-coins"
1327 | },
1328 | "0x123ab195dd38b1b40510d467a6a359b201af056f": {
1329 | id: "legolas-exchange"
1330 | },
1331 | "0x23352036e911a22cfc692b5e2e196692658aded9": {
1332 | id: "friends"
1333 | },
1334 | "0x9e46a38f5daabe8683e10793b06749eef7d733d1": {
1335 | id: "polyswarm"
1336 | },
1337 | "0x8db54ca569d3019a2ba126d03c37c44b5ef81ef6": {
1338 | id: "datawallet"
1339 | },
1340 | "0xe69a353b3152dd7b706ff7dd40fe1d18b7802d31": {
1341 | id: "adhive"
1342 | },
1343 | "0x9f5f3cfd7a32700c93f971637407ff17b91c7342": {
1344 | id: "scryinfo"
1345 | },
1346 | "0x7e9e431a0b8c4d532c745b1043c7fa29a48d4fba": {
1347 | id: "eosdac"
1348 | },
1349 | "0x6ba460ab75cd2c56343b3517ffeba60748654d26": {
1350 | id: "uptoken"
1351 | },
1352 | "0x08d32b0da63e2c3bcf8019c9c5d849d7a9d791e6": {
1353 | id: "dentacoin"
1354 | },
1355 | "0x5adc961d6ac3f7062d2ea45fefb8d8167d44b190": {
1356 | id: "dether"
1357 | },
1358 | "0x865e3707a580f9db89304005cddd050ade8873eb": {
1359 | id: "hirematch"
1360 | },
1361 | "0x37d40510a2f5bc98aa7a0f7bf4b3453bcfb90ac1": {
1362 | id: "belugapay"
1363 | },
1364 | "0x2f85e502a988af76f7ee6d83b7db8d6c0a823bf9": {
1365 | id: "latiumx"
1366 | },
1367 | "0x9b70740e708a083c6ff38df52297020f5dfaa5ee": {
1368 | id: "daneel"
1369 | },
1370 | "0xfdbc1adc26f0f8f8606a5d63b7d3a3cd21c22b23": {
1371 | id: "1world"
1372 | },
1373 | "0x1460a58096d80a50a2f1f956dda497611fa4f165": {
1374 | id: "chainium"
1375 | },
1376 | "0xffe02ee4c69edf1b340fcad64fbd6b37a7b9e265": {
1377 | id: "nanjcoin"
1378 | },
1379 | "0x900b4449236a7bb26b286601dd14d2bde7a6ac6c": {
1380 | id: "earth-token"
1381 | },
1382 | "0xb62132e35a6c13ee1ee0f84dc5d40bad8d815206": {
1383 | id: "nexo"
1384 | },
1385 | "0xfc2c4d8f95002c14ed0a7aa65102cac9e5953b5e": {
1386 | id: "rublix"
1387 | },
1388 | "0x53066cddbc0099eb6c96785d9b3df2aaeede5da3": {
1389 | id: "penta"
1390 | },
1391 | "0xebbdf302c940c6bfd49c6b165f457fdb324649bc": {
1392 | id: "hydrogen"
1393 | },
1394 | "0x737f98ac8ca59f2c68ad658e3c3d8c8963e40a4c": {
1395 | id: "amon"
1396 | },
1397 | "0x6710c63432a2de02954fc0f851db07146a6c0312": {
1398 | id: "syncfab"
1399 | },
1400 | "0x7b171c08d812f9c642dcf61f7e080610cbca64b3": {
1401 | id: "hade-platform"
1402 | },
1403 | "0x6295ab2be04a617747481b292c390bfca592cf28": {
1404 | id: "tokendesk"
1405 | },
1406 | "0x0b4bdc478791897274652dc15ef5c135cae61e60": {
1407 | id: "daex"
1408 | },
1409 | "0xbbff862d906e348e9946bfb2132ecb157da3d4b4": {
1410 | id: "sharder"
1411 | },
1412 | "0x763186eb8d4856d536ed4478302971214febc6a9": {
1413 | id: "betterbetting"
1414 | },
1415 | "0xb0280743b44bf7db4b6be482b2ba7b75e5da096c": {
1416 | id: "transcodium"
1417 | },
1418 | "0x47bc01597798dcd7506dcca36ac4302fc93a8cfb": {
1419 | id: "crowd-machine"
1420 | },
1421 | "0x4a527d8fc13c5203ab24ba0944f4cb14658d1db6": {
1422 | id: "morpheus-labs"
1423 | },
1424 | "0xd2fa8f92ea72abb35dbd6deca57173d22db2ba49": {
1425 | id: "origami"
1426 | },
1427 | "0xbcdfe338d55c061c084d81fd793ded00a27f226d": {
1428 | id: "decentralized-machine-learning"
1429 | },
1430 | "0xe34e1944e776f39b9252790a0527ebda647ae668": {
1431 | id: "helbiz"
1432 | },
1433 | "0x6c6ee5e31d828de241282b9606c8e98ea48526e2": {
1434 | id: "holo"
1435 | },
1436 | "0x12759512d326303b45f1cec8f7b6fd96f387778e": {
1437 | id: "trakinvest"
1438 | },
1439 | "0x2008e3057bd734e10ad13c9eae45ff132abc1722": {
1440 | id: "zebi"
1441 | },
1442 | "0x0947b0e6d821378805c9598291385ce7c791a6b2": {
1443 | id: "lendingblock"
1444 | },
1445 | "0xa017ac5fac5941f95010b12570b812c974469c2c": {
1446 | id: "proxeus"
1447 | },
1448 | "0x03c780cd554598592b97b7256ddaad759945b125": {
1449 | id: "biotron"
1450 | },
1451 | "0x17f8afb63dfcdcc90ebe6e84f060cc306a98257d": {
1452 | id: "nebula-ai"
1453 | },
1454 | "0xf41e5fbc2f6aac200dd8619e121ce1f05d150077": {
1455 | id: "crycash"
1456 | },
1457 | "0xd559f20296FF4895da39b5bd9ADd54b442596a61": {
1458 | id: "fintrux-network"
1459 | },
1460 | "0xf453b5b9d4e0b5c62ffb256bb2378cc2bc8e8a89": {
1461 | id: "mark-space"
1462 | },
1463 | "0xc27c95350ecd634c80df89db0f10cd5c24b7b11f": {
1464 | id: "pixie-coin"
1465 | },
1466 | "0xef8cf79c21637fc6f951bcac348915508a639a41": {
1467 | id: "srcoin"
1468 | },
1469 | "0xe5dada80aa6477e85d09747f2842f7993d0df71c": {
1470 | id: "dock"
1471 | },
1472 | "0x13c2fab6354d3790d8ece4f0f1a3280b4a25ad96": {
1473 | id: "phi-token"
1474 | },
1475 | "0x6beb418fc6e1958204ac8baddcf109b8e9694966": {
1476 | id: "linker-coin"
1477 | },
1478 | "0xe7d3e4413e29ae35b0893140f4500965c74365e5": {
1479 | id: "b2bcoin"
1480 | },
1481 | "0x44f588aeeb8c44471439d1270b3603c66a9262f1": {
1482 | id: "snipcoin"
1483 | },
1484 | "0x076c97e1c869072ee22f8c91978c99b4bcb02591": {
1485 | id: "commerceblock"
1486 | },
1487 | "0x52db8ebf894036ec997da693c5fa237a4fb69d10": {
1488 | id: "curriculum-vitae"
1489 | },
1490 | "0xb444208cb0516c150178fcf9a52604bc04a1acea": {
1491 | id: "greenmed"
1492 | },
1493 | "0xc12d099be31567add4e4e4d0d45691c3f58f5663": {
1494 | id: "auctus"
1495 | },
1496 | "0xccbf21ba6ef00802ab06637896b799f7101f54a2": {
1497 | id: "budbo"
1498 | },
1499 | "0xd7732e3783b0047aa251928960063f863ad022d8": {
1500 | id: "brahmaos"
1501 | },
1502 | "0x093e5c256ff8b32c7f1377f4c20e331674c77f00": {
1503 | id: "dignity"
1504 | },
1505 | "0x8810c63470d38639954c6b41aac545848c46484a": {
1506 | id: "aditus"
1507 | },
1508 | "0x52fb36c83ad33c1824912fc81071ca5eeb8ab390": {
1509 | id: "fidelium"
1510 | },
1511 | "0xea11755ae41d889ceec39a63e6ff75a02bc1c00d": {
1512 | id: "cortex"
1513 | },
1514 | "0x899338b84d25ac505a332adce7402d697d947494": {
1515 | id: "wawllet"
1516 | },
1517 | "0xbe428c3867f05dea2a89fc76a102b544eac7f772": {
1518 | id: "cybervein"
1519 | },
1520 | "0xa44e5137293e855b1b7bc7e2c6f8cd796ffcb037": {
1521 | id: "sentinel"
1522 | },
1523 | "0x3543638ed4a9006e4840b105944271bcea15605d": {
1524 | id: "u-network"
1525 | },
1526 | "0xc343f099d3e41aa5c1b59470450e21e92e2d840b": {
1527 | id: "verime"
1528 | },
1529 | "0x24a77c1f17c547105e14813e517be06b0040aa76": {
1530 | id: "live-stars"
1531 | },
1532 | "0x905e337c6c8645263d3521205aa37bf4d034e745": {
1533 | id: "docademic"
1534 | },
1535 | "0x9b4e2b4b13d125238aa0480dd42b4f6fc71b37cc": {
1536 | id: "mytoken"
1537 | },
1538 | "0x4cd988afbad37289baaf53c13e98e2bd46aaea8c": {
1539 | id: "key"
1540 | },
1541 | "0x3abdff32f76b42e7635bdb7e425f0231a5f3ab17": {
1542 | id: "connectjob"
1543 | },
1544 | "0x139d9397274bb9e2c29a9aa8aa0b5874d30d62e3": {
1545 | id: "boutspro"
1546 | },
1547 | "0xfedae5642668f8636a11987ff386bfd215f942ee": {
1548 | id: "policypal-network"
1549 | },
1550 | "0x61f33da40594cec1e3dc900faf99f861d01e2e7d": {
1551 | id: "cybereits"
1552 | },
1553 | "0x6dd4e4aad29a40edd6a409b9c1625186c9855b4d": {
1554 | id: "parkgene"
1555 | },
1556 | "0x1829aa045e21e0d59580024a951db48096e01782": {
1557 | id: "fuzex"
1558 | },
1559 | "0x543ff227f64aa17ea132bf9886cab5db55dcaddf": {
1560 | id: "daostack"
1561 | },
1562 | "0xd99b8a7fa48e25cce83b81812220a3e03bf64e5f": {
1563 | id: "skrumble-network"
1564 | },
1565 | "0x17e67d1cb4e349b9ca4bc3e17c7df2a397a7bb64": {
1566 | id: "freyrchain"
1567 | },
1568 | "0xE814aeE960a85208C3dB542C53E7D4a6C8D5f60F": {
1569 | id: "chronologic"
1570 | },
1571 | "0x905E337c6c8645263D3521205Aa37bf4d034e745": {
1572 | id: "docademic"
1573 | },
1574 | "0xedd7c94fd7b4971b916d15067bc454b9e1bad980": {
1575 | id: "zippie"
1576 | },
1577 | "0xec985525f3f22c7fa9c9ff4a49e37589a76d86d4": {
1578 | id: "super-game-chain"
1579 | },
1580 | "0xa0872ee815b8dd0f6937386fd77134720d953581": {
1581 | id: "edu-coin"
1582 | },
1583 | "0x8713d26637cf49e1b6b4a7ce57106aabc9325343": {
1584 | id: "content-neutrality-network"
1585 | },
1586 | "0x6ea6531b603f270d23d9edd2d8279135dc5d6773": {
1587 | id: "insurchain"
1588 | },
1589 | "0x228ba514309ffdf03a81a205a6d040e429d6e80c": {
1590 | id: "global-social-chain"
1591 | },
1592 | "0x4f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf": {
1593 | id: "digix-gold-token"
1594 | },
1595 | "0x4bffc9b4d4dcf730820a2edcad48ff5d7e0ae807": {
1596 | id: "influence-chain"
1597 | },
1598 | "0xb6f43025b29196af2dddd69b0a58afba079cd600": {
1599 | id: "intelligent-investment-chain"
1600 | },
1601 | "0x4af328c52921706dcb739f25786210499169afe6": {
1602 | id: "sakura-bloom"
1603 | },
1604 | "0x4ce6b362bc77a24966dda9078f9cef81b3b886a7": {
1605 | id: "nper"
1606 | },
1607 | "0x1a0f2ab46ec630f9fd638029027b552afa64b94c": {
1608 | id: "aston"
1609 | },
1610 | "0x6758b7d441a9739b98552b373703d8d3d14f9e62": {
1611 | id: "poa-network"
1612 | },
1613 | "0xc20464e0c373486d2b3335576e83a218b1618a5e": {
1614 | id: "datarius-credit"
1615 | },
1616 | "0x48df4e0296f908ceab0428a5182d19b31fc037d6": {
1617 | id: "fitrova"
1618 | },
1619 | "0x02585e4a14da274d02df09b222d4606b10a4e940": {
1620 | id: "hero"
1621 | },
1622 | "0xdae1baf249964bc4b6ac98c3122f0e3e785fd279": {
1623 | id: "tokia"
1624 | },
1625 | "0xf3b3cad094b89392fce5fafd40bc03b80f2bc624": {
1626 | id: "patron"
1627 | },
1628 | "0xfe5f141bf94fe84bc28ded0ab966c16b17490657": {
1629 | id: "libra-credit"
1630 | },
1631 | "0x69c4bb240cf05d51eeab6985bab35527d04a8c64": {
1632 | id: "open-platform"
1633 | },
1634 | "0x2ef27bf41236bd859a95209e17a43fbd26851f92": {
1635 | id: "morpheus-network"
1636 | },
1637 | "0x2859021ee7f2cb10162e67f33af2d22764b31aff": {
1638 | id: "silent-notary"
1639 | },
1640 | "0x55296f69f40ea6d20e478533c15a6b08b654e758": {
1641 | id: "xyo-network"
1642 | },
1643 | "0xf03045a4c8077e38f3b8e2ed33b8aee69edf869f": {
1644 | id: "blockmesh"
1645 | },
1646 | "0xb2135ab9695a7678dd590b1a996cb0f37bcb0718": {
1647 | id: "signals-network"
1648 | },
1649 | "0x8542325b72c6d9fc0ad2ca965a78435413a915a0": {
1650 | id: "oyster-shell"
1651 | },
1652 | "0x4df47b4969b2911c966506e3592c41389493953b": {
1653 | id: "fundrequest"
1654 | },
1655 | "0x4162178b78d6985480a308b2190ee5517460406d": {
1656 | id: "colu-local-network"
1657 | },
1658 | "0x491c9a23db85623eed455a8efdd6aba9b911c5df": {
1659 | id: "heronode"
1660 | },
1661 | "0x8400d94a5cb0fa0d041a3788e395285d61c9ee5e": {
1662 | id: "unibright"
1663 | },
1664 | "0x6fb3e0a217407efff7ca062d46c26e5d60a14d69": {
1665 | id: "iotex"
1666 | },
1667 | "0xece83617db208ad255ad4f45daf81e25137535bb": {
1668 | id: "invacio"
1669 | },
1670 | "0x1fe70be734e473e5721ea57c8b5b01e6caa52686": {
1671 | id: "bitrent"
1672 | },
1673 | "0x1ccaa0f2a7210d76e1fdec740d5f323e2e1b1672": {
1674 | id: "faceter"
1675 | },
1676 | "0x00c4b398500645eb5da00a1a379a88b11683ba01": {
1677 | id: "eximchain"
1678 | },
1679 | "0x5dbe296f97b23c4a6aa6183d73e574d02ba5c719": {
1680 | id: "level-up"
1681 | },
1682 | "0x588047365df5ba589f923604aac23d673555c623": {
1683 | id: "naviaddress"
1684 | },
1685 | "0xa9d2927d3a04309e008b6af6e2e282ae2952e7fd": {
1686 | id: "zip"
1687 | },
1688 | "0x1dea979ae76f26071870f824088da78979eb91c8": {
1689 | id: "spindle"
1690 | },
1691 | "0x3adfc4999f77d04c8341bac5f3a76f58dff5b37a": {
1692 | id: "privatix"
1693 | },
1694 | "0x949bed886c739f1a3273629b3320db0c5024c719": {
1695 | id: "amis"
1696 | },
1697 | "0x3893b9422cd5d70a81edeffe3d5a1c6a978310bb": {
1698 | id: "mithril"
1699 | },
1700 | "0xea26c4ac16d4a5a106820bc8aee85fd0b7b2b664": {
1701 | id: "quarkchain"
1702 | },
1703 | "0x6175f6f85339f1e56affac5a68cbf8297969004d": {
1704 | id: "shopin"
1705 | },
1706 | "0xb9bb08ab7e9fa0a1356bd4a39ec0ca267e03b0b3": {
1707 | id: "pchain"
1708 | },
1709 | "0xb6ed7644c69416d67b522e20bc294a9a9b405b31": {
1710 | id: "0xbtc"
1711 | },
1712 | "0x84f7c44b6fed1080f647e354d552595be2cc602f": {
1713 | id: "bigbom"
1714 | },
1715 | "0xc528c28fec0a90c083328bc45f587ee215760a0f": {
1716 | id: "endor-protocol"
1717 | },
1718 | "0xa4ea687a2a7f29cf2dc66b39c68e4411c0d00c49": {
1719 | id: "ivy"
1720 | },
1721 | "0xac0741127cac11e4455c7943b654bcced7fdd5a4": {
1722 | id: "ejoy"
1723 | },
1724 | "0xb1eef147028e9f480dbc5ccaa3277d417d1b85f0": {
1725 | id: "seele"
1726 | },
1727 | "0x697beac28b09e122c4332d163985e8a73121b97f": {
1728 | id: "quantum-resistant-ledger"
1729 | },
1730 | "0xfd1e80508f243e64ce234ea88a5fd2827c71d4b7": {
1731 | id: "medx"
1732 | },
1733 | "0xb5dbc6d3cf380079df3b27135664b6bcf45d1869": {
1734 | id: "shivom"
1735 | },
1736 | "0x0e8d6b471e332f140e7d9dbb99e5e3822f728da6": {
1737 | id: "the-abyss"
1738 | },
1739 | "0x81b4d08645da11374a03749ab170836e4e539767": {
1740 | id: "paymon"
1741 | },
1742 | "0xcdb7ecfd3403eef3882c65b761ef9b5054890a47": {
1743 | id: "hurify"
1744 | },
1745 | "0x3209f98bebf0149b769ce26d71f7aea8e435efea": {
1746 | id: "traxia"
1747 | },
1748 | "0xaf8a215e81faea7c180ce22b72483525121813bd": {
1749 | id: "engine"
1750 | },
1751 | "0x2d9765a94ff22e0ca3afc3e3f4b116de2b67582a": {
1752 | id: "cgc-token"
1753 | },
1754 | "0x26db5439f651caf491a87d48799da81f191bdb6b": {
1755 | id: "cashbet-coin"
1756 | },
1757 | "0xb056c38f6b7dc4064367403e26424cd2c60655e1": {
1758 | id: "ceek-vr"
1759 | },
1760 | "0x75c5ee419331b6150879530d06f9ba054755f1da": {
1761 | id: "salpay"
1762 | },
1763 | "0xf091cf09c51811819db705710e9634b8bf18f164": {
1764 | id: "couchain"
1765 | },
1766 | "0x624d520bab2e4ad83935fa503fb130614374e850": {
1767 | id: "smartshare"
1768 | },
1769 | "0x0f8c45b896784a1e408526b9300519ef8660209c": {
1770 | id: "xmax"
1771 | },
1772 | "0x69beab403438253f13b6e92db91f7fb849258263": {
1773 | id: "neurotoken"
1774 | },
1775 | "0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4": {
1776 | id: "jet8"
1777 | },
1778 | "0x436f0f3a982074c4a05084485d421466a994fe53": {
1779 | id: "rate3"
1780 | },
1781 | "0x69b148395ce0015c13e36bffbad63f49ef874e03": {
1782 | id: "data"
1783 | },
1784 | "0xca3ea3061d638e02113aa960340c98343b5acd62": {
1785 | id: "bittwatt"
1786 | },
1787 | "0x49b127bc33ce7e1586ec28cec6a65b112596c822": {
1788 | id: "alax"
1789 | },
1790 | "0x3c4a3ffd813a107febd57b2f01bc344264d90fde": {
1791 | id: "energitoken"
1792 | },
1793 | "0xa3d58c4e56fedcae3a7c43a725aee9a71f0ece4e": {
1794 | id: "metronome"
1795 | },
1796 | "0x9ab165d795019b6d8b3e971dda91071421305e5a": {
1797 | id: "aurora"
1798 | },
1799 | "0x970e035e2a013cf4becd67e300d65bc32a56d826": {
1800 | id: "bodhi-eth"
1801 | },
1802 | "0xeb9a4b185816c354db92db09cc3b50be60b901b6": {
1803 | id: "origin-sport"
1804 | },
1805 | "0xffa93aacf49297d51e211817452839052fdfb961": {
1806 | id: "distributed-credit-chain"
1807 | },
1808 | "0xa8258abc8f2811dd48eccd209db68f25e3e34667": {
1809 | id: "constellation"
1810 | },
1811 | "0x8a77e40936bbc27e80e9a3f526368c967869c86d": {
1812 | id: "merculet"
1813 | },
1814 | "0xc86d054809623432210c107af2e3f619dcfbf652": {
1815 | id: "sentinel-protocol"
1816 | },
1817 | "0x906b3f8b7845840188eab53c3f5ad348a787752f": {
1818 | id: "dorado"
1819 | },
1820 | "0x9cda8a60dd5afa156c95bd974428d91a0812e054": {
1821 | id: "tatatu"
1822 | },
1823 | "0x8e1b448ec7adfc7fa35fc2e885678bd323176e34": {
1824 | id: "egretia"
1825 | },
1826 | "0xb9ef770b6a5e12e45983c5d80545258aa38f3b78": {
1827 | id: "0chain"
1828 | },
1829 | "0xa2a54f1ec1f09316ef12c1770d32ed8f21b1fb6a": {
1830 | id: "digifinextoken"
1831 | },
1832 | "0x1ed7ae1f0e2fa4276dd7ddc786334a3df81d50c0": {
1833 | id: "forty-seven-bank"
1834 | },
1835 | "0x4f27053f32eda8af84956437bc00e5ffa7003287": {
1836 | id: "thrive-token"
1837 | },
1838 | "0x423b5f62b328d0d6d44870f4eee316befa0b2df5": {
1839 | id: "gonetwork"
1840 | },
1841 | "0x378903a03fb2c3ac76bb52773e3ce11340377a32": {
1842 | id: "clipper-coin"
1843 | },
1844 | "0xdf2c7238198ad8b389666574f2d8bc411a4b7428": {
1845 | id: "mainframe"
1846 | },
1847 | "0x6863be0e7cf7ce860a574760e9020d519a8bdc47": {
1848 | id: "on-live"
1849 | },
1850 | "0xa86a0da9d05d0771955df05b44ca120661af16de": {
1851 | id: "otcbtc-token"
1852 | },
1853 | "0xb07ec2c28834b889b1ce527ca0f19364cd38935c": {
1854 | id: "cardstack"
1855 | },
1856 | "0x8E5610ab5E39d26828167640EA29823fe1dD5843": {
1857 | id: "kanadecoin"
1858 | },
1859 | "0xdf347911910b6c9a4286ba8e2ee5ea4a39eb2134": {
1860 | id: "bobs-repair"
1861 | },
1862 | "0x4d9e23a3842fe7eb7682b9725cf6c507c424a41b": {
1863 | id: "carblock"
1864 | },
1865 | "0x4aac461c86abfa71e9d00d9a2cde8d74e4e1aeea": {
1866 | id: "zinc"
1867 | },
1868 | "0xfc05987bd2be489ACCF0f509E44B0145d68240f7": {
1869 | id: "essentia"
1870 | },
1871 | "0xf3586684107ce0859c44aa2b2e0fb8cd8731a15a": {
1872 | id: "karatgold-coin"
1873 | },
1874 | "0x765f0c16d1ddc279295c1a7c24b0883f62d33f75": {
1875 | id: "data-exchange"
1876 | },
1877 | "0x6a27348483d59150ae76ef4c0f3622a78b0ca698": {
1878 | id: "beekan"
1879 | },
1880 | "0x865ec58b06bf6305b886793aa20a2da31d034e68": {
1881 | id: "mossland"
1882 | },
1883 | "0x5b135d7e2774c801a73208f258123d7623e07784": {
1884 | id: "saifu"
1885 | },
1886 | "0x4375e7ad8a01b8ec3ed041399f62d9cd120e0063": {
1887 | id: "bit-z-token"
1888 | },
1889 | "0xf4b54874cd8a6c863e3a904c18fda964661ec363": {
1890 | id: "dws"
1891 | },
1892 | "0x83e2be8d114f9661221384b3a50d24b96a5653f5": {
1893 | id: "0xcert"
1894 | },
1895 | "0x64a60493d888728cf42616e034a0dfeae38efcf0": {
1896 | id: "oneledger"
1897 | },
1898 | "0x97aeb5066e1a590e868b511457beb6fe99d329f5": {
1899 | id: "atonomi"
1900 | },
1901 | "0x57ab1e02fee23774580c119740129eac7081e9d3": {
1902 | id: "nusd"
1903 | },
1904 | "0x986ee2b944c42d017f52af21c4c69b84dbea35d8": {
1905 | id: "bitmart-token"
1906 | },
1907 | "0x44449fa4d607f807d1ed4a69ad942971728391c8": {
1908 | id: "xmct"
1909 | },
1910 | "0x57e299ee8f1c5a92a9ed54f934acc7ff5f159699": {
1911 | id: "record"
1912 | },
1913 | "0xf4faea455575354d2699bc209b0a65ca99f69982": {
1914 | id: "no-bs-crypto"
1915 | },
1916 | "0x2c949199cff14aeaf1b33d64db01f48fb57f592f": {
1917 | id: "coni"
1918 | },
1919 | "0x943ed852dadb5c3938ecdc6883718df8142de4c8": {
1920 | id: "fanstime"
1921 | },
1922 | "0xe3f4b4a5d91e5cb9435b947f090a319737036312": {
1923 | id: "popchain"
1924 | },
1925 | "0x0f1ed66c251bcb52ecf7e67ac64bb72482048adb": {
1926 | id: "seer"
1927 | },
1928 | "0xd37532d304214d588aeeac4c365e8f1d72e2304a": {
1929 | id: "fcoin-token"
1930 | },
1931 | "0xfc05987bd2be489accf0f509e44b0145d68240f7": {
1932 | id: "essentia"
1933 | },
1934 | "0x2bba3cf6de6058cc1b4457ce00deb359e2703d7f": {
1935 | id: "hashcoin"
1936 | },
1937 | "0x02f61fd266da6e8b102d4121f5ce7b992640cf98": {
1938 | id: "likecoin"
1939 | },
1940 | "0xd9a12cde03a86e800496469858de8581d3a5353d": {
1941 | id: "crowdholding"
1942 | },
1943 | "0xac2e58a06e6265f1cf5084ee58da68e5d75b49ca": {
1944 | id: "ors-group"
1945 | },
1946 | "0x464ebe77c293e473b48cfe96ddcf88fcf7bfdac0": {
1947 | id: "kryll"
1948 | },
1949 | // Coins. Based on the slip
1950 | "0x000000000000000000000000000000000000003c": {
1951 | id: "ethereum"
1952 | },
1953 | "0x00000000000000000000000000000000000000ac": {
1954 | id: "poa-network"
1955 | },
1956 | "0x000000000000000000000000000000000000003d": {
1957 | id: "ethereum-classic"
1958 | },
1959 | "0x0000000000000000000000000000000000000334": {
1960 | id: "callisto-network"
1961 | },
1962 | "0x00000000000000000000000000000000000017ac": {
1963 | id: "gochain"
1964 | },
1965 | "0x60c24407d01782c2175d32fe7c8921ed732371d1": {
1966 | id: "lemochain"
1967 | },
1968 | "0xdb455c71c1bc2de4e80ca451184041ef32054001": {
1969 | id: "jury-online-token"
1970 | },
1971 | "0xa95592dcffa3c080b4b40e459c5f5692f67db7f8": {
1972 | id: "elysian"
1973 | },
1974 | "0x63f584fa56e60e4d0fe8802b27c7e6e3b33e007f": {
1975 | id: "contentbox"
1976 | },
1977 | "0x4689a4e169eb39cc9078c0940e21ff1aa8a39b9c": {
1978 | id: "proton-token"
1979 | },
1980 | "0xb4efd85c19999d84251304bda99e90b92300bd93": {
1981 | id: "rocket-pool"
1982 | },
1983 | "0xf8e06e4e4a80287fdca5b02dccecaa9d0954840f": {
1984 | id: "tgame"
1985 | },
1986 | "0x5dbac24e98e2a4f43adc0dc82af403fca063ce2c": {
1987 | id: "engagement-token"
1988 | },
1989 | "0x1b793e49237758dbd8b752afc9eb4b329d5da016": {
1990 | id: "vite"
1991 | },
1992 | "0x5c64031c62061865e5fd0f53d3cdaef80f72e99d": {
1993 | id: "hashgard"
1994 | },
1995 | "0x24dcc881e7dd730546834452f21872d5cb4b5293": {
1996 | id: "scroll"
1997 | },
1998 | "0x05aaaa829afa407d83315cded1d45eb16025910c": {
1999 | id: "sp8de"
2000 | },
2001 | "0x4c0fbe1bb46612915e7967d2c3213cd4d87257ad": {
2002 | id: "apis"
2003 | },
2004 | "0x8e5610ab5e39d26828167640ea29823fe1dd5843": {
2005 | id: "kanadecoin"
2006 | },
2007 | "0xf485c5e679238f9304d986bb2fc28fe3379200e5": {
2008 | id: "ugchain"
2009 | },
2010 | "0x076641af1b8f06b7f8c92587156143c109002cbe": {
2011 | id: "sopay"
2012 | },
2013 | "0xc8058d59e208399b76e66da1ec669dd6b1bee2ea": {
2014 | id: "gold-bits-coin"
2015 | },
2016 | "0xbd168cbf9d3a375b38dc51a202b5e8a4e52069ed": {
2017 | id: "blue-whale-token"
2018 | },
2019 | "0xd8950fdeaa10304b7a7fd03a2fc66bc39f3c711a": {
2020 | id: "wys-token"
2021 | },
2022 | "0xc4bcd64cb216d49fd3c643a32762f34626b45a1a": {
2023 | id: "cosmo-coin"
2024 | },
2025 | "0x9d9223436ddd466fc247e9dbbd20207e640fef58": {
2026 | id: "olive"
2027 | },
2028 | "0xaae81c0194d6459f320b70ca0cedf88e11a242ce": {
2029 | id: "wetoken"
2030 | },
2031 | "0xe3278df3eb2085ba9b6899812a99a10f9ca5e0df": {
2032 | id: "tourist-token"
2033 | },
2034 | "0x4a42d2c580f83dce404acad18dab26db11a1750e": {
2035 | id: "relex"
2036 | },
2037 | "0xfbc3c8aad80b5934d134e2cce065702ff254ad7d": {
2038 | id: "chex"
2039 | },
2040 | "0xf03f8d65bafa598611c3495124093c56e8f638f0": {
2041 | id: "view"
2042 | },
2043 | "0x9746953f5b1324a78132895cfd263f417b0faae3": {
2044 | id: "valuecybertoken"
2045 | },
2046 | "0xd2946be786f35c3cc402c29b323647abda799071": {
2047 | id: "vikkytoken"
2048 | },
2049 | "0xfbe878ced08132bd8396988671b450793c44bc12": {
2050 | id: "fox-trading"
2051 | },
2052 | "0xec491c1088eae992b7a214efb0a266ad0927a72a": {
2053 | id: "ab-chain-rtb"
2054 | },
2055 | "0x81705082ef9f0d660f07be80093d46d826d48b25": {
2056 | id: "globalvillage-ecosystem"
2057 | },
2058 | "0xaa19961b6b858d9f18a115f25aa1d98abc1fdba8": {
2059 | id: "local-coin-swap"
2060 | },
2061 | "0xb5b8f5616fe42d5ceca3e87f3fddbdd8f496d760": {
2062 | id: "zper-token"
2063 | },
2064 | "0xe7d7b37e72510309db27c460378f957b1b04bd5d": {
2065 | id: "empowr-coin"
2066 | },
2067 | "0x47da42696a866cdc61a4c809a515500a242909c1": {
2068 | id: "bitrewards"
2069 | },
2070 | "0xbf5496122cf1bb778e0cbe5eab936f2be5fc0940": {
2071 | id: "fundtoken"
2072 | },
2073 | "0xe0c8087ce1a17bdd5d6c12eb52f8d7eff7791987": {
2074 | id: "linfinity"
2075 | },
2076 | "0x4bbbc57af270138ef2ff2c50dbfad684e9e0e604": {
2077 | id: "wabnetwork"
2078 | },
2079 | "0xd8698a985b89650d0a70f99ad2909bd0c0b4b51c": {
2080 | id: "consentium"
2081 | },
2082 | "0xa849eaae994fb86afa73382e9bd88c2b6b18dc71": {
2083 | id: "mass-vehicle-ledger"
2084 | },
2085 | "0xafbec4d65bc7b116d85107fd05d912491029bf46": {
2086 | id: "arbitrage"
2087 | },
2088 | "0xf8c595d070d104377f58715ce2e6c93e49a87f3c": {
2089 | id: "dacc"
2090 | },
2091 | "0xfb5a551374b656c6e39787b1d3a03feab7f3a98e": {
2092 | id: "thingsoperatingsystem"
2093 | },
2094 | "0x8f66a173696502a0ad280781c3e55928a06c1312": {
2095 | id: "wavebase"
2096 | },
2097 | "0xfb1e5f5e984c28ad7e228cdaa1f8a0919bb6a09b": {
2098 | id: "galaxy-esolutions"
2099 | },
2100 | "0xeb021dd3e42dc6fdb6cde54d0c4a09f82a6bca29": {
2101 | id: "fnkos"
2102 | },
2103 | "0x1a66e09f7dccc10eae46e27cfa6b8d44a50df1e7": {
2104 | id: "prasm"
2105 | },
2106 | "0x1410434b0346f5be678d0fb554e5c7ab620f8f4a": {
2107 | id: "bitkan"
2108 | },
2109 | "0xdb25f211ab05b1c97d595516f45794528a807ad8": {
2110 | id: "stasis-eurs"
2111 | },
2112 | "0x0bc61dded5f6710c637cf8288eb6058766ce1921": {
2113 | id: "coinsuper-ecosystem-network"
2114 | },
2115 | "0xc98e0639c6d2ec037a615341c369666b110e80e5": {
2116 | id: "ethereum-monero"
2117 | },
2118 | "0xebc7cd2684dd96619841c7994343c5a8bda94b10": {
2119 | id: "kwhcoin"
2120 | },
2121 | "0x8d5682941ce456900b12d47ac06a88b47c764ce1": {
2122 | id: "rightmesh"
2123 | },
2124 | "0x4a6058666cf1057eac3cd3a5a614620547559fc9": {
2125 | id: "brickblock"
2126 | },
2127 | "0x5d48f293baed247a2d0189058ba37aa238bd4725": {
2128 | id: "neurochain"
2129 | },
2130 | "0x554ffc77f4251a9fb3c0e3590a6a205f8d4e067d": {
2131 | id: "zmine"
2132 | },
2133 | "0x2cc114bbe7b551d62b15c465c7bdcccd9125b182": {
2134 | id: "idol-coin"
2135 | },
2136 | "0x34364bee11607b1963d66bca665fde93fca666a8": {
2137 | id: "you-coin"
2138 | },
2139 | "0x4212fea9fec90236ecc51e41e2096b16ceb84555": {
2140 | id: "six-domain-chain"
2141 | },
2142 | "0xfb8bf095ebcdad57d2e37573a505e7d3bafdd3cc": {
2143 | id: "dipnet"
2144 | },
2145 | "0xfc44ec51c80e35a87bc2140299b1636ec83dfb04": {
2146 | id: "volt"
2147 | },
2148 | "0xff2b3353c3015e9f1fbf95b9bda23f58aa7ce007": {
2149 | id: "bitscreener-token"
2150 | },
2151 | "0x5e8f855966d638135a968861e80dda722291b06d": {
2152 | id: "coinvest"
2153 | },
2154 | "0x0e69d0a2bbb30abcb7e5cfea0e4fde19c00a8d47": {
2155 | id: "carlive-chain"
2156 | },
2157 | "0x0223fc70574214f65813fe336d870ac47e147fae": {
2158 | id: "cononchain"
2159 | },
2160 | "0xe1aee98495365fc179699c1bb3e761fa716bee62": {
2161 | id: "bezant"
2162 | },
2163 | "0xdb8646f5b487b5dd979fac618350e85018f557d4": {
2164 | id: "bitcoin-token"
2165 | },
2166 | "0xee74110fb5a1007b06282e0de5d73a61bf41d9cd": {
2167 | id: "bhpcash"
2168 | },
2169 | "0x540e5fff293f523acd26291b5bc7ac5713991feb": {
2170 | id: "pitiscoin"
2171 | },
2172 | "0xc7c03b8a3fc5719066e185ea616e87b88eba44a3": {
2173 | id: "eligma-token"
2174 | },
2175 | "0x31f3d9d1bece0c033ff78fa6da60a6048f3e13c5": {
2176 | id: "ebcoin"
2177 | },
2178 | "0x18f5b4908e8861e3114ba9a0a9a4e84c5f180cc0": {
2179 | id: "esports-token"
2180 | },
2181 | "0x4618519de4c304f3444ffa7f812dddc2971cc688": {
2182 | id: "kind-ads-token"
2183 | },
2184 | "0xa984a92731c088f1ea4d53b71a2565a399f7d8d5": {
2185 | id: "intermational-crypto-x"
2186 | },
2187 | "0x840fe75abfadc0f2d54037829571b2782e919ce4": {
2188 | id: "webcoin"
2189 | },
2190 | "0xb4d0fdfc8497aef97d3c2892ae682ee06064a2bc": {
2191 | id: "formosa"
2192 | },
2193 | "0xda80b20038bdf968c7307bb5907a469482cf6251": {
2194 | id: "brokernekonetwork"
2195 | },
2196 | "0xa31108e5bab5494560db34c95492658af239357c": {
2197 | id: "dacsee"
2198 | },
2199 | "0x37e1160184f7dd29f00b78c050bf13224780b0b0": {
2200 | id: "yuan-chain-coin"
2201 | },
2202 | "0x1014613e2b3cbc4d575054d4982e580d9b99d7b1": {
2203 | id: "bitcapitalvendor"
2204 | },
2205 | "0x9c794f933b4dd8b49031a79b0f924d68bef43992": {
2206 | id: "xtrd"
2207 | },
2208 | "0x05984006707585f66465e8a6505341f46b64fa7a": {
2209 | id: "nam-coin"
2210 | },
2211 | "0xbc46d9961a3932f7d6b64abfdec80c1816c4b835": {
2212 | id: "litex"
2213 | },
2214 | "0x9972a0f24194447e73a7e8b6cd26a52e02ddfad5": {
2215 | id: "thore-cash"
2216 | },
2217 | "0x02e3083a51e8632e571fbd6a62ac396c10c653ba": {
2218 | id: "eplus-coin"
2219 | },
2220 | "0x910dfc18d6ea3d6a7124a6f8b5458f281060fa4c": {
2221 | id: "x8x-token"
2222 | },
2223 | "0x171d750d42d661b62c277a6b486adb82348c3eca": {
2224 | id: "omnitude"
2225 | },
2226 | "0xfa456cf55250a839088b27ee32a424d7dacb54ff": {
2227 | id: "blocktrade"
2228 | },
2229 | "0xc9859fccc876e6b4b3c749c5d29ea04f48acb74f": {
2230 | id: "ino-coin"
2231 | },
2232 | "0xff5c25d2f40b47c4a37f989de933e26562ef0ac0": {
2233 | id: "kora-network-token"
2234 | },
2235 | "0xf1ca9cb74685755965c7458528a36934df52a3ef": {
2236 | id: "avinoc"
2237 | },
2238 | "0x20f7a3ddf244dc9299975b4da1c39f8d5d75f05a": {
2239 | id: "sapien"
2240 | },
2241 | "0x9f195617fa8fbad9540c5d113a99a0a0172aaedc": {
2242 | id: "niobium-coin"
2243 | },
2244 | "0x153ed9cc1b792979d2bde0bbf45cc2a7e436a5f9": {
2245 | id: "xovbank"
2246 | },
2247 | "0xf6276830c265a779a2225b9d2fcbab790cbeb92b": {
2248 | id: "xceltoken"
2249 | },
2250 | "0x567287d4f42086beab4b36de9af21c70adec6760": {
2251 | id: "latino-token"
2252 | },
2253 | "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a": {
2254 | id: "igtoken"
2255 | },
2256 | "0x6aedbf8dff31437220df351950ba2a3362168d1b": {
2257 | id: "dragonglass"
2258 | },
2259 | "0x60c68a87be1e8a84144b543aacfa77199cd3d024": {
2260 | id: "themis"
2261 | },
2262 | "0x74fd51a98a4a1ecbef8cc43be801cce630e260bd": {
2263 | id: "siacashcoin"
2264 | },
2265 | "0x72430a612adc007c50e3b6946dbb1bb0fd3101d1": {
2266 | id: "thingschain"
2267 | },
2268 | "0x054c64741dbafdc19784505494029823d89c3b13": {
2269 | id: "external-token"
2270 | },
2271 | "0x170b275ced089fffaebfe927f445a350ed9160dc": {
2272 | id: "owndata"
2273 | },
2274 | "0x076a93a40bf9e0d21d3f75dd1e0584ddbe0f9d1a": {
2275 | id: "qurito"
2276 | },
2277 | "0x3c4bea627039f0b7e7d21e34bb9c9fe962977518": {
2278 | id: "ubique-chain-of-things"
2279 | },
2280 | "0x17aa18a4b64a55abed7fa543f2ba4e91f2dce482": {
2281 | id: "insight-chain"
2282 | },
2283 | "0xe530441f4f73bdb6dc2fa5af7c3fc5fd551ec838": {
2284 | id: "gsenetwork"
2285 | },
2286 | "0xfa75b65e52a6cbc5503f45f4abba2c5df4688875": {
2287 | id: "swytch-energy-token"
2288 | },
2289 | "0x4b317864a05c91225ab8f401ec7be0aeb87e9c12": {
2290 | id: "bingocoin"
2291 | },
2292 | "0x29536b7ca7029b5cddeb03c0451715615aca35ba": {
2293 | id: "newstoken"
2294 | },
2295 | "0x4c383bdcae52a6e1cb810c76c70d6f31a249ec9b": {
2296 | id: "rusgas"
2297 | },
2298 | "0x851017523ae205adc9195e7f97d029f4cfe7794c": {
2299 | id: "social-lending-token"
2300 | },
2301 | "0x1e26b3d07e57f453cae30f7ddd2f945f5bf3ef33": {
2302 | id: "clearcoin"
2303 | },
2304 | "0x2c594e1cb006e86c3879b1d8191a8b059af52be7": {
2305 | id: "excaliburcoin"
2306 | },
2307 | "0xc16b542ff490e01fcc0dc58a60e1efdc3e357ca6": {
2308 | id: "ice-rock-mining"
2309 | },
2310 | "0xc05d14442a510de4d3d71a3d316585aa0ce32b50": {
2311 | id: "lina"
2312 | },
2313 | "0x87f5e8c3425218837f3cb67db941af0c01323e56": {
2314 | id: "bitcoin-one"
2315 | },
2316 | "0x66bad545596fb17a0b4ebdc003a85def10e8f6ae": {
2317 | id: "wiki-token"
2318 | },
2319 | "0x245ef47d4d0505ecf3ac463f4d81f41ade8f1fd1": {
2320 | id: "nuggets"
2321 | },
2322 | "0x2bdbf15d055899a767f5459a151bed15fb8fd2f6": {
2323 | id: "ultra-salescoud"
2324 | },
2325 | "0x832904863978b94802123106e6eb491bdf0df928": {
2326 | id: "optitoken"
2327 | },
2328 | "0xbb1fa4fdeb3459733bf67ebc6f893003fa976a82": {
2329 | id: "bitnation"
2330 | },
2331 | "0x6a750d255416483bec1a31ca7050c6dac4263b57": {
2332 | id: "maximine-coin/"
2333 | }
2334 | }
--------------------------------------------------------------------------------
/src/controllers/AppCheck.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from "express";
2 | import { sendJSONresponse } from "../common/Utils";
3 |
4 | export class AppCheck {
5 | public android(req: Request, res: Response) {
6 | const version = "1.6.148"
7 | const build = 323
8 | sendJSONresponse(res, 200, {
9 | "latestVersion": version,
10 | "latestVersionCode": build,
11 | "url": "https://files.trustwalletapp.com/builds/latest_release.apk",
12 | "releaseNotes": [
13 | "- Support for VeChain and Wanchain",
14 | "- Bugs fixes and perfomance improvements",
15 | ],
16 | "title": "Update Available",
17 | "description": "A new version of Trust Wallet is available. Please update to version " + version,
18 | "force": false
19 | }
20 | )
21 | }
22 |
23 | public ios(req: Request, res: Response) {
24 | const version = "1.66.0"
25 | const build = 252
26 | sendJSONresponse(res, 200, {
27 | "latestVersion": version,
28 | "latestVersionCode": build,
29 | "url": "https://itunes.apple.com/us/app/trust-ethereum-wallet/id1288339409?mt=8",
30 | "title": "Update Available",
31 | "description": "A new version of Trust Wallet is available. Please update to version " + version,
32 | "force": false
33 | },
34 | )
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/controllers/Collectibles/CollectiblesController.ts:
--------------------------------------------------------------------------------
1 | import * as BluebirbPromise from "bluebird"
2 | import axios from "axios"
3 |
4 | import { Nodes, CoinTypeIndex, Endpoints, ERCStandarts } from "../../controllers/Interfaces/Servers"
5 | import { Request, Response } from "express"
6 |
7 |
8 | export class Collectibles {
9 | public getCollectibles = async (req: Request, res: Response) => {
10 | try {
11 | const json = {docs: []}
12 | const supportedNetworks = Object.keys(CoinTypeIndex)
13 | const bodyNetworks = Object.keys(req.body)
14 | const commonNetworks = this.getCommonNetworks(supportedNetworks, bodyNetworks)
15 |
16 | await BluebirbPromise.map(commonNetworks, async (networkIndex) => {
17 | const networkId: string = CoinTypeIndex[networkIndex]
18 | const addresses: string[] = req.body[networkIndex]
19 | const url: string = `${Nodes[networkId]}${Endpoints.Collectibles}`
20 |
21 | await BluebirbPromise.map(addresses, async (address) => {
22 | const collectibles: any = await this.getAddressCollectibles({url, params: {address: address.toLowerCase()}})
23 | if (Array.isArray(collectibles)) {
24 | collectibles.forEach(collectible => {
25 | json.docs.push(Object.assign(collectible, {
26 | coin: parseInt(networkIndex),
27 | type: ERCStandarts.ERC721
28 | }))
29 | })
30 | }
31 | })
32 | })
33 | this.sendJSONresponse(res, 200, json)
34 | } catch (error) {
35 | this.sendJSONresponse(res, 400, {error: "Error getting collectibles"})
36 | }
37 |
38 | }
39 |
40 | public getCommonNetworks = (arr1: string[], arr2: string[]): string[] => {
41 | return [arr1, arr2].shift().filter(v => [arr1, arr2].every(a => a.indexOf(v) !== -1))
42 | }
43 |
44 | public getAddressCollectibles = (args) => {
45 | const {url, params } = args
46 | console.log({url})
47 | console.log({params})
48 | return axios({url, params}).then(res => res.data.docs ? res.data.docs : res.data)
49 | }
50 |
51 | private sendJSONresponse(res: Response, status: number, content: any) {
52 | return res.status(status).json(content)
53 | }
54 | }
--------------------------------------------------------------------------------
/src/controllers/DAppsController.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from "express";
2 | import { DApp } from "../models/DAppModel";
3 | import { DAppCategory } from "../models/DAppCategory";
4 | import * as xss from "xss-filters";
5 | import { sendJSONresponse } from "../common/Utils";
6 |
7 | export class DAppsController {
8 |
9 | public byCategoryID(req: Request, res: Response) {
10 | const validationErrors: any = DAppsController.validateQueryParameters(req);
11 | if (validationErrors) {
12 | sendJSONresponse(res, 400, validationErrors);
13 | return;
14 | }
15 | const queryParams = DAppsController.extractQueryParameters(req);
16 | const network = parseInt(req.query.network) || 1
17 | const digitalGood = DAppsController.isDigitalGood(req)
18 | Promise.all([
19 | DAppCategory.findOne({_id: req.params.id}),
20 | DAppsController.list({
21 | category: req.params.id,
22 | networks: {$in: [network]},
23 | digitalGood: {$in: digitalGood},
24 | }, {limit: 30, sort: {createdAt: -1}})
25 | ]).then( (values) => {
26 | sendJSONresponse(res, 200, {
27 | category: values[0],
28 | docs: values[1].docs,
29 | })
30 | }).catch((err: Error) => {
31 | sendJSONresponse(res, 404, err);
32 | });
33 | }
34 |
35 | public static isDigitalGood(req: Request): boolean[] {
36 | if (req.query.os === "iOS") {
37 | return [false]
38 | }
39 | return [true, false]
40 | }
41 |
42 | public static list(query: any, options: any = {}): Promise {
43 | return DApp.paginate({...query, enabled: true}, {
44 | populate: {
45 | path: "category",
46 | model: "DAppCategory"
47 | },
48 | ...options,
49 | })
50 | }
51 |
52 | public main(req: Request, res: Response) {
53 | const validationErrors: any = DAppsController.validateQueryParameters(req);
54 | if (validationErrors) {
55 | sendJSONresponse(res, 400, validationErrors);
56 | return;
57 | }
58 | const queryParams = DAppsController.extractQueryParameters(req);
59 | const network = parseInt(req.query.network) || 1
60 | const digitalGood = DAppsController.isDigitalGood(req)
61 |
62 | DAppCategory.find({}).sort({order: 1}).then((results: any) => {
63 | const promises = results.map((category: any) => {
64 | return DAppsController.getCategoryElements(category, network, digitalGood)
65 | })
66 | return Promise.all(promises).then((results) => {
67 | const filtered = results.filter((item: any) => {
68 | return item.results.length > 0
69 | });
70 | sendJSONresponse(res, 200, {docs: filtered})
71 | })
72 | }).catch((err: Error) => {
73 | sendJSONresponse(res, 404, err);
74 | });
75 | }
76 |
77 | public static getCategoryElements(category: any, network: number, digitalGood: boolean[]): Promise {
78 | return DAppsController.list({
79 | category,
80 | digitalGood: {$in: digitalGood},
81 | $or: [
82 | {networks: { $in: [network]}},
83 | {networks: [],
84 | },
85 | ] }, {sort: {createdAt: -1}, limit: category.limit}).then((results: any) => {
86 | return Promise.resolve({category, results: results.docs})
87 | }).catch((error: Error) => {
88 | return Promise.reject(error)
89 | })
90 | }
91 |
92 | private static validateQueryParameters(req: Request) {
93 | req.checkQuery("page", "Page needs to be a number").optional().isNumeric();
94 | req.checkQuery("limit", "limit needs to be a number").optional( ).isNumeric();
95 | // req.checkQuery("address", "address needs to be alphanumeric").isAlphanumeric();
96 |
97 | return req.validationErrors();
98 | }
99 |
100 | private static extractQueryParameters(req: Request) {
101 | // page parameter
102 | let page = parseInt(xss.inHTMLData(req.query.page));
103 | if (isNaN(page) || page < 1) {
104 | page = 1;
105 | }
106 |
107 | // limit parameter
108 | let limit = parseInt(xss.inHTMLData(req.query.limit));
109 | if (isNaN(limit)) {
110 | limit = 50;
111 | } else if (limit > 500) {
112 | limit = 500;
113 | } else if (limit < 1) {
114 | limit = 1;
115 | }
116 |
117 | // address parameter
118 | const address = xss.inHTMLData(req.query.address);
119 |
120 | return {
121 | address: address,
122 | page: page,
123 | limit: limit
124 | };
125 | }
126 | }
--------------------------------------------------------------------------------
/src/controllers/Interfaces/ITokenInfo.ts:
--------------------------------------------------------------------------------
1 | interface Logo {
2 | src: string;
3 | width: string;
4 | height: string;
5 | ipfs_hash: string;
6 | }
7 |
8 | interface Support {
9 | email: string;
10 | url: string;
11 | }
12 |
13 | interface Social {
14 | blog: string;
15 | chat: string;
16 | facebook: string;
17 | forum: string;
18 | github: string;
19 | gitter: string;
20 | instagram: string;
21 | linkedin: string;
22 | reddit: string;
23 | slack: string;
24 | telegram: string;
25 | twitter: string;
26 | youtube: string;
27 | }
28 |
29 | export interface ITokenInfo {
30 | symbol: string;
31 | address: string;
32 | decimals: number;
33 | name: string;
34 | ens_address: string;
35 | website: string;
36 | logo: Logo;
37 | support: Support;
38 | social: Social;
39 | }
40 |
--------------------------------------------------------------------------------
/src/controllers/Interfaces/ITokenPriceController.ts:
--------------------------------------------------------------------------------
1 | export interface IToken {
2 | contract: string;
3 | symbol: string;
4 | }
5 |
6 | export interface IPrice extends ITicker, IQuotes {
7 | }
8 |
9 | interface ITicker {
10 | id: number,
11 | name: string,
12 | symbol: string,
13 | website_slug: string
14 | rank: number,
15 | circulating_supply: number | null
16 | total_supply: number,
17 | max_supply: number | null,
18 | last_updated: number,
19 | }
20 |
21 | export interface IQuotes {
22 | quotes: {USD: ICurrencyQuote, [key: string]: ICurrencyQuote}
23 | }
24 |
25 | export interface ICurrencyQuote {
26 | market_cap: number
27 | percent_change_1h: number
28 | percent_change_24h: number
29 | percent_change_7d: number
30 | price: number
31 | volume_24h: number
32 | }
33 |
34 | export interface IPriceDB extends ITicker, ICurrencyQuote {
35 | }
36 |
37 | export interface ICoefficient {
38 | coefficient: number,
39 | currency: string,
40 | createdAt: any,
41 | updatedAt: any,
42 | }
--------------------------------------------------------------------------------
/src/controllers/Interfaces/Servers.ts:
--------------------------------------------------------------------------------
1 | export enum Nodes {
2 | ethereum = "https://api.trustwalletapp.com/",
3 | classic = "https://trust-classic.herokuapp.com/",
4 | poa = "https://trust-poa.herokuapp.com/",
5 | callisto = "https://trust-callisto.herokuapp.com/",
6 | gochain = "https://trust-gochain.herokuapp.com/",
7 | localhost = "http://localhost:8000/"
8 | }
9 |
10 | export enum Endpoints {
11 | TokensList = "tokens/list",
12 | Tokens = "tokens",
13 | Assets = "assets",
14 | Collectibles = "assets",
15 | Transactions = "transactions",
16 | TransactionId = "transactions/",
17 | RegisterDevice = "push/register",
18 | UnegisterDevice = "push/unregister"
19 | }
20 |
21 | // https://github.com/satoshilabs/slips/blob/master/slip-0044.md
22 | export enum CoinTypeIndex {
23 | ethereum = 60,
24 | classic = 61,
25 | poa = 178,
26 | callisto = 820,
27 | gochain = 6060,
28 | // localhost = 8000 // Uncomment for test pourpouse
29 | }
30 |
31 | export enum ERCStandarts {
32 | ERC20 = "ERC20",
33 | ERC721 = "ERC721",
34 | }
--------------------------------------------------------------------------------
/src/controllers/Interfaces/Ticker.ts:
--------------------------------------------------------------------------------
1 | export interface Ticker {
2 | website_slug: string;
3 | circulating_supply: number;
4 | id: number;
5 | last_updated: number;
6 | market_cap: number;
7 | name: string;
8 | percent_change_1h: number;
9 | percent_change_24h: number;
10 | percent_change_7d: number;
11 | price: number;
12 | rank: number;
13 | symbol: string;
14 | total_supply: number;
15 | volume_24h: number;
16 | }
17 |
18 | export enum Currencies {
19 | USD = "USD",
20 | }
21 |
22 | export interface TickerParams {
23 | currency: string,
24 | ids: string,
25 | page_number: string | number,
26 | page_size: string | number,
27 | sort: string
28 | }
29 |
30 | // export enum TickersSortBy {
31 | // PriceAsc = "price_asc",
32 | // PriceDesc = "price_desc",
33 | // MarketCapAsc = "market_cap_asc",
34 | // MarketCapDesc = "market_cap_desc",
35 | // RankAsc = "rank_asc",
36 | // RankDesc = "rank_desc",
37 | // Volume24HAsc = "volume_24h_asc",
38 | // Volume24HDesc = "volume_24h_desc",
39 | // }
40 |
--------------------------------------------------------------------------------
/src/controllers/RedirectController.ts:
--------------------------------------------------------------------------------
1 | import { Nodes, CoinTypeIndex, Endpoints } from "../controllers/Interfaces/Servers"
2 | import { Request, Response } from "express";
3 | import * as BluebirbPromise from "bluebird";
4 | import axios from "axios";
5 | import * as qs from "qs";
6 |
7 | export class Redirect {
8 |
9 | public getTransactions = async (req: Request, res: Response) => {
10 | const json = {docs: []}
11 | const networkId = req.params.networkId
12 | const query = this.createQuery(req.query)
13 | const url = `${Nodes[networkId]}${Endpoints.Transactions}${query}`
14 | const transactions = await this.getAddressTokens({url})
15 |
16 | if (Array.isArray(transactions)) {
17 | transactions.forEach(transaction => {
18 | transaction.coin = CoinTypeIndex[networkId]
19 | json.docs.push(transaction)
20 | })
21 | return res.json(json)
22 | }
23 | res.json(json)
24 | }
25 |
26 | public getAddressAllTokens = async (req, res) => {
27 | const json = {docs: []}
28 | const networks = Object.keys(CoinTypeIndex)
29 | const bodyNetworks = Object.keys(req.body)
30 | const commonNetworks = this.getCommonNetworks(networks, bodyNetworks)
31 |
32 | await BluebirbPromise.map(commonNetworks, async (networkIndex) => {
33 | const networkId = CoinTypeIndex[networkIndex]
34 | const addresses: string[] = req.body[networkIndex]
35 | const url = `${Nodes[networkId]}${Endpoints.Tokens}`
36 |
37 | await BluebirbPromise.map(addresses, async (address) => {
38 | const tokens: any = await this.getAddressTokens({url, params: {address: address.toLowerCase()}})
39 | if (Array.isArray(tokens)) {
40 | tokens.forEach(token => {
41 | token.contract.coin = parseInt(networkIndex)
42 | token.contract.type = "ERC20"
43 | json.docs.push(token)
44 | })
45 | }
46 | })
47 | })
48 |
49 | res.json(json)
50 | }
51 |
52 | public getTokensList = async (req, res) => {
53 | const tokens = {docs: []}
54 | const { query, networks, verified = true } = req.query
55 | const queryNetworks: string[] = networks ? networks.split(",") : networks
56 |
57 | if (!query || !queryNetworks) {
58 | return res.json(tokens)
59 | }
60 |
61 | const queryNetworksId = queryNetworks.map(net => CoinTypeIndex[net])
62 | const commonNetworks = this.getCommonNetworks(queryNetworksId, Object.keys(CoinTypeIndex))
63 |
64 | await BluebirbPromise.map(commonNetworks, async (network) => {
65 | const url: string = `${Nodes[network]}${Endpoints.TokensList}`
66 | const networkTokenList = await this.getAddressTokens({url, params: {query, verified}})
67 |
68 | if (Array.isArray(networkTokenList)) {
69 | networkTokenList.forEach(token => {
70 | token.coin = parseInt(CoinTypeIndex[network])
71 | token.type = "ERC20"
72 | tokens.docs.push(token)
73 | });
74 | }
75 | })
76 |
77 | res.json(tokens)
78 | }
79 |
80 | public register = async (req: Request, res: Response) => {
81 | const registrResults = []
82 | const {deviceID, token, type} = req.body
83 | const networks = Object.keys(req.body.networks)
84 | const commonNetworks = this.getCommonNetworks(networks, Object.keys(CoinTypeIndex))
85 |
86 | try {
87 | await BluebirbPromise.map(commonNetworks, async (network) => {
88 | const url = `${Nodes[CoinTypeIndex[network]]}${Endpoints.RegisterDevice}`
89 | const wallets = req.body.networks[network]
90 | const data = { deviceID, token, type, wallets }
91 | const registered = await axios.post(url, data).then(res => res.data)
92 | registrResults.push(registered)
93 | })
94 |
95 | this.sendJSONresponse(res, 200, registrResults)
96 | } catch (error) {
97 | console.error(`Error registering device`, error)
98 | this.sendJSONresponse(res, 400, {error: "Error regestering device"})
99 | }
100 |
101 | }
102 |
103 | public unregister = async (req: Request, res: Response) => {
104 | const unregisterResults = []
105 | const {deviceID, token, networks, type} = req.body
106 | const networksToUnregister = this.getSupportedCoinIndex()
107 |
108 | try {
109 | await BluebirbPromise.map(networksToUnregister, async (networkIndex) => {
110 | const coin = CoinTypeIndex[networkIndex]
111 | const url = `${Nodes[coin]}${Endpoints.UnegisterDevice}`
112 | const data = {deviceID, token, networks, type}
113 | const unregistered = await axios.post(url, data).then(res => res.data)
114 | unregisterResults.push(unregistered)
115 | })
116 |
117 | this.sendJSONresponse(res, 200, unregisterResults)
118 | } catch (error) {
119 | console.error(`Error registering device`, error)
120 | this.sendJSONresponse(res, 500, {error: error.toString()})
121 | }
122 | }
123 |
124 | private getSupportedCoinIndex () {
125 | const keys = Object.keys(CoinTypeIndex).filter(k => typeof CoinTypeIndex[k as any] === "number")
126 | const values = keys.map(k => CoinTypeIndex[k as any])
127 | return values;
128 | }
129 |
130 | private sendJSONresponse(res: Response, status: number, content: any) {
131 | return res.status(status).json(content)
132 | }
133 |
134 | public getCommonNetworks = (arr1: string[], arr2: string[]): string[] => {
135 | return [arr1, arr2].shift().filter(v => [arr1, arr2].every(a => a.indexOf(v) !== -1))
136 | }
137 |
138 | public getAssets = (req: Request, res: Response) => {
139 | const query = this.createQuery(req.query)
140 | const url = `${Nodes.ethereum}${Endpoints.Assets}${query}`
141 | res.redirect(url)
142 | }
143 |
144 | public createQuery = (query: any): string => {
145 | return query ? `?${qs.stringify(query)}` : ``
146 | }
147 |
148 | public getAddressTokens(args) {
149 | const {url, params } = args
150 | return axios({url, params}).then(res => res.data.docs ? res.data.docs : res.data)
151 | }
152 |
153 | }
--------------------------------------------------------------------------------
/src/controllers/TickerController.ts:
--------------------------------------------------------------------------------
1 | import * as _ from "lodash"
2 | import * as winston from "winston"
3 | import { Request, Response } from "express"
4 |
5 | import { sendJSONresponse } from "../common/Utils"
6 | import { CurrencyCoefficient } from "../models/Currency/CurrencyCoefficientModel"
7 | import { TickerModel } from "../models/Currency/TickerModel"
8 |
9 | import { Ticker, Currencies } from "./Interfaces/Ticker"
10 | import { ICoefficient } from "./Interfaces/ITokenPriceController"
11 |
12 | export class Tickers {
13 | private tickers: Ticker[] = []
14 | private coefficients: {[key: string]: number} = {}
15 | private defaultPageNumber: number = 1
16 | private defaultPegeSize: number = 50
17 | private mappedTickersById: {[key: string]: Ticker} = {}
18 | private mappedtickersByRank: {[key: string]: Ticker} = {}
19 |
20 | public getTickers = async (req: Request, res: Response) => {
21 | try {
22 | const query = req.query,
23 | currency = query.currency ? query.currency : Currencies.USD,
24 | ids = query.ids,
25 | page_number = query.page_number ? parseInt(query.page_number) : this.defaultPageNumber,
26 | page_size = query.page_size ? parseInt(query.page_size) : this.defaultPegeSize
27 |
28 | let coefficient = 1
29 |
30 | if (this.tickers.length == 0) {
31 | await this.loadTickers()
32 | await this.loadCoefficients()
33 | this.mapTickersById()
34 | this.mapTickersByRank()
35 | }
36 |
37 | if (this.coefficients.hasOwnProperty(currency)) {
38 | coefficient = this.coefficients[currency]
39 | }
40 |
41 | if (ids) {
42 | const idsContainer: Ticker[] = []
43 | const idsArray: string[] = ids.split(",")
44 | idsArray.forEach(id => {
45 | if (this.mappedTickersById.hasOwnProperty(id)) {
46 | idsContainer.push(_.cloneDeep(this.mappedTickersById[id]))
47 | }
48 | })
49 |
50 | const convertedToCurrency = idsContainer.map((ticker: Ticker) => this.convertToCurrency(ticker, coefficient))
51 |
52 | return sendJSONresponse(res, 200, {
53 | status: true,
54 | currency,
55 | docs: convertedToCurrency
56 | })
57 | }
58 | const paginateTickers: Ticker[] = this.paginate(page_number, page_size)
59 | const finalTicker = paginateTickers.map((ticker: Ticker) => this.convertToCurrency(ticker, coefficient))
60 |
61 | sendJSONresponse(res, 200, {
62 | status: true,
63 | currency,
64 | docs: finalTicker,
65 | })
66 | } catch (error) {
67 | sendJSONresponse(res, 500, {
68 | status: false,
69 | error
70 | })
71 | }
72 |
73 | }
74 |
75 | public paginate = (page_number: number, page_size: number): Ticker[] => {
76 | const paginated = []
77 | --page_number
78 | for (let i = page_number * page_size + 1; i <= (page_number + 1) * page_size; i++) {
79 | if (this.mappedtickersByRank.hasOwnProperty(i)) {
80 | const ticker = _.cloneDeep(this.mappedtickersByRank[i])
81 | paginated.push(ticker)
82 | }
83 | }
84 | return paginated
85 | }
86 |
87 | public convertToCurrency = (ticker: Ticker, coefficient: number): Ticker => {
88 | console.log({coefficient})
89 | ticker.market_cap = ticker.market_cap / coefficient
90 | ticker.volume_24h = ticker.volume_24h / coefficient
91 | ticker.price = ticker.price / coefficient
92 | ticker.total_supply = ticker.total_supply / coefficient
93 | ticker.circulating_supply = ticker.circulating_supply / coefficient
94 | return ticker
95 | }
96 |
97 | // public slipIdToHex(coinSlip44Index: number): string {
98 | // const hexString: string = coinSlip44Index.toString(16)
99 | // const id: string = `0`.repeat(40 - hexString.length)
100 | // return `0x${id}${hexString}`
101 | // }
102 |
103 | public loadTickers = async () => {
104 | try {
105 | this.tickers = await TickerModel.find({}).select("-_id")
106 | } catch (error) {
107 | winston.error(`Failed to load tickers from DB`, error)
108 | }
109 | }
110 |
111 | public loadCoefficients = async () => {
112 | try {
113 | const coefficietns: ICoefficient[] = await CurrencyCoefficient.find({})
114 |
115 | coefficietns.forEach(coef => {
116 | this.coefficients[coef.currency] = coef.coefficient
117 | })
118 | } catch (error) {
119 | winston.error(`Failed to load coefficients from DB`, error)
120 | }
121 | }
122 |
123 | public mapTickersById = () => {
124 | this.tickers.map(ticker => {
125 | this.mappedTickersById[ticker.id] = _.cloneDeep(ticker)
126 | })
127 | }
128 |
129 | public mapTickersByRank = () => {
130 | for (const key in this.mappedTickersById) {
131 | if (this.mappedTickersById.hasOwnProperty(key)) {
132 | const ticker = _.cloneDeep(this.mappedTickersById[key])
133 | this.mappedtickersByRank[ticker.rank] = ticker
134 | }
135 | }
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/src/controllers/TokenInfo.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from "express"
2 | import { sendJSONresponse } from "../common/Utils"
3 | import * as winston from "winston";
4 | import Axios from "axios";
5 | import { validationResult } from "express-validator/check"
6 | import { ITokenInfo } from "./Interfaces/ITokenInfo";
7 | import { constants } from "http2";
8 |
9 | export class TokenInfo {
10 | private tokensInfo: {[key: string]: {[key: string]: ITokenInfo[]}} = {}
11 | private supportedNetworks: {[key: string]: string} = {
12 | "ethereum": "eth",
13 | "ropsten": "rop",
14 | "rinkeby": "rin",
15 | "kovan": "kov",
16 | }
17 |
18 | public getTokenInfo = async (req: Request, res: Response) => {
19 | try {
20 | const validationErrors = this.validateQueryParameters(req)
21 |
22 | if (validationErrors) {
23 | return sendJSONresponse(res, 400, validationErrors)
24 | }
25 | const address: string = req.params.address
26 | const network: string = req.params.networkid
27 | const networkAbbriviation: string = this.supportedNetworks[network]
28 |
29 | if (!this.tokensInfo.hasOwnProperty(networkAbbriviation)) {
30 | await this.getTokens(network)
31 | }
32 |
33 | const addressInfo = this.tokensInfo[networkAbbriviation][address.toLowerCase()]
34 |
35 | if (addressInfo) {
36 | sendJSONresponse(res, 200, {
37 | status: true,
38 | response: addressInfo
39 | })
40 | } else {
41 | throw `No info avalible for address ${address}`
42 | }
43 | } catch (error) {
44 | sendJSONresponse(res, 500, {
45 | status: true,
46 | error
47 | })
48 | }
49 | }
50 |
51 | public getTokens = (network: string) => {
52 | try {
53 | const networkAbbriviation: string = this.supportedNetworks[network]
54 |
55 | return new Promise(async (resolve) => {
56 | const tokens = await Axios.get(`https://raw.githubusercontent.com/MyEtherWallet/ethereum-lists/master/tokens/tokens-${networkAbbriviation}.json`)
57 |
58 | const networkTokens = tokens.data.reduce((acc, val) => {
59 | const tokenObj: {[key: string]: ITokenInfo} = {}
60 | tokenObj[val.address.toLowerCase()] = val
61 | Object.assign(acc, tokenObj)
62 | return acc
63 | }, {})
64 |
65 | Object.assign(this.tokensInfo, {[networkAbbriviation]: networkTokens})
66 | winston.info(`Tokens info loaded`)
67 | resolve()
68 | })
69 | } catch (error) {
70 | winston.error(`Error fetching tokens`, error)
71 | Promise.reject(error)
72 | }
73 | }
74 |
75 | private validateQueryParameters(req: Request) {
76 | req.checkParams("address", "Must be 42 characters long").isLength({max: 42, min: 42}).isAlphanumeric().optional()
77 | // req.checkQuery("network", `Suppoted networks ${this.supportedNetworks}`).isIn(this.supportedNetworks)
78 |
79 | return req.validationErrors();
80 | }
81 | }
--------------------------------------------------------------------------------
/src/controllers/TokenPriceController.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from "express";
2 | import { sendJSONresponse } from "../common/Utils";
3 | import * as winston from "winston";
4 | import * as BluebirbPromise from "bluebird";
5 | import { IToken, IPrice, IPriceDB, ICoefficient } from "./Interfaces/ITokenPriceController";
6 | import { TickerModel } from "../models/Currency/TickerModel"
7 | import { CurrencyCoefficient } from "../models/Currency/CurrencyCoefficientModel"
8 | import { contracts } from "../common/tokens/contracts";
9 | import { setDelay } from "../common/Utils"
10 |
11 | const CoinMarketCap = require("coinmarketcap-api");
12 |
13 | export class TokenPriceController {
14 | private coimarket = new CoinMarketCap();
15 | private refreshLimit: number = 600 // seconds
16 | private updateFrequency = 300000 // milliseconds
17 | private lastestCoefficients: {[key: string]: number} = {}
18 | private coefficientUpdated = <{[key: string]: number}>{}
19 | private latestUSDPrices: IPriceDB[] = []
20 | private isUpdating: {[key: string]: boolean} = {}
21 | private githubImageURL: string = "https://raw.githubusercontent.com/TrustWallet/tokens/master/images/";
22 |
23 | constructor() {
24 | this.initialize()
25 | }
26 |
27 | getTokenPrices = async (req: Request, res: Response) => {
28 | const supportedCurrency: string[] = ["AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", "RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD"]
29 | const currency: string = supportedCurrency.indexOf(req.body.currency.toUpperCase()) == -1 ? "USD" : req.body.currency.toUpperCase();
30 | const tokens = req.body.tokens;
31 |
32 | try {
33 | const prices = await this.getPrices(currency)
34 | const filtered = this.filterTokenPrices(prices, tokens)
35 | const obj = {
36 | status: true,
37 | response: filtered
38 | }
39 |
40 | if (req.originalUrl === "/prices") {
41 | delete obj.response
42 | obj["docs"] = filtered
43 | }
44 |
45 | sendJSONresponse(res, 200, obj)
46 | } catch (error) {
47 | winston.error(`Failed to get prices for ${currency}`, error)
48 |
49 | sendJSONresponse(res, 500, {
50 | status: 500,
51 | error
52 | })
53 | }
54 | }
55 |
56 | private async initialize() {
57 | try {
58 | await this.loadUSDPrice()
59 | await this.loadCoefficientsFromDB()
60 | this.usdUpdater()
61 | this.coefficientUpdater()
62 | } catch (error) {
63 | winston.error(`Error initializing`, error)
64 | }
65 | }
66 |
67 | private async loadUSDPrice() {
68 | try {
69 | const usdPrices = await TickerModel.find({})
70 |
71 | if (usdPrices.length > 0) {
72 | winston.info(`Getting price from db`)
73 | this.latestUSDPrices = usdPrices
74 | this.coefficientUpdated.USD = Date.now()
75 | return Promise.resolve()
76 | } else {
77 | winston.info(`No prices founded in DB, getting latest prices from CM`)
78 | await this.updateUSDPrices()
79 | return Promise.resolve()
80 | }
81 | } catch (error) {
82 | winston.error(`Error updating USD prices`, error)
83 | Promise.reject(error)
84 | }
85 | }
86 |
87 | private async loadCoefficientsFromDB() {
88 | try {
89 | winston.info(`Loading coefficients from DB`)
90 |
91 | const coefficietns: ICoefficient[] = await CurrencyCoefficient.find({})
92 |
93 | coefficietns.forEach(coef => {
94 | this.lastestCoefficients[coef.currency] = coef.coefficient
95 | this.coefficientUpdated[coef.currency] = Date.now()
96 | });
97 | winston.info(`Coefficients updated`)
98 | return Promise.resolve()
99 | } catch (error) {
100 | winston.info(`Error loading coefficients from DB`)
101 | Promise.reject(error)
102 | }
103 | }
104 |
105 | private async usdUpdater() {
106 | try {
107 | if (!this.isUSDUpdated()) {
108 | winston.info(`USD prices outdated, updating ...`)
109 | await this.updateUSDPrices()
110 | winston.info(`USD prices up to date`)
111 | }
112 | await setDelay(this.updateFrequency)
113 | this.usdUpdater()
114 | } catch (error) {
115 | winston.error(`Error checking is usd up to date, restartting in ${this.updateFrequency}`, error)
116 | await setDelay(5000)
117 | }
118 | }
119 |
120 | private async coefficientUpdater() {
121 | try {
122 | for (const currency in this.coefficientUpdated) {
123 | if (this.coefficientUpdated.hasOwnProperty(currency)) {
124 | if (!this.isCoefficientUpdated(currency)) {
125 | console.log(`Coefficient for ${currency} not updated, updating ....`)
126 | this.updateCoefficient(currency)
127 | }
128 | }
129 | }
130 | winston.info(`Coefficients up to date`)
131 | await setDelay(this.updateFrequency)
132 | this.coefficientUpdater()
133 | } catch (error) {
134 | winston.error(`Error checking is coefficients up to date, restartting in ${this.updateFrequency}`, error)
135 | await setDelay(5000)
136 | }
137 | }
138 |
139 | private filterTokenPrices(prices: any[], tokens: IToken[]): any {
140 | const coefficient: number = prices[1]
141 | const altContract: string = "0x0000000000000000000000000000000000000000"; // ETH, EHC, POA, CLO
142 | const pricesMap: IPriceDB[] = prices[0].reduce((map: any, ticker: any) => {
143 | map[ticker["website_slug"]] = ticker;
144 | return map;
145 | }, {});
146 |
147 | const altValues = {
148 | "ETH": "ethereum",
149 | "ETC": "ethereum-classic",
150 | "POA": "poa-network",
151 | "CLO": "callisto-network",
152 | "GO" : "gochain"
153 | }
154 |
155 | return tokens.map((token: IToken) => {
156 | const contract: string = token.contract.toLowerCase()
157 | const symbol: string = token.symbol.toUpperCase()
158 |
159 | if (contract === altContract && altValues.hasOwnProperty(symbol)) {
160 | const slug = altValues[token.symbol];
161 | const tokenPrice: IPriceDB = pricesMap[slug];
162 | const price: string = tokenPrice.price ? (tokenPrice.price / coefficient).toString() : "0"
163 | const percent_change_24h: string = tokenPrice.percent_change_24h ? (tokenPrice.percent_change_24h).toString() : "0"
164 |
165 | return {
166 | id: tokenPrice["website_slug"],
167 | name: tokenPrice.name,
168 | symbol,
169 | price,
170 | percent_change_24h,
171 | contract,
172 | image: this.getImageUrl(token.contract),
173 | }
174 | } else if (contracts.hasOwnProperty(contract)) {
175 | const slug: string = contracts[contract].id;
176 | const tokenPrice: any = pricesMap[slug] || {};
177 | const price: string = tokenPrice.price ? (tokenPrice.price / coefficient).toString() : "0"
178 | const percent_change_24h: string = tokenPrice.percent_change_24h ? (tokenPrice.percent_change_24h).toString() : "0"
179 |
180 | return {
181 | id: tokenPrice["website_slug"] || "",
182 | name: tokenPrice.name || "",
183 | symbol: token.symbol || "",
184 | price,
185 | percent_change_24h,
186 | contract,
187 | image: this.getImageUrl(contract),
188 | }
189 | } else {
190 | return {
191 | id: "",
192 | name: "",
193 | symbol,
194 | price: "0",
195 | percent_change_24h: "0",
196 | contract,
197 | image: this.getImageUrl(contract),
198 | }
199 | }
200 | })
201 | }
202 |
203 | private async bulkUpdateUSD(prices: IPrice[]) {
204 | try {
205 | const bulkOps = prices.map(price => {
206 | const quote = price.quotes.USD
207 | return {
208 | updateOne: {
209 | filter: { website_slug: price.website_slug },
210 | update: {
211 | id: price.id,
212 | name: price.name,
213 | symbol: price.symbol,
214 | website_slug: price.website_slug,
215 | rank: price.rank,
216 | circulating_supply: price.circulating_supply,
217 | total_supply: price.total_supply,
218 | price: quote.price,
219 | volume_24h: quote.volume_24h,
220 | market_cap: quote.market_cap,
221 | percent_change_1h: quote.percent_change_1h,
222 | percent_change_24h: quote.percent_change_24h,
223 | percent_change_7d: quote.percent_change_7d,
224 | last_updated: price.last_updated
225 | },
226 | upsert: true,
227 | }
228 | }
229 | })
230 |
231 | return await TickerModel.bulkWrite(bulkOps)
232 |
233 | } catch (error) {
234 | winston.error(`Error bulk prices update`, error)
235 | }
236 | }
237 |
238 | private async updateCurrencyCoeffiientInDB(currency: string, coefficient: number) {
239 | return await CurrencyCoefficient.findOneAndUpdate({currency}, {coefficient}, {upsert: true, new: true})
240 | .catch((error: Error) => {
241 | winston.error(`Error updating coefficient for currency ${currency}`, error)
242 | })
243 | }
244 |
245 | private getImageUrl(contract: string): string {
246 | return `${this.githubImageURL}${contract.toLowerCase()}.png`;
247 | }
248 |
249 | private async updateCoefficient(currency: string) {
250 | winston.info(`Updating coefficient for currency`, currency)
251 | try {
252 | this.isUpdating[currency] = true
253 |
254 | const coefficient: number = await this.getCoefficient(currency)
255 | await this.updateCurrencyCoeffiientInDB(currency, coefficient)
256 |
257 | this.lastestCoefficients[currency] = coefficient
258 | this.coefficientUpdated[currency] = Date.now()
259 |
260 | this.isUpdating[currency] = false
261 | winston.info(`Сoefficient updated sucessfully for currency`, currency)
262 | } catch (error) {
263 | winston.error(`Error updating coefficient for currency ${currency}`, error)
264 | Promise.reject(error)
265 | }
266 | }
267 |
268 | private isUSDUpdated(): boolean {
269 | const lastUpdatedTime: number = this.coefficientUpdated.USD || 0
270 | const difference: number = (Date.now() - lastUpdatedTime) / 1000
271 | const isUpdating: boolean = this.isUpdating.USD || false
272 | return !(difference >= this.refreshLimit) && !isUpdating
273 | }
274 |
275 | private isCoefficientUpdated(currency: string): boolean {
276 | const lastUpdatedTime: number = this.coefficientUpdated[currency] || 0
277 | const difference: number = Math.floor((lastUpdatedTime - this.coefficientUpdated.USD) / 1000)
278 | const isUpdating: boolean = this.isUpdating[currency] || false
279 | return Number.isInteger(difference) && Math.abs(difference) <= this.refreshLimit && !isUpdating
280 | }
281 |
282 | private async getPrices(currency: string): Promise<[IPriceDB[], number]> {
283 | try {
284 | if (currency === "USD" ) return [this.latestUSDPrices, 1]
285 |
286 | if (this.lastestCoefficients.hasOwnProperty(currency)) {
287 | return [this.latestUSDPrices, this.lastestCoefficients[currency]]
288 | }
289 |
290 | await this.updateCoefficient(currency)
291 | return this.getPrices(currency)
292 | } catch (error) {
293 | winston.error(`Error getPrices`, error)
294 | Promise.reject(error)
295 | }
296 | }
297 |
298 | private getAllTokensPricesInUSD() {
299 | return new BluebirbPromise((resolve, reject) => {
300 | this.coimarket.getTicker({limit: 0, structure: "array"}).then((prices: any) => {
301 | resolve(prices.data);
302 | }).catch((error: Error) => {
303 | reject(error);
304 | });
305 | });
306 | }
307 |
308 | private async getCoefficient(currency: string): Promise {
309 | try {
310 | const prices = await this.coimarket.getTicker({limit: 1, convert: currency, structure: "array"})
311 | const quotes: any = prices.data[0].quotes
312 | const coefficient: number = quotes.USD.price / quotes[currency].price
313 | return coefficient
314 | } catch (error) {
315 | Promise.reject(`Error getting coefficient for currecny "${currency}" ${error}`)
316 | }
317 | }
318 |
319 | private async updateUSDPrices() {
320 | winston.info(`Updating USD prices ... `)
321 | try {
322 | const prices: any = await this.getAllTokensPricesInUSD()
323 | await this.bulkUpdateUSD(prices)
324 | const usdPrices: IPriceDB[] = await TickerModel.find({})
325 | this.latestUSDPrices = usdPrices
326 | this.coefficientUpdated.USD = Date.now()
327 | await this.updateCurrencyCoeffiientInDB("USD", 1)
328 |
329 | winston.info(`Prices updated sucsesfully`)
330 | return Promise.resolve()
331 | } catch (error) {
332 | winston.error(`Error updating USD prices`, error)
333 | }
334 | }
335 |
336 | }
--------------------------------------------------------------------------------
/src/models/Currency/CurrencyCoefficientModel.ts:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const Schema = mongoose.Schema;
3 |
4 | const schema = new Schema({
5 | currency: {
6 | type: String,
7 | index: true,
8 | uppercase: true
9 | },
10 | coefficient: {
11 | type: Number
12 | }
13 | }, {
14 | versionKey: false,
15 | timestamps: true,
16 | })
17 |
18 | export const CurrencyCoefficient = mongoose.model("CurrencyCoefficient", schema)
--------------------------------------------------------------------------------
/src/models/Currency/TickerModel.ts:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const Schema = mongoose.Schema;
3 |
4 | const schema = new Schema({
5 | id: {
6 | type: Number,
7 | required: true
8 | },
9 | name: {
10 | type: String,
11 | required: true
12 | },
13 | symbol: {
14 | type: String,
15 | required: true
16 | },
17 | website_slug: {
18 | type: String,
19 | required: true,
20 | lowercase: true,
21 | index: true
22 | },
23 | rank: {
24 | type: Number,
25 | required: true
26 | },
27 | circulating_supply: {
28 | type: Number,
29 | required: true
30 | },
31 | total_supply: {
32 | type: Number,
33 | required: true
34 | },
35 | price: {
36 | type: Number,
37 | required: true
38 | },
39 | volume_24h: {
40 | type: Number,
41 | required: true
42 | },
43 | market_cap: {
44 | type: Number,
45 | required: true
46 | },
47 | percent_change_1h: {
48 | type: Number,
49 | required: true
50 | },
51 | percent_change_24h: {
52 | type: Number,
53 | required: true
54 | },
55 | percent_change_7d: {
56 | type: Number,
57 | required: true
58 | },
59 | last_updated: {
60 | type: Number,
61 | require: true
62 | }
63 | },
64 | {
65 | versionKey: false,
66 | timestamps: true,
67 | }
68 | )
69 |
70 | export const TickerModel = mongoose.model("Ticker", schema)
--------------------------------------------------------------------------------
/src/models/DAppCategory.ts:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const mongoosePaginate = require("mongoose-paginate");
3 | const Schema = mongoose.Schema;
4 |
5 | const scheme = new Schema({
6 | name: {
7 | type: String,
8 | },
9 | image: {
10 | type: String,
11 | },
12 | order: {
13 | type: Number,
14 | },
15 | slug: {
16 | type: String
17 | },
18 | limit: {
19 | type: Number
20 | }
21 | }, {
22 | versionKey: false,
23 | });
24 |
25 | scheme.plugin(mongoosePaginate);
26 |
27 | export const DAppCategory = mongoose.model("DAppCategory", scheme);
28 |
--------------------------------------------------------------------------------
/src/models/DAppModel.ts:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const mongoosePaginate = require("mongoose-paginate");
3 | const Schema = mongoose.Schema;
4 |
5 | const scheme = new Schema({
6 | name: {
7 | type: String,
8 | },
9 | short_description: {
10 | type: String,
11 | },
12 | long_description: {
13 | type: String,
14 | },
15 | description: {
16 | type: String,
17 | },
18 | url: {
19 | type: String,
20 | index: {
21 | unique: true
22 | }
23 | },
24 | image: {
25 | type: String,
26 | },
27 | category: [{
28 | ref: "DAppCategory",
29 | type: Schema.Types.ObjectId,
30 | index: true
31 | }],
32 | networks: [{
33 | type: Number,
34 | index: true
35 | }],
36 | enabled: {
37 | type: Boolean,
38 | default: false
39 | },
40 | digitalGood: {
41 | type: Boolean,
42 | default: false
43 | }
44 | }, {
45 | versionKey: false,
46 | timestamps: true,
47 | });
48 |
49 | scheme.options.toJSON = {
50 | transform: (doc: any, ret: any, options: any) => {
51 | delete ret.__v;
52 | delete ret.enabled;
53 | delete ret.createdAt;
54 | delete ret.updatedAt;
55 | return ret;
56 | }
57 | };
58 |
59 | scheme.plugin(mongoosePaginate);
60 |
61 | export const DApp = mongoose.model("DApp", scheme);
62 |
--------------------------------------------------------------------------------
/src/models/Database.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from "mongoose";
2 | import * as winston from "winston";
3 | import Bluebird = require("bluebird");
4 | (mongoose).Promise = Bluebird;
5 |
6 | export class Database {
7 |
8 | private dbURI: string;
9 |
10 | constructor(dbURI: string) {
11 | this.dbURI = dbURI;
12 | }
13 |
14 | public connect() {
15 | const options: any = {
16 | autoIndex: true,
17 | poolSize: 500,
18 | // sets how many times to try reconnecting
19 | reconnectTries: Number.MAX_VALUE,
20 | // sets the delay between every retry (milliseconds)
21 | reconnectInterval: 1000
22 | };
23 |
24 | mongoose.connect(this.dbURI, options)
25 | .then(() => {
26 | this.hookIntoConnectionMonitorEvents();
27 | this.setupShutdownHandlers();
28 | })
29 | .catch((err: Error) => {
30 | winston.error(`Could not connect to Mongo with error: ${err}`);
31 | });
32 | }
33 |
34 | private hookIntoConnectionMonitorEvents() {
35 | mongoose.connection.on("connected", () => {
36 | winston.info("Mongoose connected");
37 | });
38 | mongoose.connection.on("error", (err: any) => {
39 | winston.info(`Mongoose connection error: ${err}`);
40 | });
41 | mongoose.connection.on("disconnected", () => {
42 | winston.info("Mongoose disconnected");
43 | });
44 | }
45 |
46 | private setupShutdownHandlers() {
47 | // SIGUSR2 signal for nodemon shutdown
48 | process.once("SIGUSR2", () => {
49 | mongoose.connection.close(() => {
50 | winston.info("Mongoose disconnected through nodemon restart");
51 | process.kill(process.pid, "SIGUSR2");
52 | });
53 | });
54 | // SIGINT signal for regular app shutdown
55 | process.on("SIGINT", () => {
56 | mongoose.connection.close(() => {
57 | winston.info("Mongoose disconnected through app termination");
58 | process.exit(0);
59 | });
60 | });
61 | // SIGTERM signal for Heroku shutdown
62 | process.on("SIGTERM", () => {
63 | mongoose.connection.close(() => {
64 | winston.info("Mongoose disconnected through Heroku app shutdown");
65 | process.exit(0);
66 | });
67 | });
68 | }
69 |
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/src/routes/ApiRoutes.ts:
--------------------------------------------------------------------------------
1 | import * as express from "express";
2 | import path = require("path");
3 | // Controllers
4 | import { DAppsController } from "../controllers/DAppsController";
5 | import { TokenPriceController } from "../controllers/TokenPriceController";
6 | import { Redirect } from "../controllers/RedirectController";
7 | import { Tickers } from "../controllers/TickerController";
8 | import { AppCheck } from "../controllers/AppCheck";
9 | import { TokenInfo } from "../controllers/TokenInfo";
10 | import { Collectibles } from "../controllers/Collectibles/CollectiblesController";
11 |
12 | const router = express.Router();
13 |
14 | const dAppsController = new DAppsController();
15 | const priceController = new TokenPriceController();
16 | const appCheck = new AppCheck();
17 | const tokenInfo = new TokenInfo();
18 | const redirect = new Redirect()
19 | const tickers = new Tickers()
20 | const collectibles = new Collectibles()
21 |
22 | // Serve docmentation
23 | router.use("/docs", express.static(path.join(__dirname, "/../../apidoc")))
24 |
25 | router.get("/dapps/main", dAppsController.main);
26 | router.get("/dapps/category/:id", dAppsController.byCategoryID);
27 |
28 | /**
29 | * @api {post} /prices
30 | * @apiVersion 0.1.0
31 | * @apiName GetTokenPrices
32 | * @apiGroup Tokens
33 | * @apiPermission none
34 | *
35 | *
36 | *
37 | * @apiExample {curl} Example usage
38 | * curl -X POST -S -H 'Content-Type: application/json' -d '{"currency":"USD","tokens":[{"contract":"0x1d462414fe14cf489c7a21cac78509f4bf8cd7c0","symbol":"CAN"}]}' -s 'https://public.trustwalletapp.com/prices'
39 | *
40 | * @apiParam {String} currency="USD" For valid fiat currency values refer to https://coinmarketcap.com/api/. Price updates every 5 minutes.
41 | * @apiParam {Object[]} tokens Token object
42 | * @apiParam {String} tokens.contract Smart contract address
43 | * @apiParam {String} tokens.symbol Smart contract symbol
44 | *
45 | * @apiParamExample {json} Request-Example:
46 | * {
47 | * "currency": "USD",
48 | * "tokens": [
49 | * {
50 | * "contract": "0x1a0f2ab46ec630f9fd638029027b552afa64b94c",
51 | * "symbol": "PIE"
52 | * }
53 | * ]
54 | * }
55 | *
56 | * @apiSuccessExample {json} Sucess-Response:
57 | * HTTPS 200 OK
58 | * {
59 | * "status": true,
60 | * "docs": [
61 | * {
62 | * "id": "aston",
63 | * "name": "Aston",
64 | * "symbol": "PIE",
65 | * "price": "0.0312211978",
66 | * "percent_change_24h": "-9.74",
67 | * "contract": "0x1a0f2ab46ec630f9fd638029027b552afa64b94c",
68 | * "image": "https://raw.githubusercontent.com/TrustWallet/tokens/master/images/0x1a0f2ab46ec630f9fd638029027b552afa64b94c.png"
69 | * }
70 | * ]
71 | * }
72 | */
73 | router.post("/tokenPrices", priceController.getTokenPrices)
74 | router.post("/prices", priceController.getTokenPrices)
75 |
76 | router.get("/appcheck/android", appCheck.android);
77 | // Token info
78 | router.get("/tokeninfo/:networkid/:address?", tokenInfo.getTokenInfo);
79 |
80 | // Redirect routes
81 |
82 | /**
83 | * @api {get} /:networkId/transactions
84 | * @apiVersion 0.1.0
85 | * @apiName GetTransactions
86 | * @apiGroup Transactions
87 | * @apiPermission none
88 | *
89 | * @apiParam {Number} networkId Network id, supported networks are: ethereum, classic, poa, callisto
90 | *
91 | * @apiParam {String} address Address
92 | * @apiParam {Number} [startBlock=1] Block number to select transaction from
93 | * @apiParam {Number} [endBlock=9999999999] Block number to select transaction till
94 | * @apiParam {Number} [page=1] Number of page
95 | * @apiParam {Number{25..50}} [limit=25] Limit transactions per page
96 | * @apiParam {String} [contract] Select address transactions on specific contract
97 | *
98 | * @apiExample {curl} Example usage
99 | * curl -i https://public.trustwalletapp.com/ethereum/transactions?address=0x1a007089523cc763d8e7c8a2f33429b28cdae5d5
100 | *
101 | * @apiSuccessExample {json} Sucess-Response:
102 | * HTTPS 200 OK
103 | * {
104 | * "docs": [
105 | * {
106 | * "operations": [],
107 | * "contract": null,
108 | * "_id": "0xd11ed968bc6be87239ca0478c4c43c83f90fdacfe2c1090fa1627d23af3fa3f9",
109 | * "blockNumber": 6030708,
110 | * "timeStamp": "1532568764",
111 | * "nonce": 38686,
112 | * "from": "0xce85247b032f7528ba97396f7b17c76d5d034d2f",
113 | * "to": "0x1a007089523cc763d8e7c8a2f33429b28cdae5d5",
114 | * "value": "5000000000000000000",
115 | * "gas": "150000",
116 | * "gasPrice": "180000000000",
117 | * "gasUsed": "21004",
118 | * "input": "0x00",
119 | * "error": "",
120 | * "id": "0xd11ed968bc6be87239ca0478c4c43c83f90fdacfe2c1090fa1627d23af3fa3f9",
121 | * "coin": 60
122 | * }
123 | * ]
124 | * }
125 | */
126 | router.get(`/:networkId/transactions`, redirect.getTransactions)
127 |
128 |
129 | /**@api {get} /tokens/list
130 | * @apiVersion 0.1.0
131 | * @apiName GetTokensList
132 | * @apiGroup Tokens
133 | * @apiPermission none
134 | *
135 | *
136 | * @apiParam {String} query Query to match condition
137 | * @apiParam {String} networks Comma delimited list of coin index (https://github.com/satoshilabs/slips/blob/master/slip-0044.md): networks=60,61
138 | * @apiParam {Boolean=true,false} [verified=true] Return only verified (meaning listed on https://coinmarketcap.com/) ERC20 contracts. If specified `false` will return both verified and not verified contracts.
139 | *
140 | * @apiExample {curl} Example usage
141 | * curl -i https://public.trustwalletapp.com/tokens/list?query=TRX&networks=60
142 | *
143 | * @apiSuccessExample {json} Sucess-Response:
144 | * HTTPS 200 OK
145 | * {
146 | * "docs": [
147 | * {
148 | * "verified": true,
149 | * "enabled": true,
150 | * "_id": "5aa590051125720640037236",
151 | * "address": "0xf230b790e05390fc8295f4d3f60332c93bed42e2",
152 | * "symbol": "TRX",
153 | * "decimals": 6,
154 | * "totalSupply": "100000000000000000",
155 | * "name": "Tronix",
156 | * "coin": 60,
157 | * "type": "ERC20"
158 | * }
159 | * ]
160 | * }
161 | *
162 | *
163 | */
164 | router.get(`/tokens/list`, redirect.getTokensList)
165 |
166 | /**
167 | * @api {post} /tokens
168 | *
169 | * @apiVersion 0.1.0
170 | * @apiName GetTokens
171 | * @apiGroup Tokens
172 | * @apiPermission none
173 | *
174 | * @apiSampleRequest off
175 | *
176 | * @apiParam (Request body) {String[]} networkIndex Array of addresses as a string
177 | * @apiParam (Request body) {String[]} address Address
178 | *
179 | * @apiParamexample {json} Request Body Example
180 | * {
181 | * "60": ["0xac4df82fe37ea2187bc8c011a23d743b4f39019a"],
182 | * "178": ["0xf88cf13f77794f15cb48b809c1bbe467fa708807"]
183 | * }
184 | *
185 | * @apiSuccessExample {json} Sucess-Response:
186 | * HtTPS 200 OK
187 | * {
188 | * "docs": [
189 | * {
190 | * "balance": "0",
191 | * "contract": {
192 | * "contract": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd",
193 | * "address": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd",
194 | * "name": "MistCoin",
195 | * "decimals": 2,
196 | * "symbol": "MC",
197 | * "coin": 60,
198 | * "type": "ERC20"
199 | * }
200 | * },
201 | * {
202 | * "balance": "0",
203 | * "contract": {
204 | * "contract": "0x3111c94b9243a8a99d5a867e00609900e437e2c0",
205 | * "address": "0x3111c94b9243a8a99d5a867e00609900e437e2c0",
206 | * "name": "TEST",
207 | * "decimals": 18,
208 | * "symbol": "TEST",
209 | * "coin": 178,
210 | * "type": "ERC20"
211 | * }
212 | * }
213 | * ]
214 | * }
215 | *
216 | *
217 | */
218 | router.post(`/tokens`, redirect.getAddressAllTokens)
219 |
220 | /**@api {get} /assets
221 | * @apiVersion 0.1.0
222 | * @apiName GetAddressAssets
223 | * @apiGroup Assets
224 | * @apiPermission none
225 | *
226 | *
227 | * @apiParam {String} address Address
228 | *
229 | * @apiExample {curl} Example usage
230 | * curl -i https://public.trustwalletapp.com/assets?address=0xe47494379c1d48ee73454c251a6395fdd4f9eb43
231 | *
232 | * @apiSuccessExample {json} Sucess-Response:
233 | * HTTPS 200 OK
234 | * {
235 | * "docs": [
236 | * {
237 | * "name": "CryptoKitties",
238 | * "id": "0x06012c8cf97bead5deae237070f9587f8e7a266d",
239 | * "items": [
240 | * {
241 | * "token_id": "511939",
242 | * "contract_address": "0x06012c8cf97bead5deae237070f9587f8e7a266d",
243 | * "category": "CryptoKitties",
244 | * "image_url": "https://s3.us-east-2.amazonaws.com/trustwallet/0x06012c8cf97bead5deae237070f9587f8e7a266d-511939.png",
245 | * "name": "CryptoKitty #511939",
246 | * "external_link": "https://www.cryptokitties.co/kitty/511939",
247 | * "description": "Top o' the muffin to ya! I'm Kitty #511939. I've never told anyone this, but I once meowed for a dog. In my last job, I batted my paw at my manager. Needless to say I was looking for work soon after. It's pawesome to meet you!"
248 | * }
249 | * ]
250 | * }
251 | * ]
252 | * }
253 | *
254 | *
255 | */
256 | router.get(`/assets`, redirect.getAssets)
257 |
258 | /**@api {post} /collectibles
259 | * @apiVersion 0.1.0
260 | * @apiName GetCollectibles
261 | * @apiGroup Collectibles
262 | * @apiPermission none
263 | *
264 | * @apiParam (Request body) {String=60,61,178,820,6060} networkIndex Network coin index
265 | * @apiParam (Request body) {String[]} address Address
266 | *
267 | * @apiParamexample {json} Request Body Example
268 | *
269 | * {
270 | * "60": ["0xd3189563ea88bB7E038F36f6F375aAe1e6d3Eb48"]
271 | * }
272 | *
273 | * @apiSuccessExample {json} Sucess-Response:
274 | * HTTPS 200 OK
275 | * {
276 | * "docs": [
277 | * {
278 | * "name": "CryptoKitties",
279 | * "id": "0x06012c8cf97bead5deae237070f9587f8e7a266d",
280 | * "items": [
281 | * {
282 | * "token_id": "511939",
283 | * "contract_address": "0x06012c8cf97bead5deae237070f9587f8e7a266d",
284 | * "category": "CryptoKitties",
285 | * "image_url": "https://s3.us-east-2.amazonaws.com/trustwallet/0x06012c8cf97bead5deae237070f9587f8e7a266d-511939.png",
286 | * "name": "CryptoKitty #511939",
287 | * "external_link": "https://www.cryptokitties.co/kitty/511939",
288 | * "description": "Top o' the muffin to ya! I'm Kitty #511939. I've never told anyone this, but I once meowed for a dog. In my last job, I batted my paw at my manager. Needless to say I was looking for work soon after. It's pawesome to meet you!"
289 | * }
290 | * ],
291 | * "coin": 60,
292 | * "type": "ERC721"
293 | * }
294 | * ]
295 | * }
296 | *
297 | *
298 | */
299 | router.post(`/collectibles`, collectibles.getCollectibles)
300 |
301 | /**
302 | * @api {post} /notifications/register
303 | *
304 | * @apiVersion 0.1.0
305 | * @apiName RegisterDevice
306 | * @apiGroup Notifications
307 | * @apiPermission none
308 | *
309 | * @apiParam (Request body) {String} deviceID Unique device id
310 | * @apiParam (Request body) {String} token Token generated by device
311 | * @apiParam (Request body) {Object=60,61,178,820} netwoks List of key and value, where key is
312 | * coin type (https://github.com/satoshilabs/slips/blob/master/slip-0044.md), and value array
313 | * of addresses
314 | * @apiParam (Request body) {String="ios","android"} type Device type
315 | *
316 | *
317 | * @apiParamexample {json} Request Body Example for regestering iOS device
318 | * {
319 | * "deviceID": "B14BD907-324A-4A40-98A1-A255C26D2BE52",
320 | * "token": "4a47fc7f78f55e2d9932abd7bb7259364356affeaa3aa28efc73f9955e9233e2",
321 | * "networks": {
322 | * "60": ["0x33923a7888c0b885768b3ed578f4d443b17182ee"]
323 | * },
324 | * "type": "ios"
325 | * }
326 | *
327 | * @apiParamexample {json} Request Body Example for regestering Android device
328 | * {
329 | * "token": "4a47fc7f78f55e2d9932abd7bb7259364356affeaa3aa28efc73f9955e9233e2",
330 | * "networks": {
331 | * "60": ["0x33923a7888c0b885768b3ed578f4d443b17182ee"]
332 | * },
333 | * "type": "android"
334 | * }
335 | *
336 | * @apiSuccessExample {json} Sucess-Response:
337 | * HTTPS 200 OK
338 | *
339 | *
340 | *
341 | */
342 | router.post(`/notifications/register`, redirect.register)
343 |
344 | /**
345 | * @api {post} /notifications/unregister
346 | *
347 | * @apiVersion 0.1.0
348 | * @apiName UnregisterDevice
349 | * @apiGroup Notifications
350 | * @apiPermission none
351 | *
352 | * @apiParam (Request body) {String} deviceID Unique device id
353 | * @apiParam (Request body) {String} token Token generated by device
354 | * @apiParam (Request body) {String="ios","android"} type Device type
355 | * @apiParam (Request body) {Number[]} networks="[]" Array of network indexes (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
356 | * If specified empty array, unsubscribe will happen on all supported networks
357 | *
358 | * @apiParamexample {json} Request Body Example for unsubscribe iOS device
359 | * {
360 | * "deviceID": "B14BD907-324A-4A40-98A1-A255C26D2BE52",
361 | * "networks": []
362 | * }
363 | *
364 | * @apiParamexample {json} Request Body Example for unsubscribe Android device
365 | * {
366 | * "token": "4a47fc7f78f55e2d9932abd7bb7259364356affeaa3aa28efc73f9955e9233e2",
367 | * "networks": []
368 | * "type": "android"
369 | * }
370 | *
371 | * @apiSuccessExample {json} Sucess-Response:
372 | * HTTPS 200 OK
373 | *
374 | *
375 | *
376 | */
377 | router.post(`/notifications/unregister`, redirect.unregister)
378 |
379 | /**
380 | * @api {get} /tickers
381 | *
382 | * @apiVersion 0.1.0
383 | * @apiName GetTickers
384 | * @apiGroup Market
385 | * @apiPermission none
386 | *
387 | * @apiParam {String="AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", "RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD"} [currency=USD] Coin value in curreny
388 | * @apiParam {String} [ids] ids Comma separated list of coin id's exp: ids=1,3,5. If ids present page_number or/and page_size will not take affect
389 | * @apiParam {Number} [page_number=1] Return resutls starting from specified rank
390 | * @apiParam {Number} [page_size=50] Return a maximum results
391 | * @apiParam {String} [sort=rank_asc] TODO other sort criterias: price_asc, price_desc, market_cap_asc, market_cap_desc, rank_asc, volume_24h_asc, volume_24h_desc
392 | *
393 | * @apiExample {curl} Example usage
394 | * https://public.trustwalletapp.com/tickers?currency=EUR&page_number=1&page_size=3
395 | * https://public.trustwalletapp.com/tickers?ids=1,2,3
396 | *
397 | * @apiSuccessExample {json} Sucess-Response:
398 | * HTTPS 200 OK
399 | * {
400 | * "status": true,
401 | * "currency": "EUR",
402 | * "docs": [
403 | * {
404 | * "website_slug": "bitcoin",
405 | * "last_updated": 1533239327,
406 | * "percent_change_7d": -6.85,
407 | * "percent_change_24h": -0.07,
408 | * "percent_change_1h": 0.38,
409 | * "market_cap": 7109455615213.157,
410 | * "volume_24h": 247847316304.44513,
411 | * "price": 413674.14790895366,
412 | * "total_supply": 939532504.2292902,
413 | * "circulating_supply": 939532504.2292902,
414 | * "rank": 1,
415 | * "symbol": "BTC",
416 | * "name": "Bitcoin",
417 | * "id": 1
418 | * }
419 | * ]
420 | * }
421 | *
422 | */
423 |
424 | router.get(`/tickers`, tickers.getTickers)
425 |
426 | export {
427 | router
428 | };
--------------------------------------------------------------------------------
/test/App.test.ts:
--------------------------------------------------------------------------------
1 | import { App } from "../src/App";
2 | const chai = require("chai")
3 | const app = new App().app
4 | const chaiHttp = require("chai-http")
5 | chai.use(chaiHttp)
6 |
7 | describe("Docs", () => {
8 | it("Docs shoud response with status 200", () => {
9 | chai.request(app)
10 | .get("/docs")
11 | .end((err, res) => {
12 | res.should.have.status(200)
13 | })
14 | });
15 | })
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "noImplicitAny": false,
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist",
9 | "suppressImplicitAnyIndexErrors": true
10 | },
11 | "include": [
12 | "src/**/*.ts"
13 | ],
14 | "exclude": [
15 | "node_modules",
16 | "**/*.test.ts"
17 | ]
18 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "class-name": true,
4 | "comment-format": [
5 | true,
6 | "check-space"
7 | ],
8 | "indent": [
9 | true,
10 | "spaces",
11 | 4
12 | ],
13 | "one-line": [
14 | true,
15 | "check-open-brace",
16 | "check-whitespace"
17 | ],
18 | "no-var-keyword": true,
19 | "quotemark": [
20 | true,
21 | "double",
22 | "avoid-escape"
23 | ],
24 | "semicolon": [
25 | false,
26 | "always",
27 | "ignore-bound-class-methods"
28 | ],
29 | "whitespace": [
30 | true,
31 | "check-branch",
32 | "check-decl",
33 | "check-operator",
34 | "check-module",
35 | "check-separator",
36 | "check-type"
37 | ],
38 | "typedef-whitespace": [
39 | true,
40 | {
41 | "call-signature": "nospace",
42 | "index-signature": "nospace",
43 | "parameter": "nospace",
44 | "property-declaration": "nospace",
45 | "variable-declaration": "nospace"
46 | },
47 | {
48 | "call-signature": "onespace",
49 | "index-signature": "onespace",
50 | "parameter": "onespace",
51 | "property-declaration": "onespace",
52 | "variable-declaration": "onespace"
53 | }
54 | ],
55 | "no-internal-module": true,
56 | "no-trailing-whitespace": true,
57 | "no-null-keyword": false,
58 | "prefer-const": true,
59 | "jsdoc-format": true
60 | }
61 | }
--------------------------------------------------------------------------------