├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── .yarnrc ├── LICENSE ├── README.md ├── package.json ├── serverless.yml ├── src ├── 404.ts ├── constants │ └── blacklist.ts ├── utils │ ├── computeBidsAsks.ts │ └── response.ts ├── v1 │ ├── _shared.ts │ ├── apollo │ │ ├── .graphqlconfig │ │ ├── client.ts │ │ ├── queries.ts │ │ └── schema.graphql │ ├── assets.ts │ ├── orderbook.ts │ ├── summary.ts │ ├── tickers.ts │ └── trades.ts └── v2 │ ├── _shared.ts │ ├── apollo │ ├── .graphqlconfig │ ├── client.ts │ ├── codegen.yml │ ├── queries.ts │ └── schema.graphql │ ├── assets.ts │ ├── blocks │ ├── .graphqlconfig │ ├── client.ts │ ├── queries.ts │ └── schema.graphql │ ├── generated │ └── v2-subgraph.ts │ ├── orderbook.ts │ ├── summary.ts │ ├── tickers.ts │ └── trades.ts ├── tsconfig.json ├── v1.md ├── v2.md └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | ./src/v2/generated/*.ts -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "project": "./tsconfig.json" 5 | }, 6 | "plugins": ["@typescript-eslint"], 7 | "extends": ["plugin:@typescript-eslint/recommended", "prettier", "prettier/@typescript-eslint"], 8 | "rules": { 9 | "@typescript-eslint/no-explicit-any": "off", 10 | "@typescript-eslint/camelcase": "off" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .serverless 2 | .build 3 | node_modules 4 | .env -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 120 5 | } 6 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | ignore-scripts true 2 | -------------------------------------------------------------------------------- /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 | 635 | Copyright (C) 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 | Copyright (C) 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Uniswap API 2 | 3 | The Uniswap API is a set of **authenticated** endpoints used by market aggregators (e.g. coinmarketcap.com) to surface 4 | Uniswap liquidity and volume information. All information is fetched from the underlying subgraphs. 5 | 6 | The API is designed around the CoinMarketCap 7 | [requirements document](https://docs.google.com/document/d/1S4urpzUnO2t7DmS_1dc4EL4tgnnbTObPYXvDeBnukCg). 8 | 9 | Prefer the Uniswap subgraph for any Uniswap queries whenever possible. The respective subgraphs will always have more 10 | recent data. 11 | 12 | V2 Subgraph: https://github.com/Uniswap/uniswap-v2-subgraph 13 | 14 | V1 Subgraph: https://github.com/graphprotocol/uniswap-subgraph 15 | 16 | ## Getting an API Key 17 | 18 | Please fill out [this form](https://forms.gle/4xucinVsTTPu71bT6) if you would like to get an API key. 19 | 20 | ## Using an API Key 21 | 22 | You can use an API key by setting it in the `x-api-key` header, like so: 23 | 24 | ```sh 25 | curl -v --compressed https://api.uniswap.info/v2/tickers -H 'x-api-key: abcd1234' 26 | ``` 27 | 28 | ## Segregated data 29 | 30 | Note the data returned by the V1 and V2 endpoints is segregated, i.e. there are no endpoints for combined data from 31 | both Uniswap V1 and V2. 32 | 33 | ## V1 Documentation 34 | 35 | The documentation of the `/v1/` endpoints is [here](./v1.md). 36 | 37 | ## V2 Documentation 38 | 39 | The documentation of the `/v2/` endpoints is [here](./v2.md). 40 | 41 | ## Deploying the API 42 | 43 | The API uses the [serverless framework](https://serverless.com) and can easily be deployed to any AWS account, 44 | via the `yarn sls deploy` command. 45 | 46 | In order to configure your AWS account as a target, 47 | see [the serverless docs](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/). 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@uniswap/api", 3 | "license": "GPL-3.0-or-later", 4 | "engines": { 5 | "node": "12.x" 6 | }, 7 | "dependencies": { 8 | "@ethersproject/address": "^5.0.0-beta.125", 9 | "apollo-cache-inmemory": "^1.6.2", 10 | "apollo-client": "^2.6.3", 11 | "apollo-link-http": "^1.5.15", 12 | "bignumber.js": "^9.0.0", 13 | "graphql": "^15.3.0", 14 | "graphql-tag": "^2.10.1", 15 | "node-fetch": "^2.6.0" 16 | }, 17 | "devDependencies": { 18 | "@graphql-codegen/cli": "1.15.4", 19 | "@graphql-codegen/typescript": "1.15.4", 20 | "@graphql-codegen/typescript-operations": "^1.15.4", 21 | "@types/aws-lambda": "^8.10.59", 22 | "@types/node-fetch": "^2.3.7", 23 | "@typescript-eslint/eslint-plugin": "^1.11.0", 24 | "@typescript-eslint/parser": "^1.11.0", 25 | "eslint": "^5.0.0", 26 | "eslint-config-prettier": "^6.0.0", 27 | "prettier": "^1.18.2", 28 | "serverless": "^1.75.1", 29 | "serverless-api-gateway-caching": "^1.4.1", 30 | "serverless-content-encoding": "^1.1.0", 31 | "serverless-plugin-typescript": "^1.1.9", 32 | "typescript": "^3.9.7" 33 | }, 34 | "scripts": { 35 | "lint:base": "yarn eslint ./src/**/*.ts", 36 | "format:base": "yarn prettier ./src/**/*.ts", 37 | "fix:lint": "yarn lint:base --fix", 38 | "fix:format": "yarn format:base --write", 39 | "fix:all": "yarn fix:lint && yarn fix:format", 40 | "check:lint": "yarn lint:base", 41 | "check:format": "yarn format:base --check", 42 | "check:all": "yarn check:lint && yarn check:format", 43 | "generate:v2": "graphql-codegen --config src/v2/apollo/codegen.yml", 44 | "build": "sls package" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | service: 2 | name: uniswap-api-auth 3 | 4 | frameworkVersion: ">=1.75.1 <2.0.0" 5 | 6 | provider: 7 | name: aws 8 | endpointType: REGIONAL 9 | runtime: nodejs12.x 10 | memorySize: 320 # optional, in MB, default is 1024 11 | timeout: 20 # optional, in seconds, default is 6 12 | logRetentionInDays: 1 13 | 14 | usagePlan: 15 | - low: # 5 QPS 16 | quota: 17 | limit: 500000 # 5 * 60 * 60 * 24 18 | period: DAY 19 | throttle: 20 | burstLimit: 10 21 | rateLimit: 5 22 | - medium: # 50 QPS 23 | quota: 24 | limit: 5000000 # 50 * 60 * 60 * 24 rounded up 25 | period: DAY 26 | throttle: 27 | burstLimit: 100 28 | rateLimit: 50 29 | - high: # 100 QPS 30 | quota: 31 | limit: 10000000 # 100 * 60 * 60 * 24 rounded up 32 | period: DAY 33 | throttle: 34 | burstLimit: 200 35 | rateLimit: 100 36 | 37 | custom: 38 | # Enable or disable caching globally 39 | apiGatewayCaching: 40 | enabled: true 41 | clusterSize: '0.5' # defaults to '0.5' 42 | ttlInSeconds: 300 # defaults to the maximum allowed: 3600 43 | contentEncoding: 44 | minimumCompressionSize: 0 # Minimum body size required for compression in bytes 45 | 46 | plugins: 47 | - serverless-plugin-typescript 48 | - serverless-api-gateway-caching 49 | - serverless-content-encoding 50 | 51 | functions: 52 | v1-summary: 53 | handler: src/v1/summary.handler 54 | events: 55 | - http: 56 | method: get 57 | path: /v1/summary 58 | private: true 59 | caching: 60 | enabled: true 61 | ttlInSeconds: 900 62 | 63 | v1-tickers: 64 | handler: src/v1/tickers.handler 65 | events: 66 | - http: 67 | method: get 68 | path: /v1/tickers 69 | private: true 70 | caching: 71 | enabled: true 72 | ttlInSeconds: 60 73 | 74 | v1-assets: 75 | handler: src/v1/assets.handler 76 | events: 77 | - http: 78 | method: get 79 | path: /v1/assets 80 | private: true 81 | caching: 82 | enabled: true 83 | ttlInSeconds: 3600 84 | 85 | v1-orderbook: 86 | handler: src/v1/orderbook.handler 87 | events: 88 | - http: 89 | method: get 90 | path: "/v1/orderbook/{pair}" 91 | private: true 92 | caching: 93 | enabled: true 94 | cacheKeyParameters: 95 | - name: request.path.pair 96 | ttlInSeconds: 3600 97 | 98 | 99 | v1-trades: 100 | handler: src/v1/trades.handler 101 | events: 102 | - http: 103 | method: get 104 | path: "/v1/trades/{pair}" 105 | private: true 106 | caching: 107 | enabled: true 108 | cacheKeyParameters: 109 | - name: request.path.pair 110 | ttlInSeconds: 900 111 | 112 | v2-summary: 113 | handler: src/v2/summary.handler 114 | events: 115 | - http: 116 | method: get 117 | path: /v2/summary 118 | private: true 119 | caching: 120 | enabled: true 121 | ttlInSeconds: 900 122 | 123 | v2-tickers: 124 | handler: src/v2/tickers.handler 125 | events: 126 | - http: 127 | method: get 128 | path: /v2/tickers 129 | private: true 130 | caching: 131 | enabled: true 132 | ttlInSeconds: 60 133 | 134 | v2-assets: 135 | handler: src/v2/assets.handler 136 | events: 137 | - http: 138 | method: get 139 | path: /v2/assets 140 | private: true 141 | caching: 142 | enabled: true 143 | ttlInSeconds: 3600 144 | 145 | v2-orderbook: 146 | handler: src/v2/orderbook.handler 147 | events: 148 | - http: 149 | method: get 150 | path: "/v2/orderbook/{pair}" 151 | private: true 152 | caching: 153 | enabled: true 154 | cacheKeyParameters: 155 | - name: request.path.pair 156 | ttlInSeconds: 3600 157 | 158 | v2-trades: 159 | handler: src/v2/trades.handler 160 | events: 161 | - http: 162 | method: get 163 | path: "/v2/trades/{pair}" 164 | private: true 165 | caching: 166 | enabled: true 167 | cacheKeyParameters: 168 | - name: request.path.pair 169 | ttlInSeconds: 900 170 | -------------------------------------------------------------------------------- /src/404.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | import { createErrorResponse } from './utils/response' 3 | 4 | export const handler: APIGatewayProxyHandler = async event => { 5 | return createErrorResponse(404, 'Invalid route') 6 | } 7 | -------------------------------------------------------------------------------- /src/constants/blacklist.ts: -------------------------------------------------------------------------------- 1 | // list of lowercase token addresses that are not returned from the API 2 | const BLACKLIST = [ 3 | '0xb8c77482e45f1f44de1745f52c74426c631bdd52', // BNB 4 | '0x95daaab98046846bf4b2853e23cba236fa394a31', // EMONT 5 | '0x55296f69f40ea6d20e478533c15a6b08b654e758', // XYO 6 | '0xc3761eb917cd790b30dad99f6cc5b4ff93c4f9ea', // ERC20 7 | '0x5c406d99e04b8494dc253fcc52943ef82bca7d75', // cUSD 8 | 9 | '0x5a4ade4f3e934a0885f42884f7077261c3f4f66f', // old SNX 10 | '0x42456d7084eacf4083f1140d3229471bba2949a8' // old sETH 11 | ] 12 | export default BLACKLIST 13 | -------------------------------------------------------------------------------- /src/utils/computeBidsAsks.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | 3 | function getAmountOut( 4 | amountIn: BigNumber, 5 | reservesIn: BigNumber, 6 | reservesOut: BigNumber 7 | ): { amountOut: BigNumber; reservesInAfter: BigNumber; reservesOutAfter: BigNumber } { 8 | const amountOut = amountIn.eq(0) 9 | ? new BigNumber(0) 10 | : reservesOut.minus(reservesOut.multipliedBy(reservesIn).dividedBy(reservesIn.plus(amountIn.multipliedBy(0.997)))) 11 | return { 12 | amountOut, 13 | reservesInAfter: reservesIn.plus(amountIn), 14 | reservesOutAfter: reservesOut.minus(amountOut) 15 | } 16 | } 17 | 18 | function getAmountIn( 19 | amountOut: BigNumber, 20 | reservesIn: BigNumber, 21 | reservesOut: BigNumber 22 | ): { amountIn: BigNumber; reservesInAfter: BigNumber; reservesOutAfter: BigNumber } { 23 | const amountIn = amountOut.eq(0) 24 | ? new BigNumber(0) 25 | : amountOut.isGreaterThanOrEqualTo(reservesOut) 26 | ? new BigNumber(Infinity) 27 | : reservesIn 28 | .multipliedBy(reservesOut) 29 | .dividedBy(reservesOut.minus(amountOut)) // reserves in after 30 | .minus(reservesIn) // minus reserves in 31 | .dividedBy(0.997) // fee 32 | 33 | return { 34 | amountIn, 35 | reservesInAfter: reservesIn.plus(amountIn), 36 | reservesOutAfter: reservesOut.minus(amountOut) 37 | } 38 | } 39 | 40 | export function computeBidsAsks( 41 | baseReserves: BigNumber, 42 | quoteReserves: BigNumber, 43 | numSegments: number = 200 44 | ): { bids: [string, string][]; asks: [string, string][] } { 45 | if (baseReserves.eq(0) || quoteReserves.eq(0)) { 46 | return { 47 | bids: [], 48 | asks: [] 49 | } 50 | } 51 | 52 | // we don't do exactly 100 segments because we do not care about the trade that takes exact out of entire reserves 53 | const increment = baseReserves.dividedBy(numSegments + 1) 54 | const baseAmounts = Array.from({ length: numSegments }, (x, i): BigNumber => increment.multipliedBy(i)) 55 | 56 | const bids = baseAmounts.map((buyBaseAmount): [string, string] => { 57 | const { reservesInAfter: baseReservesBefore, reservesOutAfter: quoteReservesBefore } = getAmountOut( 58 | buyBaseAmount, 59 | baseReserves, 60 | quoteReserves 61 | ) 62 | const { amountOut } = getAmountOut(increment, baseReservesBefore, quoteReservesBefore) 63 | return [increment.toString(), amountOut.dividedBy(increment).toString()] 64 | }) 65 | 66 | const asks = baseAmounts.map((sellBaseAmount): [string, string] => { 67 | const { reservesInAfter: baseReservesBefore, reservesOutAfter: quoteReservesBefore } = getAmountIn( 68 | sellBaseAmount, 69 | quoteReserves, 70 | baseReserves 71 | ) 72 | const { amountIn } = getAmountIn(increment, baseReservesBefore, quoteReservesBefore) 73 | return [increment.toString(), amountIn.dividedBy(increment).toString()] 74 | }) 75 | 76 | return { 77 | bids, 78 | asks 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/utils/response.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyResult } from 'aws-lambda' 2 | 3 | export function createResponse(statusCode: number, body: any): APIGatewayProxyResult { 4 | return { 5 | body: JSON.stringify(body), 6 | statusCode, 7 | headers: { 8 | 'content-type': 'application/json' 9 | } 10 | } 11 | } 12 | 13 | export function createSuccessResponse(body: any): APIGatewayProxyResult { 14 | return createResponse(200, body) 15 | } 16 | 17 | export function createErrorResponse(code: number, message: string): APIGatewayProxyResult { 18 | return createResponse(code, { errorCode: code, message }) 19 | } 20 | 21 | export function createBadRequestResponse(message: string = 'Bad request'): APIGatewayProxyResult { 22 | return createErrorResponse(400, message) 23 | } 24 | 25 | export function createServerErrorResponse(error: Error): APIGatewayProxyResult { 26 | return createErrorResponse(500, error.message) 27 | } 28 | -------------------------------------------------------------------------------- /src/v1/_shared.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | import BLACKLIST from '../constants/blacklist' 3 | import { getAddress } from '@ethersproject/address' 4 | import { computeBidsAsks } from '../utils/computeBidsAsks' 5 | 6 | import client from './apollo/client' 7 | import { TOP_PAIRS, TOP_PAIRS_DATA, ORDERBOOK, TRANSACTIONS } from './apollo/queries' 8 | 9 | const SECOND = 1000 10 | const MINUTE = 60 * SECOND 11 | const HOUR = 60 * MINUTE 12 | const DAY = 24 * HOUR 13 | export function get24HoursAgo(): number { 14 | return Math.floor((Date.now() - DAY) / 1000) 15 | } 16 | 17 | const TOP_PAIR_LIMIT = 100 18 | interface Pair { 19 | tokenAddress: string 20 | tokenSymbol?: string 21 | tokenName?: string 22 | exchangeAddress: string 23 | } 24 | export async function getTopPairs(): Promise { 25 | return client 26 | .query({ 27 | query: TOP_PAIRS, 28 | variables: { 29 | limit: TOP_PAIR_LIMIT 30 | } 31 | }) 32 | .then(({ data: { exchanges } }): Pair[] => 33 | exchanges 34 | .map( 35 | ({ tokenAddress, tokenSymbol, tokenName, id }: any): Pair => { 36 | const normalized = { 37 | tokenAddress: getAddress(tokenAddress), 38 | tokenSymbol, 39 | tokenName, 40 | exchangeAddress: getAddress(id) 41 | } 42 | // hard-code SAI 43 | if (normalized.tokenAddress === '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359') { 44 | normalized.tokenSymbol = 'Sai Stablecoin v1.0' 45 | normalized.tokenName = 'SAI' 46 | } 47 | return normalized 48 | } 49 | ) 50 | .filter((pair: Pair): boolean => !BLACKLIST.includes(pair.tokenAddress.toLowerCase())) 51 | ) 52 | } 53 | 54 | interface PairData { 55 | price: string 56 | tradeVolumeEth: string 57 | tradeVolumeToken: string 58 | } 59 | export async function getTopPairsData(): Promise<[Pair[], PairData[]]> { 60 | const topPairs = await getTopPairs() 61 | 62 | const _24HoursAgo = get24HoursAgo() 63 | const topPairsData = await Promise.all( 64 | topPairs.map( 65 | (pair): Promise => 66 | client 67 | .query({ 68 | query: TOP_PAIRS_DATA, 69 | variables: { 70 | exchangeAddress: pair.exchangeAddress.toLowerCase(), 71 | timestamp: _24HoursAgo 72 | } 73 | }) 74 | .then( 75 | ({ data: { exchanges, exchangeHistoricalDatas } }): PairData => { 76 | const price = exchanges[0].price 77 | 78 | const tradeVolumeEth = new BigNumber(exchanges[0].tradeVolumeEth) 79 | const tradeVolumeToken = new BigNumber(exchanges[0].tradeVolumeToken) 80 | 81 | const tradeVolumeEth24HoursAgo = new BigNumber( 82 | exchangeHistoricalDatas[0] ? exchangeHistoricalDatas[0].tradeVolumeEth : 0 83 | ) 84 | const tradeVolumeToken24HoursAgo = new BigNumber( 85 | exchangeHistoricalDatas[0] ? exchangeHistoricalDatas[0].tradeVolumeToken : 0 86 | ) 87 | 88 | return { 89 | price, 90 | tradeVolumeEth: tradeVolumeEth.minus(tradeVolumeEth24HoursAgo).toString(), 91 | tradeVolumeToken: tradeVolumeToken.minus(tradeVolumeToken24HoursAgo).toString() 92 | } 93 | } 94 | ) 95 | ) 96 | ) 97 | 98 | return [topPairs, topPairsData] 99 | } 100 | 101 | interface Orderbook { 102 | timestamp: number 103 | bids: [string, string][] 104 | asks: [string, string][] 105 | } 106 | export async function getOrderbook(exchangeAddress: string): Promise { 107 | const exchangeHistoricalData = await client 108 | .query({ 109 | query: ORDERBOOK, 110 | variables: { 111 | exchangeAddress: exchangeAddress.toLowerCase() 112 | } 113 | }) 114 | .then( 115 | ({ 116 | data: { 117 | exchangeHistoricalDatas: [exchangeHistoricalData] 118 | } 119 | }): any => exchangeHistoricalData 120 | ) 121 | 122 | return { 123 | timestamp: exchangeHistoricalData.timestamp, 124 | ...computeBidsAsks( 125 | new BigNumber(exchangeHistoricalData.ethBalance), 126 | new BigNumber(exchangeHistoricalData.tokenBalance), 127 | 20 128 | ) 129 | } 130 | } 131 | 132 | interface Trade { 133 | id: string 134 | timestamp: number 135 | type: 'buy' | 'sell' 136 | ethAmount: string 137 | tokenAmount: string 138 | price: string 139 | } 140 | export async function getTrades(exchangeAddress: string): Promise { 141 | const _24HoursAgo = get24HoursAgo() 142 | 143 | let skip = 0 144 | let results: Trade[] = [] 145 | let finished = false 146 | while (!finished) { 147 | await client 148 | .query({ 149 | query: TRANSACTIONS, 150 | variables: { 151 | skip, 152 | exchangeAddress: exchangeAddress.toLowerCase(), 153 | timestamp: _24HoursAgo 154 | } 155 | }) 156 | .then(({ data: { transactions } }): void => { 157 | if (transactions.length === 0) { 158 | finished = true 159 | } else { 160 | skip += transactions.length 161 | 162 | results = results.concat( 163 | transactions 164 | .map((transaction: any): Trade[] => [ 165 | ...transaction.ethPurchaseEvents.map( 166 | (event: any): Trade => ({ 167 | id: event.id, 168 | timestamp: transaction.timestamp, 169 | type: 'buy', 170 | ethAmount: event.ethAmount, 171 | tokenAmount: event.tokenAmount, 172 | price: new BigNumber(event.tokenAmount).dividedBy(new BigNumber(event.ethAmount)).toString() 173 | }) 174 | ), 175 | ...transaction.tokenPurchaseEvents.map( 176 | (event: any): Trade => ({ 177 | id: event.id, 178 | timestamp: transaction.timestamp, 179 | type: 'sell', 180 | ethAmount: event.ethAmount, 181 | tokenAmount: event.tokenAmount, 182 | price: new BigNumber(event.tokenAmount).dividedBy(new BigNumber(event.ethAmount)).toString() 183 | }) 184 | ) 185 | ]) 186 | .reduce((accumulator: any, trades: Trade[]): Trade[] => accumulator.concat(trades)) 187 | ) 188 | } 189 | }) 190 | } 191 | 192 | return results 193 | } 194 | -------------------------------------------------------------------------------- /src/v1/apollo/.graphqlconfig: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Uniswap V1", 3 | "schemaPath": "schema.graphql", 4 | "extensions": { 5 | "endpoints": { 6 | "Uniswap V1": { 7 | "url": "https://api.thegraph.com/subgraphs/name/graphprotocol/uniswap", 8 | "headers": { 9 | "user-agent": "JS GraphQL" 10 | }, 11 | "introspect": false 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/v1/apollo/client.ts: -------------------------------------------------------------------------------- 1 | import { ApolloClient } from 'apollo-client' 2 | import { InMemoryCache } from 'apollo-cache-inmemory' 3 | import { HttpLink } from 'apollo-link-http' 4 | import fetch from 'node-fetch' 5 | 6 | export default new ApolloClient({ 7 | link: new HttpLink({ 8 | fetch, 9 | uri: 'https://api.thegraph.com/subgraphs/name/graphprotocol/uniswap' 10 | }), 11 | cache: new InMemoryCache() 12 | }) 13 | -------------------------------------------------------------------------------- /src/v1/apollo/queries.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag' 2 | 3 | export const TOP_PAIRS = gql` 4 | query _($limit: Int!) { 5 | exchanges(first: $limit, orderBy: ethBalance, orderDirection: desc) { 6 | tokenAddress 7 | tokenSymbol 8 | tokenName 9 | id 10 | } 11 | } 12 | ` 13 | 14 | export const TOP_PAIRS_DATA = gql` 15 | query _($exchangeAddress: String!, $timestamp: Int!) { 16 | exchanges(where: { id: $exchangeAddress }) { 17 | price 18 | tradeVolumeEth 19 | tradeVolumeToken 20 | } 21 | 22 | exchangeHistoricalDatas( 23 | where: { exchangeAddress: $exchangeAddress, timestamp_lte: $timestamp } 24 | first: 1 25 | orderBy: timestamp 26 | orderDirection: desc 27 | ) { 28 | tradeVolumeEth 29 | tradeVolumeToken 30 | } 31 | } 32 | ` 33 | 34 | export const ORDERBOOK = gql` 35 | query _($exchangeAddress: String!) { 36 | exchangeHistoricalDatas( 37 | first: 1 38 | where: { exchangeAddress: $exchangeAddress } 39 | orderBy: timestamp 40 | orderDirection: desc 41 | ) { 42 | timestamp 43 | ethBalance 44 | tokenBalance 45 | } 46 | } 47 | ` 48 | 49 | export const TRANSACTIONS = gql` 50 | query _($skip: Int!, $exchangeAddress: String!, $timestamp: Int!) { 51 | transactions( 52 | skip: $skip 53 | where: { exchangeAddress: $exchangeAddress, timestamp_gte: $timestamp } 54 | orderBy: timestamp 55 | orderDirection: asc 56 | ) { 57 | timestamp 58 | ethPurchaseEvents { 59 | id 60 | ethAmount 61 | tokenAmount 62 | } 63 | tokenPurchaseEvents { 64 | id 65 | ethAmount 66 | tokenAmount 67 | } 68 | } 69 | } 70 | ` 71 | -------------------------------------------------------------------------------- /src/v1/assets.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | 3 | import { getTopPairs } from './_shared' 4 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 5 | 6 | export const handler: APIGatewayProxyHandler = async () => { 7 | return await getTopPairs() 8 | .then(topPairs => 9 | createSuccessResponse({ 10 | ETH: { 11 | name: 'Ether', 12 | symbol: 'ETH', 13 | id: 'ETH', 14 | maker_fee: '0', 15 | taker_fee: '0.003' 16 | }, 17 | ...topPairs.reduce((accumulator: any, pair): any => { 18 | accumulator[pair.tokenAddress] = { 19 | ...(pair.tokenName ? { name: pair.tokenName } : {}), 20 | ...(pair.tokenSymbol ? { symbol: pair.tokenSymbol } : {}), 21 | id: pair.exchangeAddress, 22 | maker_fee: '0', 23 | taker_fee: '0.003' 24 | } 25 | return accumulator 26 | }, {}) 27 | }) 28 | ) 29 | .catch(error => createServerErrorResponse(error)) 30 | } 31 | -------------------------------------------------------------------------------- /src/v1/orderbook.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | 3 | import { getOrderbook } from './_shared' 4 | import { createSuccessResponse, createBadRequestResponse, createServerErrorResponse } from '../utils/response' 5 | 6 | export const handler: APIGatewayProxyHandler = async event => { 7 | if (!event.pathParameters?.pair || !/^ETH_0x[0-9a-fA-F]{40}$/.test(event.pathParameters.pair)) { 8 | return createBadRequestResponse() 9 | } 10 | 11 | return await getOrderbook(event.pathParameters.pair.substring(4)) 12 | .then(orderbook => { 13 | return createSuccessResponse({ 14 | timestamp: orderbook.timestamp, 15 | bids: orderbook.bids, 16 | asks: orderbook.asks 17 | }) 18 | }) 19 | .catch(error => createServerErrorResponse(error)) 20 | } 21 | -------------------------------------------------------------------------------- /src/v1/summary.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | 3 | import { getTopPairsData } from './_shared' 4 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 5 | 6 | export const handler: APIGatewayProxyHandler = async () => { 7 | return await getTopPairsData() 8 | .then(([topPairs, topPairsData]) => { 9 | return createSuccessResponse( 10 | topPairs.reduce((accumulator: any, _: any, i): any => { 11 | const pair = topPairs[i] 12 | const pairData = topPairsData[i] 13 | 14 | accumulator[`ETH_${pair.exchangeAddress}`] = { 15 | last_price: pairData.price, 16 | base_volume: pairData.tradeVolumeEth, 17 | quote_volume: pairData.tradeVolumeToken 18 | } 19 | return accumulator 20 | }, {}) 21 | ) 22 | }) 23 | .catch(error => createServerErrorResponse(error)) 24 | } 25 | -------------------------------------------------------------------------------- /src/v1/tickers.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | import { getTopPairsData } from './_shared' 3 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 4 | 5 | export const handler: APIGatewayProxyHandler = async () => { 6 | return await getTopPairsData() 7 | .then(([topPairs, topPairsData]) => { 8 | return createSuccessResponse( 9 | topPairs.reduce((accumulator: any, _: any, i): any => { 10 | const pair = topPairs[i] 11 | const pairData = topPairsData[i] 12 | 13 | accumulator[`ETH_${pair.exchangeAddress}`] = { 14 | base_name: 'Ether', 15 | base_symbol: 'ETH', 16 | base_id: 'ETH', 17 | ...(pair.tokenName ? { quote_name: pair.tokenName } : {}), 18 | ...(pair.tokenSymbol ? { quote_symbol: pair.tokenSymbol } : {}), 19 | quote_id: pair.exchangeAddress, 20 | quote_token_address: pair.tokenAddress, 21 | last_price: pairData.price, 22 | base_volume: pairData.tradeVolumeEth, 23 | quote_volume: pairData.tradeVolumeToken 24 | } 25 | 26 | return accumulator 27 | }, {}) 28 | ) 29 | }) 30 | .catch(error => createServerErrorResponse(error)) 31 | } 32 | -------------------------------------------------------------------------------- /src/v1/trades.ts: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda' 2 | 3 | import { getTrades } from './_shared' 4 | import { createSuccessResponse, createBadRequestResponse, createServerErrorResponse } from '../utils/response' 5 | 6 | export const handler: APIGatewayProxyHandler = async event => { 7 | if (!event.pathParameters?.pair || !/^ETH_0x[0-9a-fA-F]{40}$/.test(event.pathParameters.pair)) { 8 | return createBadRequestResponse() 9 | } 10 | 11 | return await getTrades(event.pathParameters.pair.substring(4)) 12 | .then(trades => { 13 | return createSuccessResponse( 14 | trades.map((trades): any => ({ 15 | trade_id: trades.id, 16 | price: trades.price, 17 | base_volume: trades.ethAmount, 18 | quote_volume: trades.tokenAmount, 19 | trade_timestamp: trades.timestamp, 20 | type: trades.type 21 | })) 22 | ) 23 | }) 24 | .catch(error => createServerErrorResponse(error)) 25 | } 26 | -------------------------------------------------------------------------------- /src/v2/_shared.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | import BLACKLIST from '../constants/blacklist' 3 | 4 | import client from './apollo/client' 5 | import { 6 | PAIR_RESERVES_BY_TOKENS, 7 | SWAPS_BY_PAIR, 8 | TOP_PAIRS, 9 | PAIR_FROM_TOKENS, 10 | PAIRS_VOLUME_QUERY 11 | } from './apollo/queries' 12 | import { getBlockFromTimestamp } from './blocks/queries' 13 | import { 14 | PairReservesQuery, 15 | PairReservesQueryVariables, 16 | PairsVolumeQuery, 17 | PairsVolumeQueryVariables, 18 | SwapsByPairQuery, 19 | SwapsByPairQueryVariables, 20 | TopPairsQuery, 21 | TopPairsQueryVariables 22 | } from './generated/v2-subgraph' 23 | 24 | const SECOND = 1000 25 | const MINUTE = 60 * SECOND 26 | const HOUR = 60 * MINUTE 27 | const DAY = 24 * HOUR 28 | 29 | export function get24HoursAgo(): number { 30 | return Math.floor((Date.now() - DAY) / 1000) 31 | } 32 | 33 | const TOP_PAIR_LIMIT = 1000 34 | export type Pair = TopPairsQuery['pairs'][number] 35 | 36 | export interface MappedDetailedPair extends Pair { 37 | price?: string 38 | previous24hVolumeToken0: BigNumber 39 | previous24hVolumeToken1: BigNumber 40 | } 41 | 42 | export async function getTopPairs(): Promise { 43 | const epochSecond = Math.floor(new Date().getTime() / 1000) 44 | const firstBlock = await getBlockFromTimestamp(epochSecond - 86400) 45 | 46 | if (!firstBlock) { 47 | throw new Error('first block was not fetched') 48 | } 49 | 50 | const { 51 | data: { pairs }, 52 | errors: topPairsErrors 53 | } = await client.query({ 54 | query: TOP_PAIRS, 55 | variables: { 56 | limit: TOP_PAIR_LIMIT, 57 | excludeTokenIds: BLACKLIST 58 | }, 59 | fetchPolicy: 'no-cache' 60 | }) 61 | 62 | if (topPairsErrors && topPairsErrors.length > 0) { 63 | console.error('Failed to fetch top pairs', topPairsErrors) 64 | throw new Error('Failed to fetch top pairs from the subgraph') 65 | } 66 | 67 | const { 68 | data: { pairVolumes }, 69 | errors: yesterdayVolumeErrors 70 | } = await client.query({ 71 | query: PAIRS_VOLUME_QUERY, 72 | variables: { 73 | limit: TOP_PAIR_LIMIT, 74 | pairIds: pairs.map(pair => pair.id), 75 | blockNumber: +firstBlock 76 | }, 77 | fetchPolicy: 'no-cache' 78 | }) 79 | 80 | if (yesterdayVolumeErrors && yesterdayVolumeErrors.length > 0) { 81 | console.error('Failed to fetch yesterday volume', yesterdayVolumeErrors) 82 | throw new Error(`Failed to get volume info for 24h ago from the subgraph`) 83 | } 84 | 85 | const yesterdayVolumeIndex = 86 | pairVolumes?.reduce<{ [pairId: string]: { volumeToken0: BigNumber; volumeToken1: BigNumber } }>((memo, pair) => { 87 | memo[pair.id] = { volumeToken0: new BigNumber(pair.volumeToken0), volumeToken1: new BigNumber(pair.volumeToken1) } 88 | return memo 89 | }, {}) ?? {} 90 | 91 | return ( 92 | pairs?.map( 93 | (pair): MappedDetailedPair => { 94 | const yesterday = yesterdayVolumeIndex[pair.id] 95 | if (yesterday) { 96 | if (yesterday.volumeToken0.gt(pair.volumeToken0)) { 97 | throw new Error(`Invalid subgraph response: pair ${pair.id} returned volumeToken0 < yesterday.volumeToken0`) 98 | } 99 | if (yesterday.volumeToken1.gt(pair.volumeToken1)) { 100 | throw new Error(`Invalid subgraph response: pair ${pair.id} returned volumeToken1 < yesterday.volumeToken1`) 101 | } 102 | } 103 | 104 | return { 105 | ...pair, 106 | price: 107 | pair.reserve0 !== '0' && pair.reserve1 !== '0' 108 | ? new BigNumber(pair.reserve1).dividedBy(pair.reserve0).toString() 109 | : undefined, 110 | previous24hVolumeToken0: 111 | pair.volumeToken0 && yesterday?.volumeToken0 112 | ? new BigNumber(pair.volumeToken0).minus(yesterday.volumeToken0) 113 | : new BigNumber(pair.volumeToken0), 114 | previous24hVolumeToken1: 115 | pair.volumeToken1 && yesterday?.volumeToken1 116 | ? new BigNumber(pair.volumeToken1).minus(yesterday.volumeToken1) 117 | : new BigNumber(pair.volumeToken1) 118 | } 119 | } 120 | ) ?? [] 121 | ) 122 | } 123 | 124 | function isSorted(tokenA: string, tokenB: string): boolean { 125 | return tokenA.toLowerCase() < tokenB.toLowerCase() 126 | } 127 | 128 | function sortedFormatted(tokenA: string, tokenB: string): [string, string] { 129 | return isSorted(tokenA, tokenB) 130 | ? [tokenA.toLowerCase(), tokenB.toLowerCase()] 131 | : [tokenB.toLowerCase(), tokenA.toLowerCase()] 132 | } 133 | 134 | // returns reserves of token a and b in the order they are queried 135 | export async function getReserves(tokenA: string, tokenB: string): Promise<[string, string]> { 136 | const [token0, token1] = sortedFormatted(tokenA, tokenB) 137 | return client 138 | .query({ 139 | query: PAIR_RESERVES_BY_TOKENS, 140 | variables: { 141 | token0, 142 | token1 143 | } 144 | }) 145 | .then(({ data: { pairs: [{ reserve0, reserve1 }] } }): [string, string] => 146 | tokenA.toLowerCase() === token0 ? [reserve0, reserve1] : [reserve1, reserve0] 147 | ) 148 | } 149 | 150 | type ArrayElement = A extends readonly (infer T)[] ? T : never 151 | 152 | type Swap = ArrayElement 153 | 154 | interface SwapMapped extends Swap { 155 | amountAIn: string 156 | amountAOut: string 157 | amountBIn: string 158 | amountBOut: string 159 | } 160 | 161 | export async function getSwaps(tokenA: string, tokenB: string): Promise { 162 | const _24HoursAgo = get24HoursAgo() 163 | const [token0, token1] = sortedFormatted(tokenA, tokenB) 164 | 165 | let { 166 | data: { 167 | pairs: [{ id: pairAddress }] 168 | } 169 | } = await client.query({ 170 | query: PAIR_FROM_TOKENS, 171 | variables: { 172 | token0, 173 | token1 174 | } 175 | }) 176 | 177 | const sorted = isSorted(tokenA, tokenB) 178 | let skip = 0 179 | let results: SwapMapped[] = [] 180 | let finished = false 181 | while (!finished) { 182 | await client 183 | .query({ 184 | query: SWAPS_BY_PAIR, 185 | variables: { 186 | skip, 187 | pairAddress, 188 | timestamp: _24HoursAgo 189 | } 190 | }) 191 | .then(({ data: { swaps } }): void => { 192 | if (!swaps || swaps.length === 0) { 193 | finished = true 194 | } else { 195 | skip += swaps.length 196 | 197 | results = results.concat( 198 | swaps.map( 199 | (swap: Swap): SwapMapped => ({ 200 | ...swap, 201 | amountAIn: sorted ? swap.amount0In : swap.amount1In, 202 | amountAOut: sorted ? swap.amount0Out : swap.amount1Out, 203 | amountBIn: sorted ? swap.amount1In : swap.amount0In, 204 | amountBOut: sorted ? swap.amount1Out : swap.amount0Out 205 | }) 206 | ) 207 | ) 208 | } 209 | }) 210 | } 211 | 212 | return results 213 | } 214 | -------------------------------------------------------------------------------- /src/v2/apollo/.graphqlconfig: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Uniswap V2", 3 | "schemaPath": "schema.graphql", 4 | "extensions": { 5 | "endpoints": { 6 | "Uniswap V2": { 7 | "url": "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", 8 | "headers": { 9 | "user-agent": "JS GraphQL" 10 | }, 11 | "introspect": false 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/v2/apollo/client.ts: -------------------------------------------------------------------------------- 1 | import { ApolloClient } from 'apollo-client' 2 | import { InMemoryCache } from 'apollo-cache-inmemory' 3 | import { HttpLink } from 'apollo-link-http' 4 | import fetch from 'node-fetch' 5 | 6 | export default new ApolloClient({ 7 | link: new HttpLink({ 8 | fetch, 9 | uri: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2' 10 | }), 11 | cache: new InMemoryCache() 12 | }) 13 | -------------------------------------------------------------------------------- /src/v2/apollo/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: './src/v2/apollo/schema.graphql' 3 | documents: 4 | - './src/v2/apollo/queries.ts' 5 | generates: 6 | ./src/v2/generated/v2-subgraph.ts: 7 | plugins: 8 | - "typescript" 9 | - "typescript-operations" 10 | config: 11 | declarationKind: 'interface' 12 | immutableTypes: true 13 | -------------------------------------------------------------------------------- /src/v2/apollo/queries.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag' 2 | 3 | export const PAIRS_VOLUME_QUERY = gql` 4 | query PairsVolume($limit: Int!, $pairIds: [ID!]!, $blockNumber: Int!) { 5 | pairVolumes: pairs(first: $limit, where: { id_in: $pairIds }, block: { number: $blockNumber }) { 6 | id 7 | volumeToken0 8 | volumeToken1 9 | } 10 | } 11 | ` 12 | 13 | // gets the top 1k pairs by USD reserves 14 | export const TOP_PAIRS = gql` 15 | fragment TokenInfo on Token { 16 | id 17 | symbol 18 | name 19 | } 20 | 21 | query TopPairs($limit: Int!, $excludeTokenIds: [String!]!) { 22 | pairs( 23 | first: $limit 24 | orderBy: reserveUSD 25 | orderDirection: desc 26 | where: { token0_not_in: $excludeTokenIds, token1_not_in: $excludeTokenIds } 27 | ) { 28 | id 29 | token0 { 30 | ...TokenInfo 31 | } 32 | token1 { 33 | ...TokenInfo 34 | } 35 | reserve0 36 | reserve1 37 | volumeToken0 38 | volumeToken1 39 | } 40 | } 41 | ` 42 | 43 | export const PAIR_RESERVES_BY_TOKENS = gql` 44 | query PairReserves($token0: String!, $token1: String!) { 45 | pairs(where: { token0: $token0, token1: $token1 }) { 46 | reserve0 47 | reserve1 48 | } 49 | } 50 | ` 51 | 52 | export const SWAPS_BY_PAIR = gql` 53 | query SwapsByPair($skip: Int!, $timestamp: BigInt!, $pairAddress: String!) { 54 | swaps( 55 | skip: $skip 56 | where: { timestamp_gte: $timestamp, pair: $pairAddress } 57 | orderBy: timestamp 58 | orderDirection: asc 59 | ) { 60 | id 61 | timestamp 62 | amount0In 63 | amount0Out 64 | amount1In 65 | amount1Out 66 | } 67 | } 68 | ` 69 | 70 | export const PAIR_FROM_TOKENS = gql` 71 | query SwapsByTokens($token0: String!, $token1: String!) { 72 | pairs(where: { token0: $token0, token1: $token1 }) { 73 | id 74 | } 75 | } 76 | ` 77 | -------------------------------------------------------------------------------- /src/v2/apollo/schema.graphql: -------------------------------------------------------------------------------- 1 | # This file was generated based on ".graphqlconfig". Do not edit manually. 2 | 3 | schema { 4 | query: Query 5 | subscription: Subscription 6 | } 7 | 8 | type Bundle { 9 | ethPrice: BigDecimal! 10 | id: ID! 11 | } 12 | 13 | type Burn { 14 | amount0: BigDecimal 15 | amount1: BigDecimal 16 | amountUSD: BigDecimal 17 | feeLiquidity: BigDecimal 18 | feeTo: Bytes 19 | id: ID! 20 | liquidity: BigDecimal! 21 | logIndex: BigInt 22 | pair: Pair! 23 | sender: Bytes 24 | timestamp: BigInt! 25 | to: Bytes 26 | transaction: Transaction! 27 | } 28 | 29 | type LiquidityPosition { 30 | id: ID! 31 | liquidityTokenBalance: BigDecimal! 32 | pair: Pair! 33 | poolOwnership: BigDecimal 34 | user: User! 35 | } 36 | 37 | type Mint { 38 | amount0: BigDecimal 39 | amount1: BigDecimal 40 | amountUSD: BigDecimal 41 | feeLiquidity: BigDecimal 42 | feeTo: Bytes 43 | id: ID! 44 | liquidity: BigDecimal! 45 | logIndex: BigInt 46 | pair: Pair! 47 | sender: Bytes 48 | timestamp: BigInt! 49 | to: Bytes! 50 | transaction: Transaction! 51 | } 52 | 53 | type Pair { 54 | burns(first: Int = 100, orderBy: Burn_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Burn_filter): [Burn!] 55 | createdAtBlockNumber: BigInt! 56 | createdAtTimestamp: BigInt! 57 | factory: UniswapFactory! 58 | id: ID! 59 | liquidityPositions(first: Int = 100, orderBy: LiquidityPosition_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: LiquidityPosition_filter): [LiquidityPosition!] 60 | mints(first: Int = 100, orderBy: Mint_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Mint_filter): [Mint!] 61 | reserve0: BigDecimal! 62 | reserve1: BigDecimal! 63 | reserveETH: BigDecimal! 64 | reserveUSD: BigDecimal! 65 | swaps(first: Int = 100, orderBy: Swap_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Swap_filter): [Swap!] 66 | token0: Token! 67 | token0Price: BigDecimal! 68 | token1: Token! 69 | token1Price: BigDecimal! 70 | totalSupply: BigDecimal! 71 | trackedReserveETH: BigDecimal! 72 | txCount: BigInt! 73 | volumeToken0: BigDecimal! 74 | volumeToken1: BigDecimal! 75 | volumeUSD: BigDecimal! 76 | } 77 | 78 | type PairDayData { 79 | dailyTxns: BigInt! 80 | dailyVolumeToken0: BigDecimal! 81 | dailyVolumeToken1: BigDecimal! 82 | dailyVolumeUSD: BigDecimal! 83 | date: Int! 84 | id: ID! 85 | pairAddress: Bytes! 86 | reserve0: BigDecimal! 87 | reserve1: BigDecimal! 88 | reserveUSD: BigDecimal! 89 | token0: Token! 90 | token1: Token! 91 | } 92 | 93 | type Query { 94 | bundle( 95 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 96 | block: Block_height, 97 | id: ID! 98 | ): Bundle 99 | bundles( 100 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 101 | block: Block_height, 102 | first: Int = 100, 103 | orderBy: Bundle_orderBy, 104 | orderDirection: OrderDirection, 105 | skip: Int = 0, 106 | where: Bundle_filter 107 | ): [Bundle!]! 108 | burn( 109 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 110 | block: Block_height, 111 | id: ID! 112 | ): Burn 113 | burns( 114 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 115 | block: Block_height, 116 | first: Int = 100, 117 | orderBy: Burn_orderBy, 118 | orderDirection: OrderDirection, 119 | skip: Int = 0, 120 | where: Burn_filter 121 | ): [Burn!]! 122 | liquidityPosition( 123 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 124 | block: Block_height, 125 | id: ID! 126 | ): LiquidityPosition 127 | liquidityPositions( 128 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 129 | block: Block_height, 130 | first: Int = 100, 131 | orderBy: LiquidityPosition_orderBy, 132 | orderDirection: OrderDirection, 133 | skip: Int = 0, 134 | where: LiquidityPosition_filter 135 | ): [LiquidityPosition!]! 136 | mint( 137 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 138 | block: Block_height, 139 | id: ID! 140 | ): Mint 141 | mints( 142 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 143 | block: Block_height, 144 | first: Int = 100, 145 | orderBy: Mint_orderBy, 146 | orderDirection: OrderDirection, 147 | skip: Int = 0, 148 | where: Mint_filter 149 | ): [Mint!]! 150 | pair( 151 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 152 | block: Block_height, 153 | id: ID! 154 | ): Pair 155 | pairDayData( 156 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 157 | block: Block_height, 158 | id: ID! 159 | ): PairDayData 160 | pairDayDatas( 161 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 162 | block: Block_height, 163 | first: Int = 100, 164 | orderBy: PairDayData_orderBy, 165 | orderDirection: OrderDirection, 166 | skip: Int = 0, 167 | where: PairDayData_filter 168 | ): [PairDayData!]! 169 | pairs( 170 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 171 | block: Block_height, 172 | first: Int = 100, 173 | orderBy: Pair_orderBy, 174 | orderDirection: OrderDirection, 175 | skip: Int = 0, 176 | where: Pair_filter 177 | ): [Pair!]! 178 | swap( 179 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 180 | block: Block_height, 181 | id: ID! 182 | ): Swap 183 | swaps( 184 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 185 | block: Block_height, 186 | first: Int = 100, 187 | orderBy: Swap_orderBy, 188 | orderDirection: OrderDirection, 189 | skip: Int = 0, 190 | where: Swap_filter 191 | ): [Swap!]! 192 | token( 193 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 194 | block: Block_height, 195 | id: ID! 196 | ): Token 197 | tokenDayData( 198 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 199 | block: Block_height, 200 | id: ID! 201 | ): TokenDayData 202 | tokenDayDatas( 203 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 204 | block: Block_height, 205 | first: Int = 100, 206 | orderBy: TokenDayData_orderBy, 207 | orderDirection: OrderDirection, 208 | skip: Int = 0, 209 | where: TokenDayData_filter 210 | ): [TokenDayData!]! 211 | tokens( 212 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 213 | block: Block_height, 214 | first: Int = 100, 215 | orderBy: Token_orderBy, 216 | orderDirection: OrderDirection, 217 | skip: Int = 0, 218 | where: Token_filter 219 | ): [Token!]! 220 | transaction( 221 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 222 | block: Block_height, 223 | id: ID! 224 | ): Transaction 225 | transactions( 226 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 227 | block: Block_height, 228 | first: Int = 100, 229 | orderBy: Transaction_orderBy, 230 | orderDirection: OrderDirection, 231 | skip: Int = 0, 232 | where: Transaction_filter 233 | ): [Transaction!]! 234 | uniswapDayData( 235 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 236 | block: Block_height, 237 | id: ID! 238 | ): UniswapDayData 239 | uniswapDayDatas( 240 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 241 | block: Block_height, 242 | first: Int = 100, 243 | orderBy: UniswapDayData_orderBy, 244 | orderDirection: OrderDirection, 245 | skip: Int = 0, 246 | where: UniswapDayData_filter 247 | ): [UniswapDayData!]! 248 | uniswapFactories( 249 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 250 | block: Block_height, 251 | first: Int = 100, 252 | orderBy: UniswapFactory_orderBy, 253 | orderDirection: OrderDirection, 254 | skip: Int = 0, 255 | where: UniswapFactory_filter 256 | ): [UniswapFactory!]! 257 | uniswapFactory( 258 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 259 | block: Block_height, 260 | id: ID! 261 | ): UniswapFactory 262 | user( 263 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 264 | block: Block_height, 265 | id: ID! 266 | ): User 267 | users( 268 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 269 | block: Block_height, 270 | first: Int = 100, 271 | orderBy: User_orderBy, 272 | orderDirection: OrderDirection, 273 | skip: Int = 0, 274 | where: User_filter 275 | ): [User!]! 276 | } 277 | 278 | type Subscription { 279 | bundle( 280 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 281 | block: Block_height, 282 | id: ID! 283 | ): Bundle 284 | bundles( 285 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 286 | block: Block_height, 287 | first: Int = 100, 288 | orderBy: Bundle_orderBy, 289 | orderDirection: OrderDirection, 290 | skip: Int = 0, 291 | where: Bundle_filter 292 | ): [Bundle!]! 293 | burn( 294 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 295 | block: Block_height, 296 | id: ID! 297 | ): Burn 298 | burns( 299 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 300 | block: Block_height, 301 | first: Int = 100, 302 | orderBy: Burn_orderBy, 303 | orderDirection: OrderDirection, 304 | skip: Int = 0, 305 | where: Burn_filter 306 | ): [Burn!]! 307 | liquidityPosition( 308 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 309 | block: Block_height, 310 | id: ID! 311 | ): LiquidityPosition 312 | liquidityPositions( 313 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 314 | block: Block_height, 315 | first: Int = 100, 316 | orderBy: LiquidityPosition_orderBy, 317 | orderDirection: OrderDirection, 318 | skip: Int = 0, 319 | where: LiquidityPosition_filter 320 | ): [LiquidityPosition!]! 321 | mint( 322 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 323 | block: Block_height, 324 | id: ID! 325 | ): Mint 326 | mints( 327 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 328 | block: Block_height, 329 | first: Int = 100, 330 | orderBy: Mint_orderBy, 331 | orderDirection: OrderDirection, 332 | skip: Int = 0, 333 | where: Mint_filter 334 | ): [Mint!]! 335 | pair( 336 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 337 | block: Block_height, 338 | id: ID! 339 | ): Pair 340 | pairDayData( 341 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 342 | block: Block_height, 343 | id: ID! 344 | ): PairDayData 345 | pairDayDatas( 346 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 347 | block: Block_height, 348 | first: Int = 100, 349 | orderBy: PairDayData_orderBy, 350 | orderDirection: OrderDirection, 351 | skip: Int = 0, 352 | where: PairDayData_filter 353 | ): [PairDayData!]! 354 | pairs( 355 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 356 | block: Block_height, 357 | first: Int = 100, 358 | orderBy: Pair_orderBy, 359 | orderDirection: OrderDirection, 360 | skip: Int = 0, 361 | where: Pair_filter 362 | ): [Pair!]! 363 | swap( 364 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 365 | block: Block_height, 366 | id: ID! 367 | ): Swap 368 | swaps( 369 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 370 | block: Block_height, 371 | first: Int = 100, 372 | orderBy: Swap_orderBy, 373 | orderDirection: OrderDirection, 374 | skip: Int = 0, 375 | where: Swap_filter 376 | ): [Swap!]! 377 | token( 378 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 379 | block: Block_height, 380 | id: ID! 381 | ): Token 382 | tokenDayData( 383 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 384 | block: Block_height, 385 | id: ID! 386 | ): TokenDayData 387 | tokenDayDatas( 388 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 389 | block: Block_height, 390 | first: Int = 100, 391 | orderBy: TokenDayData_orderBy, 392 | orderDirection: OrderDirection, 393 | skip: Int = 0, 394 | where: TokenDayData_filter 395 | ): [TokenDayData!]! 396 | tokens( 397 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 398 | block: Block_height, 399 | first: Int = 100, 400 | orderBy: Token_orderBy, 401 | orderDirection: OrderDirection, 402 | skip: Int = 0, 403 | where: Token_filter 404 | ): [Token!]! 405 | transaction( 406 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 407 | block: Block_height, 408 | id: ID! 409 | ): Transaction 410 | transactions( 411 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 412 | block: Block_height, 413 | first: Int = 100, 414 | orderBy: Transaction_orderBy, 415 | orderDirection: OrderDirection, 416 | skip: Int = 0, 417 | where: Transaction_filter 418 | ): [Transaction!]! 419 | uniswapDayData( 420 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 421 | block: Block_height, 422 | id: ID! 423 | ): UniswapDayData 424 | uniswapDayDatas( 425 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 426 | block: Block_height, 427 | first: Int = 100, 428 | orderBy: UniswapDayData_orderBy, 429 | orderDirection: OrderDirection, 430 | skip: Int = 0, 431 | where: UniswapDayData_filter 432 | ): [UniswapDayData!]! 433 | uniswapFactories( 434 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 435 | block: Block_height, 436 | first: Int = 100, 437 | orderBy: UniswapFactory_orderBy, 438 | orderDirection: OrderDirection, 439 | skip: Int = 0, 440 | where: UniswapFactory_filter 441 | ): [UniswapFactory!]! 442 | uniswapFactory( 443 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 444 | block: Block_height, 445 | id: ID! 446 | ): UniswapFactory 447 | user( 448 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 449 | block: Block_height, 450 | id: ID! 451 | ): User 452 | users( 453 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 454 | block: Block_height, 455 | first: Int = 100, 456 | orderBy: User_orderBy, 457 | orderDirection: OrderDirection, 458 | skip: Int = 0, 459 | where: User_filter 460 | ): [User!]! 461 | } 462 | 463 | type Swap { 464 | amount0In: BigDecimal! 465 | amount0Out: BigDecimal! 466 | amount1In: BigDecimal! 467 | amount1Out: BigDecimal! 468 | amountUSD: BigDecimal! 469 | id: ID! 470 | logIndex: BigInt 471 | pair: Pair! 472 | sender: Bytes! 473 | timestamp: BigInt! 474 | to: Bytes! 475 | transaction: Transaction! 476 | } 477 | 478 | type Token { 479 | allPairs(first: Int = 100, orderBy: Pair_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Pair_filter): [Pair!] 480 | decimals: BigInt! 481 | derivedETH: BigDecimal 482 | id: ID! 483 | mostLiquidPairs(first: Int = 100, orderBy: PairDayData_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: PairDayData_filter): [PairDayData]! 484 | name: String! 485 | symbol: String! 486 | totalLiquidity: BigDecimal! 487 | tradeVolume: BigDecimal! 488 | tradeVolumeUSD: BigDecimal! 489 | txCount: BigInt! 490 | } 491 | 492 | type TokenDayData { 493 | dailyTxns: BigInt! 494 | dailyVolumeETH: BigDecimal! 495 | dailyVolumeToken: BigDecimal! 496 | dailyVolumeUSD: BigDecimal! 497 | date: Int! 498 | id: ID! 499 | maxStored: Int! 500 | mostLiquidPairs(first: Int = 100, orderBy: PairDayData_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: PairDayData_filter): [PairDayData!]! 501 | priceUSD: BigDecimal! 502 | token: Token! 503 | totalLiquidityETH: BigDecimal! 504 | totalLiquidityToken: BigDecimal! 505 | totalLiquidityUSD: BigDecimal! 506 | } 507 | 508 | type Transaction { 509 | blockNumber: BigInt! 510 | burns(first: Int = 100, orderBy: Burn_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Burn_filter): [Burn]! 511 | id: ID! 512 | mints(first: Int = 100, orderBy: Mint_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Mint_filter): [Mint]! 513 | swaps(first: Int = 100, orderBy: Swap_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Swap_filter): [Swap]! 514 | timestamp: BigInt! 515 | } 516 | 517 | type UniswapDayData { 518 | dailyVolumeETH: BigDecimal! 519 | dailyVolumeUSD: BigDecimal! 520 | date: Int! 521 | id: ID! 522 | maxStored: Int 523 | mostLiquidTokens(first: Int = 100, orderBy: TokenDayData_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: TokenDayData_filter): [TokenDayData!]! 524 | totalLiquidityETH: BigDecimal! 525 | totalLiquidityUSD: BigDecimal! 526 | totalVolumeETH: BigDecimal! 527 | totalVolumeUSD: BigDecimal! 528 | txCount: BigInt! 529 | } 530 | 531 | type UniswapFactory { 532 | id: ID! 533 | mostLiquidTokens(first: Int = 100, orderBy: TokenDayData_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: TokenDayData_filter): [TokenDayData!]! 534 | pairCount: Int! 535 | pairs(first: Int = 100, orderBy: Pair_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: Pair_filter): [Pair]! 536 | totalLiquidityETH: BigDecimal! 537 | totalLiquidityUSD: BigDecimal! 538 | totalVolumeETH: BigDecimal! 539 | totalVolumeUSD: BigDecimal! 540 | txCount: BigInt! 541 | } 542 | 543 | type User { 544 | id: ID! 545 | liquidityPositions(first: Int = 100, orderBy: LiquidityPosition_orderBy, orderDirection: OrderDirection, skip: Int = 0, where: LiquidityPosition_filter): [LiquidityPosition!] 546 | } 547 | 548 | enum Bundle_orderBy { 549 | ethPrice 550 | id 551 | } 552 | 553 | enum Burn_orderBy { 554 | amount0 555 | amount1 556 | amountUSD 557 | feeLiquidity 558 | feeTo 559 | id 560 | liquidity 561 | logIndex 562 | pair 563 | sender 564 | timestamp 565 | to 566 | transaction 567 | } 568 | 569 | enum LiquidityPosition_orderBy { 570 | id 571 | liquidityTokenBalance 572 | pair 573 | poolOwnership 574 | user 575 | } 576 | 577 | enum Mint_orderBy { 578 | amount0 579 | amount1 580 | amountUSD 581 | feeLiquidity 582 | feeTo 583 | id 584 | liquidity 585 | logIndex 586 | pair 587 | sender 588 | timestamp 589 | to 590 | transaction 591 | } 592 | 593 | enum OrderDirection { 594 | asc 595 | desc 596 | } 597 | 598 | enum PairDayData_orderBy { 599 | dailyTxns 600 | dailyVolumeToken0 601 | dailyVolumeToken1 602 | dailyVolumeUSD 603 | date 604 | id 605 | pairAddress 606 | reserve0 607 | reserve1 608 | reserveUSD 609 | token0 610 | token1 611 | } 612 | 613 | enum Pair_orderBy { 614 | burns 615 | createdAtBlockNumber 616 | createdAtTimestamp 617 | factory 618 | id 619 | liquidityPositions 620 | mints 621 | reserve0 622 | reserve1 623 | reserveETH 624 | reserveUSD 625 | swaps 626 | token0 627 | token0Price 628 | token1 629 | token1Price 630 | totalSupply 631 | trackedReserveETH 632 | txCount 633 | volumeToken0 634 | volumeToken1 635 | volumeUSD 636 | } 637 | 638 | enum Swap_orderBy { 639 | amount0In 640 | amount0Out 641 | amount1In 642 | amount1Out 643 | amountUSD 644 | id 645 | logIndex 646 | pair 647 | sender 648 | timestamp 649 | to 650 | transaction 651 | } 652 | 653 | enum TokenDayData_orderBy { 654 | dailyTxns 655 | dailyVolumeETH 656 | dailyVolumeToken 657 | dailyVolumeUSD 658 | date 659 | id 660 | maxStored 661 | mostLiquidPairs 662 | priceUSD 663 | token 664 | totalLiquidityETH 665 | totalLiquidityToken 666 | totalLiquidityUSD 667 | } 668 | 669 | enum Token_orderBy { 670 | allPairs 671 | decimals 672 | derivedETH 673 | id 674 | mostLiquidPairs 675 | name 676 | symbol 677 | totalLiquidity 678 | tradeVolume 679 | tradeVolumeUSD 680 | txCount 681 | } 682 | 683 | enum Transaction_orderBy { 684 | blockNumber 685 | burns 686 | id 687 | mints 688 | swaps 689 | timestamp 690 | } 691 | 692 | enum UniswapDayData_orderBy { 693 | dailyVolumeETH 694 | dailyVolumeUSD 695 | date 696 | id 697 | maxStored 698 | mostLiquidTokens 699 | totalLiquidityETH 700 | totalLiquidityUSD 701 | totalVolumeETH 702 | totalVolumeUSD 703 | txCount 704 | } 705 | 706 | enum UniswapFactory_orderBy { 707 | id 708 | mostLiquidTokens 709 | pairCount 710 | pairs 711 | totalLiquidityETH 712 | totalLiquidityUSD 713 | totalVolumeETH 714 | totalVolumeUSD 715 | txCount 716 | } 717 | 718 | enum User_orderBy { 719 | id 720 | liquidityPositions 721 | } 722 | 723 | input Block_height { 724 | hash: Bytes 725 | number: Int 726 | } 727 | 728 | input Bundle_filter { 729 | ethPrice: BigDecimal 730 | ethPrice_gt: BigDecimal 731 | ethPrice_gte: BigDecimal 732 | ethPrice_in: [BigDecimal!] 733 | ethPrice_lt: BigDecimal 734 | ethPrice_lte: BigDecimal 735 | ethPrice_not: BigDecimal 736 | ethPrice_not_in: [BigDecimal!] 737 | id: ID 738 | id_gt: ID 739 | id_gte: ID 740 | id_in: [ID!] 741 | id_lt: ID 742 | id_lte: ID 743 | id_not: ID 744 | id_not_in: [ID!] 745 | } 746 | 747 | input Burn_filter { 748 | amount0: BigDecimal 749 | amount0_gt: BigDecimal 750 | amount0_gte: BigDecimal 751 | amount0_in: [BigDecimal!] 752 | amount0_lt: BigDecimal 753 | amount0_lte: BigDecimal 754 | amount0_not: BigDecimal 755 | amount0_not_in: [BigDecimal!] 756 | amount1: BigDecimal 757 | amount1_gt: BigDecimal 758 | amount1_gte: BigDecimal 759 | amount1_in: [BigDecimal!] 760 | amount1_lt: BigDecimal 761 | amount1_lte: BigDecimal 762 | amount1_not: BigDecimal 763 | amount1_not_in: [BigDecimal!] 764 | amountUSD: BigDecimal 765 | amountUSD_gt: BigDecimal 766 | amountUSD_gte: BigDecimal 767 | amountUSD_in: [BigDecimal!] 768 | amountUSD_lt: BigDecimal 769 | amountUSD_lte: BigDecimal 770 | amountUSD_not: BigDecimal 771 | amountUSD_not_in: [BigDecimal!] 772 | feeLiquidity: BigDecimal 773 | feeLiquidity_gt: BigDecimal 774 | feeLiquidity_gte: BigDecimal 775 | feeLiquidity_in: [BigDecimal!] 776 | feeLiquidity_lt: BigDecimal 777 | feeLiquidity_lte: BigDecimal 778 | feeLiquidity_not: BigDecimal 779 | feeLiquidity_not_in: [BigDecimal!] 780 | feeTo: Bytes 781 | feeTo_contains: Bytes 782 | feeTo_in: [Bytes!] 783 | feeTo_not: Bytes 784 | feeTo_not_contains: Bytes 785 | feeTo_not_in: [Bytes!] 786 | id: ID 787 | id_gt: ID 788 | id_gte: ID 789 | id_in: [ID!] 790 | id_lt: ID 791 | id_lte: ID 792 | id_not: ID 793 | id_not_in: [ID!] 794 | liquidity: BigDecimal 795 | liquidity_gt: BigDecimal 796 | liquidity_gte: BigDecimal 797 | liquidity_in: [BigDecimal!] 798 | liquidity_lt: BigDecimal 799 | liquidity_lte: BigDecimal 800 | liquidity_not: BigDecimal 801 | liquidity_not_in: [BigDecimal!] 802 | logIndex: BigInt 803 | logIndex_gt: BigInt 804 | logIndex_gte: BigInt 805 | logIndex_in: [BigInt!] 806 | logIndex_lt: BigInt 807 | logIndex_lte: BigInt 808 | logIndex_not: BigInt 809 | logIndex_not_in: [BigInt!] 810 | pair: String 811 | pair_contains: String 812 | pair_ends_with: String 813 | pair_gt: String 814 | pair_gte: String 815 | pair_in: [String!] 816 | pair_lt: String 817 | pair_lte: String 818 | pair_not: String 819 | pair_not_contains: String 820 | pair_not_ends_with: String 821 | pair_not_in: [String!] 822 | pair_not_starts_with: String 823 | pair_starts_with: String 824 | sender: Bytes 825 | sender_contains: Bytes 826 | sender_in: [Bytes!] 827 | sender_not: Bytes 828 | sender_not_contains: Bytes 829 | sender_not_in: [Bytes!] 830 | timestamp: BigInt 831 | timestamp_gt: BigInt 832 | timestamp_gte: BigInt 833 | timestamp_in: [BigInt!] 834 | timestamp_lt: BigInt 835 | timestamp_lte: BigInt 836 | timestamp_not: BigInt 837 | timestamp_not_in: [BigInt!] 838 | to: Bytes 839 | to_contains: Bytes 840 | to_in: [Bytes!] 841 | to_not: Bytes 842 | to_not_contains: Bytes 843 | to_not_in: [Bytes!] 844 | } 845 | 846 | input LiquidityPosition_filter { 847 | id: ID 848 | id_gt: ID 849 | id_gte: ID 850 | id_in: [ID!] 851 | id_lt: ID 852 | id_lte: ID 853 | id_not: ID 854 | id_not_in: [ID!] 855 | liquidityTokenBalance: BigDecimal 856 | liquidityTokenBalance_gt: BigDecimal 857 | liquidityTokenBalance_gte: BigDecimal 858 | liquidityTokenBalance_in: [BigDecimal!] 859 | liquidityTokenBalance_lt: BigDecimal 860 | liquidityTokenBalance_lte: BigDecimal 861 | liquidityTokenBalance_not: BigDecimal 862 | liquidityTokenBalance_not_in: [BigDecimal!] 863 | pair: String 864 | pair_contains: String 865 | pair_ends_with: String 866 | pair_gt: String 867 | pair_gte: String 868 | pair_in: [String!] 869 | pair_lt: String 870 | pair_lte: String 871 | pair_not: String 872 | pair_not_contains: String 873 | pair_not_ends_with: String 874 | pair_not_in: [String!] 875 | pair_not_starts_with: String 876 | pair_starts_with: String 877 | poolOwnership: BigDecimal 878 | poolOwnership_gt: BigDecimal 879 | poolOwnership_gte: BigDecimal 880 | poolOwnership_in: [BigDecimal!] 881 | poolOwnership_lt: BigDecimal 882 | poolOwnership_lte: BigDecimal 883 | poolOwnership_not: BigDecimal 884 | poolOwnership_not_in: [BigDecimal!] 885 | user: String 886 | user_contains: String 887 | user_ends_with: String 888 | user_gt: String 889 | user_gte: String 890 | user_in: [String!] 891 | user_lt: String 892 | user_lte: String 893 | user_not: String 894 | user_not_contains: String 895 | user_not_ends_with: String 896 | user_not_in: [String!] 897 | user_not_starts_with: String 898 | user_starts_with: String 899 | } 900 | 901 | input Mint_filter { 902 | amount0: BigDecimal 903 | amount0_gt: BigDecimal 904 | amount0_gte: BigDecimal 905 | amount0_in: [BigDecimal!] 906 | amount0_lt: BigDecimal 907 | amount0_lte: BigDecimal 908 | amount0_not: BigDecimal 909 | amount0_not_in: [BigDecimal!] 910 | amount1: BigDecimal 911 | amount1_gt: BigDecimal 912 | amount1_gte: BigDecimal 913 | amount1_in: [BigDecimal!] 914 | amount1_lt: BigDecimal 915 | amount1_lte: BigDecimal 916 | amount1_not: BigDecimal 917 | amount1_not_in: [BigDecimal!] 918 | amountUSD: BigDecimal 919 | amountUSD_gt: BigDecimal 920 | amountUSD_gte: BigDecimal 921 | amountUSD_in: [BigDecimal!] 922 | amountUSD_lt: BigDecimal 923 | amountUSD_lte: BigDecimal 924 | amountUSD_not: BigDecimal 925 | amountUSD_not_in: [BigDecimal!] 926 | feeLiquidity: BigDecimal 927 | feeLiquidity_gt: BigDecimal 928 | feeLiquidity_gte: BigDecimal 929 | feeLiquidity_in: [BigDecimal!] 930 | feeLiquidity_lt: BigDecimal 931 | feeLiquidity_lte: BigDecimal 932 | feeLiquidity_not: BigDecimal 933 | feeLiquidity_not_in: [BigDecimal!] 934 | feeTo: Bytes 935 | feeTo_contains: Bytes 936 | feeTo_in: [Bytes!] 937 | feeTo_not: Bytes 938 | feeTo_not_contains: Bytes 939 | feeTo_not_in: [Bytes!] 940 | id: ID 941 | id_gt: ID 942 | id_gte: ID 943 | id_in: [ID!] 944 | id_lt: ID 945 | id_lte: ID 946 | id_not: ID 947 | id_not_in: [ID!] 948 | liquidity: BigDecimal 949 | liquidity_gt: BigDecimal 950 | liquidity_gte: BigDecimal 951 | liquidity_in: [BigDecimal!] 952 | liquidity_lt: BigDecimal 953 | liquidity_lte: BigDecimal 954 | liquidity_not: BigDecimal 955 | liquidity_not_in: [BigDecimal!] 956 | logIndex: BigInt 957 | logIndex_gt: BigInt 958 | logIndex_gte: BigInt 959 | logIndex_in: [BigInt!] 960 | logIndex_lt: BigInt 961 | logIndex_lte: BigInt 962 | logIndex_not: BigInt 963 | logIndex_not_in: [BigInt!] 964 | pair: String 965 | pair_contains: String 966 | pair_ends_with: String 967 | pair_gt: String 968 | pair_gte: String 969 | pair_in: [String!] 970 | pair_lt: String 971 | pair_lte: String 972 | pair_not: String 973 | pair_not_contains: String 974 | pair_not_ends_with: String 975 | pair_not_in: [String!] 976 | pair_not_starts_with: String 977 | pair_starts_with: String 978 | sender: Bytes 979 | sender_contains: Bytes 980 | sender_in: [Bytes!] 981 | sender_not: Bytes 982 | sender_not_contains: Bytes 983 | sender_not_in: [Bytes!] 984 | timestamp: BigInt 985 | timestamp_gt: BigInt 986 | timestamp_gte: BigInt 987 | timestamp_in: [BigInt!] 988 | timestamp_lt: BigInt 989 | timestamp_lte: BigInt 990 | timestamp_not: BigInt 991 | timestamp_not_in: [BigInt!] 992 | to: Bytes 993 | to_contains: Bytes 994 | to_in: [Bytes!] 995 | to_not: Bytes 996 | to_not_contains: Bytes 997 | to_not_in: [Bytes!] 998 | } 999 | 1000 | input PairDayData_filter { 1001 | dailyTxns: BigInt 1002 | dailyTxns_gt: BigInt 1003 | dailyTxns_gte: BigInt 1004 | dailyTxns_in: [BigInt!] 1005 | dailyTxns_lt: BigInt 1006 | dailyTxns_lte: BigInt 1007 | dailyTxns_not: BigInt 1008 | dailyTxns_not_in: [BigInt!] 1009 | dailyVolumeToken0: BigDecimal 1010 | dailyVolumeToken0_gt: BigDecimal 1011 | dailyVolumeToken0_gte: BigDecimal 1012 | dailyVolumeToken0_in: [BigDecimal!] 1013 | dailyVolumeToken0_lt: BigDecimal 1014 | dailyVolumeToken0_lte: BigDecimal 1015 | dailyVolumeToken0_not: BigDecimal 1016 | dailyVolumeToken0_not_in: [BigDecimal!] 1017 | dailyVolumeToken1: BigDecimal 1018 | dailyVolumeToken1_gt: BigDecimal 1019 | dailyVolumeToken1_gte: BigDecimal 1020 | dailyVolumeToken1_in: [BigDecimal!] 1021 | dailyVolumeToken1_lt: BigDecimal 1022 | dailyVolumeToken1_lte: BigDecimal 1023 | dailyVolumeToken1_not: BigDecimal 1024 | dailyVolumeToken1_not_in: [BigDecimal!] 1025 | dailyVolumeUSD: BigDecimal 1026 | dailyVolumeUSD_gt: BigDecimal 1027 | dailyVolumeUSD_gte: BigDecimal 1028 | dailyVolumeUSD_in: [BigDecimal!] 1029 | dailyVolumeUSD_lt: BigDecimal 1030 | dailyVolumeUSD_lte: BigDecimal 1031 | dailyVolumeUSD_not: BigDecimal 1032 | dailyVolumeUSD_not_in: [BigDecimal!] 1033 | date: Int 1034 | date_gt: Int 1035 | date_gte: Int 1036 | date_in: [Int!] 1037 | date_lt: Int 1038 | date_lte: Int 1039 | date_not: Int 1040 | date_not_in: [Int!] 1041 | id: ID 1042 | id_gt: ID 1043 | id_gte: ID 1044 | id_in: [ID!] 1045 | id_lt: ID 1046 | id_lte: ID 1047 | id_not: ID 1048 | id_not_in: [ID!] 1049 | pairAddress: Bytes 1050 | pairAddress_contains: Bytes 1051 | pairAddress_in: [Bytes!] 1052 | pairAddress_not: Bytes 1053 | pairAddress_not_contains: Bytes 1054 | pairAddress_not_in: [Bytes!] 1055 | reserve0: BigDecimal 1056 | reserve0_gt: BigDecimal 1057 | reserve0_gte: BigDecimal 1058 | reserve0_in: [BigDecimal!] 1059 | reserve0_lt: BigDecimal 1060 | reserve0_lte: BigDecimal 1061 | reserve0_not: BigDecimal 1062 | reserve0_not_in: [BigDecimal!] 1063 | reserve1: BigDecimal 1064 | reserve1_gt: BigDecimal 1065 | reserve1_gte: BigDecimal 1066 | reserve1_in: [BigDecimal!] 1067 | reserve1_lt: BigDecimal 1068 | reserve1_lte: BigDecimal 1069 | reserve1_not: BigDecimal 1070 | reserve1_not_in: [BigDecimal!] 1071 | reserveUSD: BigDecimal 1072 | reserveUSD_gt: BigDecimal 1073 | reserveUSD_gte: BigDecimal 1074 | reserveUSD_in: [BigDecimal!] 1075 | reserveUSD_lt: BigDecimal 1076 | reserveUSD_lte: BigDecimal 1077 | reserveUSD_not: BigDecimal 1078 | reserveUSD_not_in: [BigDecimal!] 1079 | token0: String 1080 | token0_contains: String 1081 | token0_ends_with: String 1082 | token0_gt: String 1083 | token0_gte: String 1084 | token0_in: [String!] 1085 | token0_lt: String 1086 | token0_lte: String 1087 | token0_not: String 1088 | token0_not_contains: String 1089 | token0_not_ends_with: String 1090 | token0_not_in: [String!] 1091 | token0_not_starts_with: String 1092 | token0_starts_with: String 1093 | token1: String 1094 | token1_contains: String 1095 | token1_ends_with: String 1096 | token1_gt: String 1097 | token1_gte: String 1098 | token1_in: [String!] 1099 | token1_lt: String 1100 | token1_lte: String 1101 | token1_not: String 1102 | token1_not_contains: String 1103 | token1_not_ends_with: String 1104 | token1_not_in: [String!] 1105 | token1_not_starts_with: String 1106 | token1_starts_with: String 1107 | } 1108 | 1109 | input Pair_filter { 1110 | createdAtBlockNumber: BigInt 1111 | createdAtBlockNumber_gt: BigInt 1112 | createdAtBlockNumber_gte: BigInt 1113 | createdAtBlockNumber_in: [BigInt!] 1114 | createdAtBlockNumber_lt: BigInt 1115 | createdAtBlockNumber_lte: BigInt 1116 | createdAtBlockNumber_not: BigInt 1117 | createdAtBlockNumber_not_in: [BigInt!] 1118 | createdAtTimestamp: BigInt 1119 | createdAtTimestamp_gt: BigInt 1120 | createdAtTimestamp_gte: BigInt 1121 | createdAtTimestamp_in: [BigInt!] 1122 | createdAtTimestamp_lt: BigInt 1123 | createdAtTimestamp_lte: BigInt 1124 | createdAtTimestamp_not: BigInt 1125 | createdAtTimestamp_not_in: [BigInt!] 1126 | id: ID 1127 | id_gt: ID 1128 | id_gte: ID 1129 | id_in: [ID!] 1130 | id_lt: ID 1131 | id_lte: ID 1132 | id_not: ID 1133 | id_not_in: [ID!] 1134 | reserve0: BigDecimal 1135 | reserve0_gt: BigDecimal 1136 | reserve0_gte: BigDecimal 1137 | reserve0_in: [BigDecimal!] 1138 | reserve0_lt: BigDecimal 1139 | reserve0_lte: BigDecimal 1140 | reserve0_not: BigDecimal 1141 | reserve0_not_in: [BigDecimal!] 1142 | reserve1: BigDecimal 1143 | reserve1_gt: BigDecimal 1144 | reserve1_gte: BigDecimal 1145 | reserve1_in: [BigDecimal!] 1146 | reserve1_lt: BigDecimal 1147 | reserve1_lte: BigDecimal 1148 | reserve1_not: BigDecimal 1149 | reserve1_not_in: [BigDecimal!] 1150 | reserveETH: BigDecimal 1151 | reserveETH_gt: BigDecimal 1152 | reserveETH_gte: BigDecimal 1153 | reserveETH_in: [BigDecimal!] 1154 | reserveETH_lt: BigDecimal 1155 | reserveETH_lte: BigDecimal 1156 | reserveETH_not: BigDecimal 1157 | reserveETH_not_in: [BigDecimal!] 1158 | reserveUSD: BigDecimal 1159 | reserveUSD_gt: BigDecimal 1160 | reserveUSD_gte: BigDecimal 1161 | reserveUSD_in: [BigDecimal!] 1162 | reserveUSD_lt: BigDecimal 1163 | reserveUSD_lte: BigDecimal 1164 | reserveUSD_not: BigDecimal 1165 | reserveUSD_not_in: [BigDecimal!] 1166 | token0: String 1167 | token0Price: BigDecimal 1168 | token0Price_gt: BigDecimal 1169 | token0Price_gte: BigDecimal 1170 | token0Price_in: [BigDecimal!] 1171 | token0Price_lt: BigDecimal 1172 | token0Price_lte: BigDecimal 1173 | token0Price_not: BigDecimal 1174 | token0Price_not_in: [BigDecimal!] 1175 | token0_contains: String 1176 | token0_ends_with: String 1177 | token0_gt: String 1178 | token0_gte: String 1179 | token0_in: [String!] 1180 | token0_lt: String 1181 | token0_lte: String 1182 | token0_not: String 1183 | token0_not_contains: String 1184 | token0_not_ends_with: String 1185 | token0_not_in: [String!] 1186 | token0_not_starts_with: String 1187 | token0_starts_with: String 1188 | token1: String 1189 | token1Price: BigDecimal 1190 | token1Price_gt: BigDecimal 1191 | token1Price_gte: BigDecimal 1192 | token1Price_in: [BigDecimal!] 1193 | token1Price_lt: BigDecimal 1194 | token1Price_lte: BigDecimal 1195 | token1Price_not: BigDecimal 1196 | token1Price_not_in: [BigDecimal!] 1197 | token1_contains: String 1198 | token1_ends_with: String 1199 | token1_gt: String 1200 | token1_gte: String 1201 | token1_in: [String!] 1202 | token1_lt: String 1203 | token1_lte: String 1204 | token1_not: String 1205 | token1_not_contains: String 1206 | token1_not_ends_with: String 1207 | token1_not_in: [String!] 1208 | token1_not_starts_with: String 1209 | token1_starts_with: String 1210 | totalSupply: BigDecimal 1211 | totalSupply_gt: BigDecimal 1212 | totalSupply_gte: BigDecimal 1213 | totalSupply_in: [BigDecimal!] 1214 | totalSupply_lt: BigDecimal 1215 | totalSupply_lte: BigDecimal 1216 | totalSupply_not: BigDecimal 1217 | totalSupply_not_in: [BigDecimal!] 1218 | trackedReserveETH: BigDecimal 1219 | trackedReserveETH_gt: BigDecimal 1220 | trackedReserveETH_gte: BigDecimal 1221 | trackedReserveETH_in: [BigDecimal!] 1222 | trackedReserveETH_lt: BigDecimal 1223 | trackedReserveETH_lte: BigDecimal 1224 | trackedReserveETH_not: BigDecimal 1225 | trackedReserveETH_not_in: [BigDecimal!] 1226 | txCount: BigInt 1227 | txCount_gt: BigInt 1228 | txCount_gte: BigInt 1229 | txCount_in: [BigInt!] 1230 | txCount_lt: BigInt 1231 | txCount_lte: BigInt 1232 | txCount_not: BigInt 1233 | txCount_not_in: [BigInt!] 1234 | volumeToken0: BigDecimal 1235 | volumeToken0_gt: BigDecimal 1236 | volumeToken0_gte: BigDecimal 1237 | volumeToken0_in: [BigDecimal!] 1238 | volumeToken0_lt: BigDecimal 1239 | volumeToken0_lte: BigDecimal 1240 | volumeToken0_not: BigDecimal 1241 | volumeToken0_not_in: [BigDecimal!] 1242 | volumeToken1: BigDecimal 1243 | volumeToken1_gt: BigDecimal 1244 | volumeToken1_gte: BigDecimal 1245 | volumeToken1_in: [BigDecimal!] 1246 | volumeToken1_lt: BigDecimal 1247 | volumeToken1_lte: BigDecimal 1248 | volumeToken1_not: BigDecimal 1249 | volumeToken1_not_in: [BigDecimal!] 1250 | volumeUSD: BigDecimal 1251 | volumeUSD_gt: BigDecimal 1252 | volumeUSD_gte: BigDecimal 1253 | volumeUSD_in: [BigDecimal!] 1254 | volumeUSD_lt: BigDecimal 1255 | volumeUSD_lte: BigDecimal 1256 | volumeUSD_not: BigDecimal 1257 | volumeUSD_not_in: [BigDecimal!] 1258 | } 1259 | 1260 | input Swap_filter { 1261 | amount0In: BigDecimal 1262 | amount0In_gt: BigDecimal 1263 | amount0In_gte: BigDecimal 1264 | amount0In_in: [BigDecimal!] 1265 | amount0In_lt: BigDecimal 1266 | amount0In_lte: BigDecimal 1267 | amount0In_not: BigDecimal 1268 | amount0In_not_in: [BigDecimal!] 1269 | amount0Out: BigDecimal 1270 | amount0Out_gt: BigDecimal 1271 | amount0Out_gte: BigDecimal 1272 | amount0Out_in: [BigDecimal!] 1273 | amount0Out_lt: BigDecimal 1274 | amount0Out_lte: BigDecimal 1275 | amount0Out_not: BigDecimal 1276 | amount0Out_not_in: [BigDecimal!] 1277 | amount1In: BigDecimal 1278 | amount1In_gt: BigDecimal 1279 | amount1In_gte: BigDecimal 1280 | amount1In_in: [BigDecimal!] 1281 | amount1In_lt: BigDecimal 1282 | amount1In_lte: BigDecimal 1283 | amount1In_not: BigDecimal 1284 | amount1In_not_in: [BigDecimal!] 1285 | amount1Out: BigDecimal 1286 | amount1Out_gt: BigDecimal 1287 | amount1Out_gte: BigDecimal 1288 | amount1Out_in: [BigDecimal!] 1289 | amount1Out_lt: BigDecimal 1290 | amount1Out_lte: BigDecimal 1291 | amount1Out_not: BigDecimal 1292 | amount1Out_not_in: [BigDecimal!] 1293 | amountUSD: BigDecimal 1294 | amountUSD_gt: BigDecimal 1295 | amountUSD_gte: BigDecimal 1296 | amountUSD_in: [BigDecimal!] 1297 | amountUSD_lt: BigDecimal 1298 | amountUSD_lte: BigDecimal 1299 | amountUSD_not: BigDecimal 1300 | amountUSD_not_in: [BigDecimal!] 1301 | id: ID 1302 | id_gt: ID 1303 | id_gte: ID 1304 | id_in: [ID!] 1305 | id_lt: ID 1306 | id_lte: ID 1307 | id_not: ID 1308 | id_not_in: [ID!] 1309 | logIndex: BigInt 1310 | logIndex_gt: BigInt 1311 | logIndex_gte: BigInt 1312 | logIndex_in: [BigInt!] 1313 | logIndex_lt: BigInt 1314 | logIndex_lte: BigInt 1315 | logIndex_not: BigInt 1316 | logIndex_not_in: [BigInt!] 1317 | pair: String 1318 | pair_contains: String 1319 | pair_ends_with: String 1320 | pair_gt: String 1321 | pair_gte: String 1322 | pair_in: [String!] 1323 | pair_lt: String 1324 | pair_lte: String 1325 | pair_not: String 1326 | pair_not_contains: String 1327 | pair_not_ends_with: String 1328 | pair_not_in: [String!] 1329 | pair_not_starts_with: String 1330 | pair_starts_with: String 1331 | sender: Bytes 1332 | sender_contains: Bytes 1333 | sender_in: [Bytes!] 1334 | sender_not: Bytes 1335 | sender_not_contains: Bytes 1336 | sender_not_in: [Bytes!] 1337 | timestamp: BigInt 1338 | timestamp_gt: BigInt 1339 | timestamp_gte: BigInt 1340 | timestamp_in: [BigInt!] 1341 | timestamp_lt: BigInt 1342 | timestamp_lte: BigInt 1343 | timestamp_not: BigInt 1344 | timestamp_not_in: [BigInt!] 1345 | to: Bytes 1346 | to_contains: Bytes 1347 | to_in: [Bytes!] 1348 | to_not: Bytes 1349 | to_not_contains: Bytes 1350 | to_not_in: [Bytes!] 1351 | } 1352 | 1353 | input TokenDayData_filter { 1354 | dailyTxns: BigInt 1355 | dailyTxns_gt: BigInt 1356 | dailyTxns_gte: BigInt 1357 | dailyTxns_in: [BigInt!] 1358 | dailyTxns_lt: BigInt 1359 | dailyTxns_lte: BigInt 1360 | dailyTxns_not: BigInt 1361 | dailyTxns_not_in: [BigInt!] 1362 | dailyVolumeETH: BigDecimal 1363 | dailyVolumeETH_gt: BigDecimal 1364 | dailyVolumeETH_gte: BigDecimal 1365 | dailyVolumeETH_in: [BigDecimal!] 1366 | dailyVolumeETH_lt: BigDecimal 1367 | dailyVolumeETH_lte: BigDecimal 1368 | dailyVolumeETH_not: BigDecimal 1369 | dailyVolumeETH_not_in: [BigDecimal!] 1370 | dailyVolumeToken: BigDecimal 1371 | dailyVolumeToken_gt: BigDecimal 1372 | dailyVolumeToken_gte: BigDecimal 1373 | dailyVolumeToken_in: [BigDecimal!] 1374 | dailyVolumeToken_lt: BigDecimal 1375 | dailyVolumeToken_lte: BigDecimal 1376 | dailyVolumeToken_not: BigDecimal 1377 | dailyVolumeToken_not_in: [BigDecimal!] 1378 | dailyVolumeUSD: BigDecimal 1379 | dailyVolumeUSD_gt: BigDecimal 1380 | dailyVolumeUSD_gte: BigDecimal 1381 | dailyVolumeUSD_in: [BigDecimal!] 1382 | dailyVolumeUSD_lt: BigDecimal 1383 | dailyVolumeUSD_lte: BigDecimal 1384 | dailyVolumeUSD_not: BigDecimal 1385 | dailyVolumeUSD_not_in: [BigDecimal!] 1386 | date: Int 1387 | date_gt: Int 1388 | date_gte: Int 1389 | date_in: [Int!] 1390 | date_lt: Int 1391 | date_lte: Int 1392 | date_not: Int 1393 | date_not_in: [Int!] 1394 | id: ID 1395 | id_gt: ID 1396 | id_gte: ID 1397 | id_in: [ID!] 1398 | id_lt: ID 1399 | id_lte: ID 1400 | id_not: ID 1401 | id_not_in: [ID!] 1402 | maxStored: Int 1403 | maxStored_gt: Int 1404 | maxStored_gte: Int 1405 | maxStored_in: [Int!] 1406 | maxStored_lt: Int 1407 | maxStored_lte: Int 1408 | maxStored_not: Int 1409 | maxStored_not_in: [Int!] 1410 | mostLiquidPairs: [String!] 1411 | mostLiquidPairs_contains: [String!] 1412 | mostLiquidPairs_not: [String!] 1413 | mostLiquidPairs_not_contains: [String!] 1414 | priceUSD: BigDecimal 1415 | priceUSD_gt: BigDecimal 1416 | priceUSD_gte: BigDecimal 1417 | priceUSD_in: [BigDecimal!] 1418 | priceUSD_lt: BigDecimal 1419 | priceUSD_lte: BigDecimal 1420 | priceUSD_not: BigDecimal 1421 | priceUSD_not_in: [BigDecimal!] 1422 | token: String 1423 | token_contains: String 1424 | token_ends_with: String 1425 | token_gt: String 1426 | token_gte: String 1427 | token_in: [String!] 1428 | token_lt: String 1429 | token_lte: String 1430 | token_not: String 1431 | token_not_contains: String 1432 | token_not_ends_with: String 1433 | token_not_in: [String!] 1434 | token_not_starts_with: String 1435 | token_starts_with: String 1436 | totalLiquidityETH: BigDecimal 1437 | totalLiquidityETH_gt: BigDecimal 1438 | totalLiquidityETH_gte: BigDecimal 1439 | totalLiquidityETH_in: [BigDecimal!] 1440 | totalLiquidityETH_lt: BigDecimal 1441 | totalLiquidityETH_lte: BigDecimal 1442 | totalLiquidityETH_not: BigDecimal 1443 | totalLiquidityETH_not_in: [BigDecimal!] 1444 | totalLiquidityToken: BigDecimal 1445 | totalLiquidityToken_gt: BigDecimal 1446 | totalLiquidityToken_gte: BigDecimal 1447 | totalLiquidityToken_in: [BigDecimal!] 1448 | totalLiquidityToken_lt: BigDecimal 1449 | totalLiquidityToken_lte: BigDecimal 1450 | totalLiquidityToken_not: BigDecimal 1451 | totalLiquidityToken_not_in: [BigDecimal!] 1452 | totalLiquidityUSD: BigDecimal 1453 | totalLiquidityUSD_gt: BigDecimal 1454 | totalLiquidityUSD_gte: BigDecimal 1455 | totalLiquidityUSD_in: [BigDecimal!] 1456 | totalLiquidityUSD_lt: BigDecimal 1457 | totalLiquidityUSD_lte: BigDecimal 1458 | totalLiquidityUSD_not: BigDecimal 1459 | totalLiquidityUSD_not_in: [BigDecimal!] 1460 | } 1461 | 1462 | input Token_filter { 1463 | allPairs: [String!] 1464 | allPairs_contains: [String!] 1465 | allPairs_not: [String!] 1466 | allPairs_not_contains: [String!] 1467 | decimals: BigInt 1468 | decimals_gt: BigInt 1469 | decimals_gte: BigInt 1470 | decimals_in: [BigInt!] 1471 | decimals_lt: BigInt 1472 | decimals_lte: BigInt 1473 | decimals_not: BigInt 1474 | decimals_not_in: [BigInt!] 1475 | derivedETH: BigDecimal 1476 | derivedETH_gt: BigDecimal 1477 | derivedETH_gte: BigDecimal 1478 | derivedETH_in: [BigDecimal!] 1479 | derivedETH_lt: BigDecimal 1480 | derivedETH_lte: BigDecimal 1481 | derivedETH_not: BigDecimal 1482 | derivedETH_not_in: [BigDecimal!] 1483 | id: ID 1484 | id_gt: ID 1485 | id_gte: ID 1486 | id_in: [ID!] 1487 | id_lt: ID 1488 | id_lte: ID 1489 | id_not: ID 1490 | id_not_in: [ID!] 1491 | mostLiquidPairs: [String!] 1492 | mostLiquidPairs_contains: [String!] 1493 | mostLiquidPairs_not: [String!] 1494 | mostLiquidPairs_not_contains: [String!] 1495 | name: String 1496 | name_contains: String 1497 | name_ends_with: String 1498 | name_gt: String 1499 | name_gte: String 1500 | name_in: [String!] 1501 | name_lt: String 1502 | name_lte: String 1503 | name_not: String 1504 | name_not_contains: String 1505 | name_not_ends_with: String 1506 | name_not_in: [String!] 1507 | name_not_starts_with: String 1508 | name_starts_with: String 1509 | symbol: String 1510 | symbol_contains: String 1511 | symbol_ends_with: String 1512 | symbol_gt: String 1513 | symbol_gte: String 1514 | symbol_in: [String!] 1515 | symbol_lt: String 1516 | symbol_lte: String 1517 | symbol_not: String 1518 | symbol_not_contains: String 1519 | symbol_not_ends_with: String 1520 | symbol_not_in: [String!] 1521 | symbol_not_starts_with: String 1522 | symbol_starts_with: String 1523 | totalLiquidity: BigDecimal 1524 | totalLiquidity_gt: BigDecimal 1525 | totalLiquidity_gte: BigDecimal 1526 | totalLiquidity_in: [BigDecimal!] 1527 | totalLiquidity_lt: BigDecimal 1528 | totalLiquidity_lte: BigDecimal 1529 | totalLiquidity_not: BigDecimal 1530 | totalLiquidity_not_in: [BigDecimal!] 1531 | tradeVolume: BigDecimal 1532 | tradeVolumeUSD: BigDecimal 1533 | tradeVolumeUSD_gt: BigDecimal 1534 | tradeVolumeUSD_gte: BigDecimal 1535 | tradeVolumeUSD_in: [BigDecimal!] 1536 | tradeVolumeUSD_lt: BigDecimal 1537 | tradeVolumeUSD_lte: BigDecimal 1538 | tradeVolumeUSD_not: BigDecimal 1539 | tradeVolumeUSD_not_in: [BigDecimal!] 1540 | tradeVolume_gt: BigDecimal 1541 | tradeVolume_gte: BigDecimal 1542 | tradeVolume_in: [BigDecimal!] 1543 | tradeVolume_lt: BigDecimal 1544 | tradeVolume_lte: BigDecimal 1545 | tradeVolume_not: BigDecimal 1546 | tradeVolume_not_in: [BigDecimal!] 1547 | txCount: BigInt 1548 | txCount_gt: BigInt 1549 | txCount_gte: BigInt 1550 | txCount_in: [BigInt!] 1551 | txCount_lt: BigInt 1552 | txCount_lte: BigInt 1553 | txCount_not: BigInt 1554 | txCount_not_in: [BigInt!] 1555 | } 1556 | 1557 | input Transaction_filter { 1558 | blockNumber: BigInt 1559 | blockNumber_gt: BigInt 1560 | blockNumber_gte: BigInt 1561 | blockNumber_in: [BigInt!] 1562 | blockNumber_lt: BigInt 1563 | blockNumber_lte: BigInt 1564 | blockNumber_not: BigInt 1565 | blockNumber_not_in: [BigInt!] 1566 | burns: [String!] 1567 | burns_contains: [String!] 1568 | burns_not: [String!] 1569 | burns_not_contains: [String!] 1570 | id: ID 1571 | id_gt: ID 1572 | id_gte: ID 1573 | id_in: [ID!] 1574 | id_lt: ID 1575 | id_lte: ID 1576 | id_not: ID 1577 | id_not_in: [ID!] 1578 | mints: [String!] 1579 | mints_contains: [String!] 1580 | mints_not: [String!] 1581 | mints_not_contains: [String!] 1582 | swaps: [String!] 1583 | swaps_contains: [String!] 1584 | swaps_not: [String!] 1585 | swaps_not_contains: [String!] 1586 | timestamp: BigInt 1587 | timestamp_gt: BigInt 1588 | timestamp_gte: BigInt 1589 | timestamp_in: [BigInt!] 1590 | timestamp_lt: BigInt 1591 | timestamp_lte: BigInt 1592 | timestamp_not: BigInt 1593 | timestamp_not_in: [BigInt!] 1594 | } 1595 | 1596 | input UniswapDayData_filter { 1597 | dailyVolumeETH: BigDecimal 1598 | dailyVolumeETH_gt: BigDecimal 1599 | dailyVolumeETH_gte: BigDecimal 1600 | dailyVolumeETH_in: [BigDecimal!] 1601 | dailyVolumeETH_lt: BigDecimal 1602 | dailyVolumeETH_lte: BigDecimal 1603 | dailyVolumeETH_not: BigDecimal 1604 | dailyVolumeETH_not_in: [BigDecimal!] 1605 | dailyVolumeUSD: BigDecimal 1606 | dailyVolumeUSD_gt: BigDecimal 1607 | dailyVolumeUSD_gte: BigDecimal 1608 | dailyVolumeUSD_in: [BigDecimal!] 1609 | dailyVolumeUSD_lt: BigDecimal 1610 | dailyVolumeUSD_lte: BigDecimal 1611 | dailyVolumeUSD_not: BigDecimal 1612 | dailyVolumeUSD_not_in: [BigDecimal!] 1613 | date: Int 1614 | date_gt: Int 1615 | date_gte: Int 1616 | date_in: [Int!] 1617 | date_lt: Int 1618 | date_lte: Int 1619 | date_not: Int 1620 | date_not_in: [Int!] 1621 | id: ID 1622 | id_gt: ID 1623 | id_gte: ID 1624 | id_in: [ID!] 1625 | id_lt: ID 1626 | id_lte: ID 1627 | id_not: ID 1628 | id_not_in: [ID!] 1629 | maxStored: Int 1630 | maxStored_gt: Int 1631 | maxStored_gte: Int 1632 | maxStored_in: [Int!] 1633 | maxStored_lt: Int 1634 | maxStored_lte: Int 1635 | maxStored_not: Int 1636 | maxStored_not_in: [Int!] 1637 | mostLiquidTokens: [String!] 1638 | mostLiquidTokens_contains: [String!] 1639 | mostLiquidTokens_not: [String!] 1640 | mostLiquidTokens_not_contains: [String!] 1641 | totalLiquidityETH: BigDecimal 1642 | totalLiquidityETH_gt: BigDecimal 1643 | totalLiquidityETH_gte: BigDecimal 1644 | totalLiquidityETH_in: [BigDecimal!] 1645 | totalLiquidityETH_lt: BigDecimal 1646 | totalLiquidityETH_lte: BigDecimal 1647 | totalLiquidityETH_not: BigDecimal 1648 | totalLiquidityETH_not_in: [BigDecimal!] 1649 | totalLiquidityUSD: BigDecimal 1650 | totalLiquidityUSD_gt: BigDecimal 1651 | totalLiquidityUSD_gte: BigDecimal 1652 | totalLiquidityUSD_in: [BigDecimal!] 1653 | totalLiquidityUSD_lt: BigDecimal 1654 | totalLiquidityUSD_lte: BigDecimal 1655 | totalLiquidityUSD_not: BigDecimal 1656 | totalLiquidityUSD_not_in: [BigDecimal!] 1657 | totalVolumeETH: BigDecimal 1658 | totalVolumeETH_gt: BigDecimal 1659 | totalVolumeETH_gte: BigDecimal 1660 | totalVolumeETH_in: [BigDecimal!] 1661 | totalVolumeETH_lt: BigDecimal 1662 | totalVolumeETH_lte: BigDecimal 1663 | totalVolumeETH_not: BigDecimal 1664 | totalVolumeETH_not_in: [BigDecimal!] 1665 | totalVolumeUSD: BigDecimal 1666 | totalVolumeUSD_gt: BigDecimal 1667 | totalVolumeUSD_gte: BigDecimal 1668 | totalVolumeUSD_in: [BigDecimal!] 1669 | totalVolumeUSD_lt: BigDecimal 1670 | totalVolumeUSD_lte: BigDecimal 1671 | totalVolumeUSD_not: BigDecimal 1672 | totalVolumeUSD_not_in: [BigDecimal!] 1673 | txCount: BigInt 1674 | txCount_gt: BigInt 1675 | txCount_gte: BigInt 1676 | txCount_in: [BigInt!] 1677 | txCount_lt: BigInt 1678 | txCount_lte: BigInt 1679 | txCount_not: BigInt 1680 | txCount_not_in: [BigInt!] 1681 | } 1682 | 1683 | input UniswapFactory_filter { 1684 | id: ID 1685 | id_gt: ID 1686 | id_gte: ID 1687 | id_in: [ID!] 1688 | id_lt: ID 1689 | id_lte: ID 1690 | id_not: ID 1691 | id_not_in: [ID!] 1692 | mostLiquidTokens: [String!] 1693 | mostLiquidTokens_contains: [String!] 1694 | mostLiquidTokens_not: [String!] 1695 | mostLiquidTokens_not_contains: [String!] 1696 | pairCount: Int 1697 | pairCount_gt: Int 1698 | pairCount_gte: Int 1699 | pairCount_in: [Int!] 1700 | pairCount_lt: Int 1701 | pairCount_lte: Int 1702 | pairCount_not: Int 1703 | pairCount_not_in: [Int!] 1704 | pairs: [String!] 1705 | pairs_contains: [String!] 1706 | pairs_not: [String!] 1707 | pairs_not_contains: [String!] 1708 | totalLiquidityETH: BigDecimal 1709 | totalLiquidityETH_gt: BigDecimal 1710 | totalLiquidityETH_gte: BigDecimal 1711 | totalLiquidityETH_in: [BigDecimal!] 1712 | totalLiquidityETH_lt: BigDecimal 1713 | totalLiquidityETH_lte: BigDecimal 1714 | totalLiquidityETH_not: BigDecimal 1715 | totalLiquidityETH_not_in: [BigDecimal!] 1716 | totalLiquidityUSD: BigDecimal 1717 | totalLiquidityUSD_gt: BigDecimal 1718 | totalLiquidityUSD_gte: BigDecimal 1719 | totalLiquidityUSD_in: [BigDecimal!] 1720 | totalLiquidityUSD_lt: BigDecimal 1721 | totalLiquidityUSD_lte: BigDecimal 1722 | totalLiquidityUSD_not: BigDecimal 1723 | totalLiquidityUSD_not_in: [BigDecimal!] 1724 | totalVolumeETH: BigDecimal 1725 | totalVolumeETH_gt: BigDecimal 1726 | totalVolumeETH_gte: BigDecimal 1727 | totalVolumeETH_in: [BigDecimal!] 1728 | totalVolumeETH_lt: BigDecimal 1729 | totalVolumeETH_lte: BigDecimal 1730 | totalVolumeETH_not: BigDecimal 1731 | totalVolumeETH_not_in: [BigDecimal!] 1732 | totalVolumeUSD: BigDecimal 1733 | totalVolumeUSD_gt: BigDecimal 1734 | totalVolumeUSD_gte: BigDecimal 1735 | totalVolumeUSD_in: [BigDecimal!] 1736 | totalVolumeUSD_lt: BigDecimal 1737 | totalVolumeUSD_lte: BigDecimal 1738 | totalVolumeUSD_not: BigDecimal 1739 | totalVolumeUSD_not_in: [BigDecimal!] 1740 | txCount: BigInt 1741 | txCount_gt: BigInt 1742 | txCount_gte: BigInt 1743 | txCount_in: [BigInt!] 1744 | txCount_lt: BigInt 1745 | txCount_lte: BigInt 1746 | txCount_not: BigInt 1747 | txCount_not_in: [BigInt!] 1748 | } 1749 | 1750 | input User_filter { 1751 | id: ID 1752 | id_gt: ID 1753 | id_gte: ID 1754 | id_in: [ID!] 1755 | id_lt: ID 1756 | id_lte: ID 1757 | id_not: ID 1758 | id_not_in: [ID!] 1759 | } 1760 | 1761 | 1762 | scalar BigDecimal 1763 | 1764 | scalar BigInt 1765 | 1766 | scalar Bytes -------------------------------------------------------------------------------- /src/v2/assets.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from '@ethersproject/address' 2 | import { APIGatewayProxyHandler } from 'aws-lambda' 3 | 4 | import { getTopPairs, Pair } from './_shared' 5 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 6 | 7 | interface ReturnShape { 8 | [tokenAddress: string]: { id: string; name: string; symbol: string; maker_fee: '0'; taker_fee: '0.003' } 9 | } 10 | 11 | export const handler: APIGatewayProxyHandler = async () => { 12 | try { 13 | const pairs = await getTopPairs() 14 | const tokens = pairs.reduce<{ 15 | [tokenAddress: string]: { id: string; name: string; symbol: string; maker_fee: '0'; taker_fee: '0.003' } 16 | }>((memo: ReturnShape, pair: Pair): ReturnShape => { 17 | for (let token of [pair.token0, pair.token1]) { 18 | const id = getAddress(token.id) 19 | if (memo[id]) continue 20 | memo[id] = { 21 | id, 22 | name: token.name, 23 | symbol: token.symbol, 24 | maker_fee: '0', 25 | taker_fee: '0.003' 26 | } 27 | } 28 | return memo 29 | }, {}) 30 | return createSuccessResponse(tokens) 31 | } catch (error) { 32 | return createServerErrorResponse(error) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/v2/blocks/.graphqlconfig: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ethereum Blocks", 3 | "schemaPath": "schema.graphql", 4 | "extensions": { 5 | "endpoints": { 6 | "Ethereum Blocks": { 7 | "url": "https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks", 8 | "headers": { 9 | "user-agent": "JS GraphQL" 10 | }, 11 | "introspect": false 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/v2/blocks/client.ts: -------------------------------------------------------------------------------- 1 | import { InMemoryCache } from 'apollo-cache-inmemory' 2 | import { ApolloClient } from 'apollo-client' 3 | import { HttpLink } from 'apollo-link-http' 4 | import fetch from 'node-fetch' 5 | 6 | export const blockClient = new ApolloClient({ 7 | link: new HttpLink({ 8 | fetch, 9 | uri: 'https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks' 10 | }), 11 | cache: new InMemoryCache() 12 | }) 13 | -------------------------------------------------------------------------------- /src/v2/blocks/queries.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag' 2 | import { blockClient } from './client' 3 | 4 | export const GET_BLOCK = gql` 5 | query blocks($timestamp: BigInt!) { 6 | blocks(first: 1, orderBy: timestamp, orderDirection: asc, where: { timestamp_gt: $timestamp }) { 7 | id 8 | number 9 | timestamp 10 | } 11 | } 12 | ` 13 | 14 | /** 15 | * Returns the block corresponding to a given epoch timestamp (seconds) 16 | * @param timestamp epoch timestamp in seconds 17 | */ 18 | export async function getBlockFromTimestamp(timestamp: number): Promise { 19 | const result = await blockClient.query({ 20 | query: GET_BLOCK, 21 | variables: { 22 | timestamp: '' + timestamp 23 | }, 24 | fetchPolicy: 'cache-first' 25 | }) 26 | return result?.data?.blocks?.[0]?.number 27 | } 28 | -------------------------------------------------------------------------------- /src/v2/blocks/schema.graphql: -------------------------------------------------------------------------------- 1 | # This file was generated based on ".graphqlconfig". Do not edit manually. 2 | 3 | schema { 4 | query: Query 5 | subscription: Subscription 6 | } 7 | 8 | type Block { 9 | author: String 10 | difficulty: BigInt 11 | gasLimit: BigInt 12 | gasUsed: BigInt 13 | id: ID! 14 | number: BigInt! 15 | parentHash: String 16 | receiptsRoot: String 17 | size: BigInt 18 | stateRoot: String 19 | timestamp: BigInt! 20 | totalDifficulty: BigInt 21 | transactionsRoot: String 22 | unclesHash: String 23 | } 24 | 25 | type Query { 26 | block( 27 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 28 | block: Block_height, 29 | id: ID! 30 | ): Block 31 | blocks( 32 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 33 | block: Block_height, 34 | first: Int = 100, 35 | orderBy: Block_orderBy, 36 | orderDirection: OrderDirection, 37 | skip: Int = 0, 38 | where: Block_filter 39 | ): [Block!]! 40 | } 41 | 42 | type Subscription { 43 | block( 44 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 45 | block: Block_height, 46 | id: ID! 47 | ): Block 48 | blocks( 49 | "The block at which the query should be executed. Can either be an `{ number: Int }` containing the block number or a `{ hash: Bytes }` value containing a block hash. Defaults to the latest block when omitted." 50 | block: Block_height, 51 | first: Int = 100, 52 | orderBy: Block_orderBy, 53 | orderDirection: OrderDirection, 54 | skip: Int = 0, 55 | where: Block_filter 56 | ): [Block!]! 57 | } 58 | 59 | enum Block_orderBy { 60 | author 61 | difficulty 62 | gasLimit 63 | gasUsed 64 | id 65 | number 66 | parentHash 67 | receiptsRoot 68 | size 69 | stateRoot 70 | timestamp 71 | totalDifficulty 72 | transactionsRoot 73 | unclesHash 74 | } 75 | 76 | enum OrderDirection { 77 | asc 78 | desc 79 | } 80 | 81 | input Block_filter { 82 | author: String 83 | author_contains: String 84 | author_ends_with: String 85 | author_gt: String 86 | author_gte: String 87 | author_in: [String!] 88 | author_lt: String 89 | author_lte: String 90 | author_not: String 91 | author_not_contains: String 92 | author_not_ends_with: String 93 | author_not_in: [String!] 94 | author_not_starts_with: String 95 | author_starts_with: String 96 | difficulty: BigInt 97 | difficulty_gt: BigInt 98 | difficulty_gte: BigInt 99 | difficulty_in: [BigInt!] 100 | difficulty_lt: BigInt 101 | difficulty_lte: BigInt 102 | difficulty_not: BigInt 103 | difficulty_not_in: [BigInt!] 104 | gasLimit: BigInt 105 | gasLimit_gt: BigInt 106 | gasLimit_gte: BigInt 107 | gasLimit_in: [BigInt!] 108 | gasLimit_lt: BigInt 109 | gasLimit_lte: BigInt 110 | gasLimit_not: BigInt 111 | gasLimit_not_in: [BigInt!] 112 | gasUsed: BigInt 113 | gasUsed_gt: BigInt 114 | gasUsed_gte: BigInt 115 | gasUsed_in: [BigInt!] 116 | gasUsed_lt: BigInt 117 | gasUsed_lte: BigInt 118 | gasUsed_not: BigInt 119 | gasUsed_not_in: [BigInt!] 120 | id: ID 121 | id_gt: ID 122 | id_gte: ID 123 | id_in: [ID!] 124 | id_lt: ID 125 | id_lte: ID 126 | id_not: ID 127 | id_not_in: [ID!] 128 | number: BigInt 129 | number_gt: BigInt 130 | number_gte: BigInt 131 | number_in: [BigInt!] 132 | number_lt: BigInt 133 | number_lte: BigInt 134 | number_not: BigInt 135 | number_not_in: [BigInt!] 136 | parentHash: String 137 | parentHash_contains: String 138 | parentHash_ends_with: String 139 | parentHash_gt: String 140 | parentHash_gte: String 141 | parentHash_in: [String!] 142 | parentHash_lt: String 143 | parentHash_lte: String 144 | parentHash_not: String 145 | parentHash_not_contains: String 146 | parentHash_not_ends_with: String 147 | parentHash_not_in: [String!] 148 | parentHash_not_starts_with: String 149 | parentHash_starts_with: String 150 | receiptsRoot: String 151 | receiptsRoot_contains: String 152 | receiptsRoot_ends_with: String 153 | receiptsRoot_gt: String 154 | receiptsRoot_gte: String 155 | receiptsRoot_in: [String!] 156 | receiptsRoot_lt: String 157 | receiptsRoot_lte: String 158 | receiptsRoot_not: String 159 | receiptsRoot_not_contains: String 160 | receiptsRoot_not_ends_with: String 161 | receiptsRoot_not_in: [String!] 162 | receiptsRoot_not_starts_with: String 163 | receiptsRoot_starts_with: String 164 | size: BigInt 165 | size_gt: BigInt 166 | size_gte: BigInt 167 | size_in: [BigInt!] 168 | size_lt: BigInt 169 | size_lte: BigInt 170 | size_not: BigInt 171 | size_not_in: [BigInt!] 172 | stateRoot: String 173 | stateRoot_contains: String 174 | stateRoot_ends_with: String 175 | stateRoot_gt: String 176 | stateRoot_gte: String 177 | stateRoot_in: [String!] 178 | stateRoot_lt: String 179 | stateRoot_lte: String 180 | stateRoot_not: String 181 | stateRoot_not_contains: String 182 | stateRoot_not_ends_with: String 183 | stateRoot_not_in: [String!] 184 | stateRoot_not_starts_with: String 185 | stateRoot_starts_with: String 186 | timestamp: BigInt 187 | timestamp_gt: BigInt 188 | timestamp_gte: BigInt 189 | timestamp_in: [BigInt!] 190 | timestamp_lt: BigInt 191 | timestamp_lte: BigInt 192 | timestamp_not: BigInt 193 | timestamp_not_in: [BigInt!] 194 | totalDifficulty: BigInt 195 | totalDifficulty_gt: BigInt 196 | totalDifficulty_gte: BigInt 197 | totalDifficulty_in: [BigInt!] 198 | totalDifficulty_lt: BigInt 199 | totalDifficulty_lte: BigInt 200 | totalDifficulty_not: BigInt 201 | totalDifficulty_not_in: [BigInt!] 202 | transactionsRoot: String 203 | transactionsRoot_contains: String 204 | transactionsRoot_ends_with: String 205 | transactionsRoot_gt: String 206 | transactionsRoot_gte: String 207 | transactionsRoot_in: [String!] 208 | transactionsRoot_lt: String 209 | transactionsRoot_lte: String 210 | transactionsRoot_not: String 211 | transactionsRoot_not_contains: String 212 | transactionsRoot_not_ends_with: String 213 | transactionsRoot_not_in: [String!] 214 | transactionsRoot_not_starts_with: String 215 | transactionsRoot_starts_with: String 216 | unclesHash: String 217 | unclesHash_contains: String 218 | unclesHash_ends_with: String 219 | unclesHash_gt: String 220 | unclesHash_gte: String 221 | unclesHash_in: [String!] 222 | unclesHash_lt: String 223 | unclesHash_lte: String 224 | unclesHash_not: String 225 | unclesHash_not_contains: String 226 | unclesHash_not_ends_with: String 227 | unclesHash_not_in: [String!] 228 | unclesHash_not_starts_with: String 229 | unclesHash_starts_with: String 230 | } 231 | 232 | input Block_height { 233 | hash: Bytes 234 | number: Int 235 | } 236 | 237 | 238 | scalar BigDecimal 239 | 240 | scalar BigInt 241 | 242 | scalar Bytes -------------------------------------------------------------------------------- /src/v2/orderbook.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from '@ethersproject/address' 2 | import { APIGatewayProxyHandler } from 'aws-lambda' 3 | import BigNumber from 'bignumber.js' 4 | import { createSuccessResponse, createBadRequestResponse, createServerErrorResponse } from '../utils/response' 5 | 6 | import { getReserves } from './_shared' 7 | import { computeBidsAsks } from '../utils/computeBidsAsks' 8 | 9 | export const handler: APIGatewayProxyHandler = async event => { 10 | if (!event.pathParameters?.pair || !/^0x[0-9a-fA-F]{40}_0x[0-9a-fA-F]{40}$/.test(event.pathParameters.pair)) { 11 | return createBadRequestResponse('Invalid pair identifier: must be of format tokenAddress_tokenAddress') 12 | } 13 | 14 | const [tokenA, tokenB] = event.pathParameters?.pair.split('_') 15 | let idA: string, idB: string 16 | try { 17 | ;[idA, idB] = [getAddress(tokenA), getAddress(tokenB)] 18 | } catch (error) { 19 | return createBadRequestResponse('Invalid pair identifier: both addresses must be *checksummed*') 20 | } 21 | 22 | try { 23 | const [reservesA, reservesB] = await getReserves(idA, idB) 24 | 25 | const timestamp = new Date().getTime() 26 | 27 | return createSuccessResponse({ 28 | timestamp, 29 | ...computeBidsAsks(new BigNumber(reservesA), new BigNumber(reservesB)) 30 | }) 31 | } catch (error) { 32 | return createServerErrorResponse(error) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/v2/summary.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from '@ethersproject/address' 2 | import { APIGatewayProxyHandler } from 'aws-lambda' 3 | 4 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 5 | import { getTopPairs } from './_shared' 6 | 7 | interface ReturnShape { 8 | [tokenIds: string]: { last_price: string; base_volume: string; quote_volume: string } 9 | } 10 | 11 | export const handler: APIGatewayProxyHandler = async () => { 12 | try { 13 | const pairs = await getTopPairs() 14 | 15 | return createSuccessResponse( 16 | pairs.reduce((accumulator, pair): any => { 17 | const id0 = getAddress(pair.token0.id) 18 | const id1 = getAddress(pair.token1.id) 19 | accumulator[`${id0}_${id1}`] = { 20 | last_price: pair.price ?? '0', 21 | base_volume: pair.volumeToken0, 22 | quote_volume: pair.volumeToken1 23 | } 24 | return accumulator 25 | }, {}) 26 | ) 27 | } catch (error) { 28 | return createServerErrorResponse(error) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/v2/tickers.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from '@ethersproject/address' 2 | import { APIGatewayProxyHandler } from 'aws-lambda' 3 | import { createSuccessResponse, createServerErrorResponse } from '../utils/response' 4 | import { getTopPairs } from './_shared' 5 | 6 | interface ReturnShape { 7 | [tokenIds: string]: { 8 | base_name: string 9 | base_symbol: string 10 | base_id: string 11 | quote_name: string 12 | quote_symbol: string 13 | quote_id: string 14 | last_price: string 15 | base_volume: string 16 | quote_volume: string 17 | } 18 | } 19 | 20 | export const handler: APIGatewayProxyHandler = async () => { 21 | try { 22 | const pairs = await getTopPairs() 23 | return createSuccessResponse( 24 | pairs.reduce((accumulator, pair): ReturnShape => { 25 | const id0 = getAddress(pair.token0.id) 26 | const id1 = getAddress(pair.token1.id) 27 | 28 | accumulator[`${id0}_${id1}`] = { 29 | base_id: id0, 30 | base_name: pair.token0.name, 31 | base_symbol: pair.token0.symbol, 32 | quote_id: id1, 33 | quote_name: pair.token1.name, 34 | quote_symbol: pair.token1.symbol, 35 | last_price: pair.price ?? '0', 36 | base_volume: pair.previous24hVolumeToken0.toString(), 37 | quote_volume: pair.previous24hVolumeToken1.toString() 38 | } 39 | 40 | return accumulator 41 | }, {}) 42 | ) 43 | } catch (error) { 44 | return createServerErrorResponse(error) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/v2/trades.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from '@ethersproject/address' 2 | import { APIGatewayProxyHandler } from 'aws-lambda' 3 | import BigNumber from 'bignumber.js' 4 | 5 | import { getSwaps } from './_shared' 6 | import { createSuccessResponse, createBadRequestResponse, createServerErrorResponse } from '../utils/response' 7 | 8 | export const handler: APIGatewayProxyHandler = async event => { 9 | if (!event.pathParameters?.pair || !/^0x[0-9a-fA-F]{40}_0x[0-9a-fA-F]{40}$/.test(event.pathParameters.pair)) { 10 | return createBadRequestResponse('Invalid pair identifier: must be of format tokenAddress_tokenAddress') 11 | } 12 | 13 | const [tokenA, tokenB] = event.pathParameters.pair.split('_') 14 | let idA: string, idB: string 15 | try { 16 | ;[idA, idB] = [getAddress(tokenA), getAddress(tokenB)] 17 | } catch (error) { 18 | return createBadRequestResponse('Invalid pair identifier: both asset identifiers must be *checksummed* addresses') 19 | } 20 | 21 | try { 22 | const swaps = await getSwaps(idA, idB) 23 | 24 | return createSuccessResponse( 25 | swaps.map(swap => { 26 | const aIn = swap.amountAIn !== '0' 27 | const aOut = swap.amountAOut !== '0' 28 | const bIn = swap.amountBIn !== '0' 29 | const bOut = swap.amountBOut !== '0' 30 | 31 | // a is the base so if the pair sends a and not b then it's a 'buy' 32 | const isBuy = aOut && bIn && !aIn && !bOut 33 | const isSell = !aOut && !bIn && aIn && bOut 34 | const isBorrowBoth = aOut && bOut && aIn && bIn 35 | 36 | const type = isBuy ? 'buy' : isSell ? 'sell' : isBorrowBoth ? 'borrow-both' : '???' 37 | const baseAmount = aOut ? swap.amountAOut : swap.amountAIn 38 | const quoteAmount = bOut ? swap.amountBOut : swap.amountBIn 39 | return { 40 | trade_id: swap.id, 41 | base_volume: baseAmount, 42 | quote_volume: quoteAmount, 43 | type, 44 | trade_timestamp: swap.timestamp, 45 | price: 46 | baseAmount !== '0' ? new BigNumber(quoteAmount).dividedBy(new BigNumber(baseAmount)).toString() : undefined 47 | } 48 | }) 49 | ) 50 | } catch (error) { 51 | return createServerErrorResponse(error) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 6 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 7 | "lib": ["es2015"] /* Specify library files to be included in the compilation. */, 8 | // "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | // "outDir": "./", /* Redirect output structure to the directory. */ 16 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, 28 | "strictNullChecks": true /* Enable strict null checks. */, 29 | "strictFunctionTypes": true /* Enable strict checking of function types. */, 30 | "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */, 31 | "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */, 32 | "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */, 33 | "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 52 | 53 | /* Source Map Options */ 54 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 55 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 56 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 57 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 58 | 59 | /* Experimental Options */ 60 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 61 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 62 | }, 63 | "include": ["./src/**/*.ts"] 64 | } 65 | -------------------------------------------------------------------------------- /v1.md: -------------------------------------------------------------------------------- 1 | # V1 Endpoints 2 | 3 | All Uniswap pairs consist of ETH (treated as the base currency) paired with an ERC20 token (treated as the quote currency). 4 | 5 | ## [`/v1/summary`](https://api.uniswap.info/v1/summary) 6 | 7 | Returns data for the top ~100 Uniswap pairs, sorted by ETH liquidity. Results are cached for 15 minutes. 8 | 9 | ### Request 10 | 11 | `GET https://api.uniswap.info/v1/summary` 12 | 13 | ### Response 14 | 15 | ```json5 16 | { 17 | "ETH_0x...": { // the asset ids of ETH and ERC20 tokens, joined by an underscore 18 | "last_price": "1.234", // denominated in tokens/ETH 19 | "base_volume": "123.456", // denominated in ETH 20 | "quote_volume": "1234.56" // denominated in tokens 21 | }, 22 | // ... 23 | } 24 | ``` 25 | 26 | ## [`/v1/assets`](https://api.uniswap.info/v1/assets) 27 | 28 | Returns the top ~100 assets supported by Uniswap, which consist of ETH and ERC20 tokens. The assets are sorted by ETH liquidity in their ETH pair. Results are cached for 24 hours. 29 | 30 | ### Request 31 | 32 | `GET https://api.uniswap.info/v1/assets` 33 | 34 | ### Response 35 | 36 | ```json5 37 | { 38 | // ..., 39 | "0x...": { // "ETH" or the address of the ERC20 token 40 | "name": "...", // not necesssarily included for ERC20 tokens 41 | "symbol": "...", // not necesssarily included for ERC20 tokens 42 | "id": "0x...", // asset id, "ETH" or the address of the Uniswap exchange for the ERC20 token 43 | "maker_fee": "0", // always 0 44 | "taker_fee": "0.003", // always 0.003 i.e. .3% 45 | }, 46 | // ... 47 | } 48 | ``` 49 | 50 | ## [`/v1/tickers`](https://api.uniswap.info/v1/tickers) 51 | 52 | Returns data for the top ~100 Uniswap pairs, sorted by ETH liquidity. Results are cached for 15 minutes. 53 | 54 | ### Request 55 | 56 | `GET https://api.uniswap.info/v1/tickers` 57 | 58 | ### Response 59 | 60 | ```json5 61 | { 62 | "ETH_0x...": { // the asset ids of ETH and ERC20 tokens, joined by an underscore 63 | "base_name": "Ether", // always "Ether" 64 | "base_symbol": "ETH", // always "ETH" 65 | "base_id": "ETH", // always "ETH" 66 | "quote_name": "...", // not necesssarily included 67 | "quote_symbol": "...", // not necesssarily included 68 | "quote_id": "0x...", // the asset id of the ERC20 token 69 | "quote_token_address": "0x...", // the address of the ERC20 token 70 | "last_price": "1.234", // denominated in tokens/ETH 71 | "base_volume": "123.456", // denominated in ETH 72 | "quote_volume": "1234.56" // denominated in tokens 73 | }, 74 | // ... 75 | } 76 | ``` 77 | 78 | ## `/v1/orderbook/:pair` 79 | 80 | Returns simulated orderbook data for the given Uniswap pair. Since Uniswap has a continuous orderbook, fixed amounts in an interval are chosen for bids and asks, and prices are derived from the Uniswap formula. Results are cached for 240 minutes. 81 | 82 | ### Request 83 | 84 | `GET https://api.uniswap.info/v1/orderbook/:pair` 85 | 86 | ### URL Parameters 87 | 88 | - `pair`: The asset ids of ETH and an ERC20 token, joined by an underscore, e.g. `ETH_0x...` 89 | 90 | ### Response 91 | 92 | ```json5 93 | { 94 | "timestamp": 1234567, // UNIX timestamp 95 | "bids": [ 96 | ["12", "1.2"], // denominated in ETH, tokens/ETH 97 | ["12", "1.1"], // denominated in ETH, tokens/ETH 98 | // ... 99 | ], 100 | "asks": [ 101 | ["12", "1.3"], // denominated in ETH, tokens/ETH 102 | ["12", "1.4"], // denominated in ETH, tokens/ETH 103 | // ... 104 | ] 105 | } 106 | ``` 107 | 108 | ## `/v1/trades/:pair` 109 | 110 | Returns all trades in the last 24 hours for the given Uniswap pair. Results are cached for 15 minutes. 111 | 112 | ### URL Parameters 113 | 114 | - `pair`: The asset ids of ETH and an ERC20 token, joined by an underscore, e.g. `ETH_0x...` 115 | 116 | ### Request 117 | 118 | `GET https://api.uniswap.info/v1/trades/:pair` 119 | 120 | ### Response 121 | 122 | ```json5 123 | [ 124 | { 125 | "trade_id": "...", 126 | "price": "1.234", // denominated in tokens/ETH 127 | "base_volume": "123.456", // denominated in ETH 128 | "quote_volume": "1234.56", // denominated in tokens 129 | "trade_timestamp": 1234567, // UNIX timestamp 130 | "type": "buy" // "buy" or "sell" 131 | }, 132 | // ... 133 | ] 134 | ``` 135 | -------------------------------------------------------------------------------- /v2.md: -------------------------------------------------------------------------------- 1 | # V2 Endpoints 2 | 3 | All Uniswap V2 pairs consist of two different tokens. ETH is not a native currency in Uniswap V2, and is represented 4 | only by WETH in the V2 pairs. 5 | 6 | The canonical WETH address used by the Uniswap interface is `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`. 7 | 8 | ## [`/v2/summary`](https://api.uniswap.info/v2/summary) 9 | 10 | Returns data for the top ~1000 Uniswap V2 pairs, sorted by reserves. 11 | Results are edge cached for 15 minutes. 12 | 13 | ### Request 14 | 15 | `GET https://api.uniswap.info/v2/summary` 16 | 17 | ### Response 18 | 19 | ```json5 20 | { 21 | "0x..._0x...": { // the asset ids of the ERC20 tokens (i.e. token addresses), joined by an underscore 22 | "last_price": "1.234", // denominated in token0/token1 23 | "base_volume": "123.456", // last 24h volume denominated in token0 24 | "quote_volume": "1234.56" // last 24h volume denominated in token1 25 | }, 26 | // ... 27 | } 28 | ``` 29 | 30 | ## [`/v2/assets`](https://api.uniswap.info/v2/assets) 31 | 32 | Returns the tokens in the top ~1000 pairs on Uniswap V2, sorted by reserves. 33 | Results are edge cached for 24 hours. 34 | 35 | ### Request 36 | 37 | `GET https://api.uniswap.info/v2/assets` 38 | 39 | ### Response 40 | 41 | ```json5 42 | { 43 | // ..., 44 | "0x...": { // the address of the ERC20 token 45 | "name": "...", // not necesssarily included for ERC20 tokens 46 | "symbol": "...", // not necesssarily included for ERC20 tokens 47 | "id": "0x...", // the address of the ERC20 token 48 | "maker_fee": "0", // always 0 49 | "taker_fee": "0.003", // always 0.003 i.e. .3% 50 | }, 51 | // ... 52 | } 53 | ``` 54 | 55 | ## [`/v2/tickers`](https://api.uniswap.info/v2/tickers) 56 | 57 | Returns data for the top ~1000 Uniswap V2 pairs, sorted by reserves. 58 | Results are edge cached for 1 minute. 59 | 60 | ### Request 61 | 62 | `GET https://api.uniswap.info/v2/tickers` 63 | 64 | ### Response 65 | 66 | ```json5 67 | { 68 | "0x..._0x...": { // the asset ids of ETH and ERC20 tokens, joined by an underscore 69 | "base_name": "...", // token0 name 70 | "base_symbol": "...", // token0 symbol 71 | "base_id": "0x...", // token0 address 72 | "quote_name": "...", // token1 name 73 | "quote_symbol": "...", // token1 symbol 74 | "quote_id": "0x...", // token1 address 75 | "last_price": "1.234", // the mid price as token1/token0 76 | "base_volume": "123.456", // denominated in token0 77 | "quote_volume": "1234.56" // denominated in token1 78 | }, 79 | // ... 80 | } 81 | ``` 82 | 83 | ## `/v2/orderbook/:pair` 84 | 85 | Returns simulated orderbook data for the given Uniswap V2 pair. 86 | Since Uniswap has a continuous orderbook, fixed amounts in an interval are chosen for bids and asks, 87 | and prices are derived from the Uniswap V2 formula (accounting for both slippage and fees paid to LPs). 88 | Results are edge cached for 240 minutes. 89 | 90 | ### Request 91 | 92 | `GET https://api.uniswap.info/v2/orderbook/:pair` 93 | 94 | ### URL Parameters 95 | 96 | - `pair`: The asset ids of two ERC20 tokens, joined by an underscore, e.g. `0x..._0x...`. The first token address is considered the base in the response. 97 | 98 | ### Response 99 | 100 | ```json5 101 | { 102 | "timestamp": 1234567, // UNIX timestamp of the response 103 | "bids": [ 104 | ["12", "1.2"], // denominated in base token, quote token/base token 105 | ["12", "1.1"], // denominated in base token, quote token/base token 106 | // ... 107 | ], 108 | "asks": [ 109 | ["12", "1.3"], // denominated in base token, quote token/base token 110 | ["12", "1.4"], // denominated in base token, quote token/base token 111 | // ... 112 | ] 113 | } 114 | ``` 115 | 116 | ## `/v2/trades/:pair` 117 | 118 | Returns all swaps in the last 24 hours for the given Uniswap V2 pair. 119 | Results are edge cached for 15 minutes. 120 | 121 | The pair address is the address of the two tokens in either order. 122 | The first address is considered the base in the response. 123 | 124 | Note because Uniswap V2 supports flash swaps and borrowing of both tokens in a pair, you may wish to exclude these 125 | trade types (types `"???"` and `"borrow-both"`). 126 | 127 | ### URL Parameters 128 | 129 | - `pair`: The asset ids of two ERC20 tokens, joined by an underscore, e.g. `0x..._0x...`. The first token address is considered the base in the response. 130 | 131 | ### Request 132 | 133 | `GET https://api.uniswap.info/v2/trades/:pair` 134 | 135 | ### Response 136 | 137 | ```json5 138 | [ 139 | { 140 | "trade_id": "...", 141 | "price": "1.234", // denominated in quote token/base token 142 | "base_volume": "123.456", // denominated in base token 143 | "quote_volume": "1234.56", // denominated in quote token 144 | "trade_timestamp": 1234567, // UNIX timestamp 145 | "type": "buy" // "buy"/"sell"/"borrow-both"/"???" 146 | }, 147 | // ... 148 | ] 149 | ``` 150 | --------------------------------------------------------------------------------