├── .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 | [![Greenkeeper badge](https://badges.greenkeeper.io/TrustWallet/trust-ray.svg)](https://greenkeeper.io/) 4 | 5 | [![Build Status](https://travis-ci.org/TrustWallet/trust-ray.svg?branch=master)](https://travis-ci.org/TrustWallet/trust-ray) 6 | [![License](https://img.shields.io/badge/license-GPL3-green.svg?style=flat)](https://github.com/fastlane/fastlane/blob/master/LICENSE) 7 | [![HitCount](http://hits.dwyl.io/rip32700/TrustWallet/trust-wallet-backend.svg)](http://hits.dwyl.io/rip32700/TrustWallet/trust-wallet-backend) 8 | [![Black Duck Security Risk](https://copilot.blackducksoftware.com/github/repos/TrustWallet/trust-ray/branches/token_endpoint/badge-risk.svg)](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 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](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 | } --------------------------------------------------------------------------------