Commit 6e995d6c authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

feat(pools): integrate with The Graph using RTK Query (#1924)

* integrate with the graph

* Update src/state/data/slice.ts
Co-authored-by: default avatarNoah Zinsmeister <noahwz@gmail.com>
Co-authored-by: default avatarNoah Zinsmeister <noahwz@gmail.com>
parent f0961127
import { BaseQueryFn } from '@reduxjs/toolkit/query/react'
import { DocumentNode } from 'graphql'
import { ClientError, request } from 'graphql-request'
export const UNISWAP_V3_GRAPH_URL = 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-alt'
// wrapper around graphql-request to interface with rtk-query
export const graphqlBaseQuery =
({
baseUrl,
}: {
baseUrl: string
}): BaseQueryFn<{ document: string | DocumentNode; variables?: any }, unknown, ClientError> =>
async ({ document, variables }) => {
try {
return { data: await request(baseUrl, document, variables) }
} catch (error) {
if (error instanceof ClientError) {
return { error }
}
throw error
}
}
import { createApi } from '@reduxjs/toolkit/query/react'
import { gql } from 'graphql-request'
import { FeeAmount } from '@uniswap/v3-sdk'
import { reduce } from 'lodash'
import { graphqlBaseQuery, UNISWAP_V3_GRAPH_URL } from './common'
import { FeeTierDistribution, PoolTVL } from './types'
export const dataApi = createApi({
reducerPath: 'dataApi',
baseQuery: graphqlBaseQuery({
baseUrl: UNISWAP_V3_GRAPH_URL,
}),
endpoints: (builder) => ({
getFeeTierDistribution: builder.query<FeeTierDistribution, { token0: string; token1: string }>({
query: ({ token0, token1 }) => ({
document: gql`
query pools($token0: Bytes!, $token1: Bytes!) {
_meta {
block {
number
}
}
asToken0: pools(
orderBy: totalValueLockedToken0
orderDirection: desc
where: { token0: $token0, token1: $token1 }
) {
feeTier
totalValueLockedToken0
totalValueLockedToken1
}
asToken1: pools(
orderBy: totalValueLockedToken0
orderDirection: desc
where: { token0: $token1, token1: $token0 }
) {
feeTier
totalValueLockedToken0
totalValueLockedToken1
}
}
`,
variables: {
token0,
token1,
},
}),
transformResponse: (poolTvl: PoolTVL) => {
const all = poolTvl.asToken0.concat(poolTvl.asToken1)
// sum tvl for token0 and token1 by fee tier
const tvlByFeeTer = all.reduce<{ [feeAmount: number]: [number | undefined, number | undefined] }>(
(acc, value) => {
acc[value.feeTier][0] = (acc[value.feeTier][0] ?? 0) + Number(value.totalValueLockedToken0)
acc[value.feeTier][1] = (acc[value.feeTier][1] ?? 0) + Number(value.totalValueLockedToken1)
return acc
},
{
[FeeAmount.LOW]: [undefined, undefined],
[FeeAmount.MEDIUM]: [undefined, undefined],
[FeeAmount.HIGH]: [undefined, undefined],
}
)
// sum total tvl for token0 and token1
const [sumToken0Tvl, sumToken1Tvl] = reduce(
tvlByFeeTer,
(acc: [number, number], value) => {
acc[0] += value[0] ?? 0
acc[1] += value[1] ?? 0
return acc
},
[0, 0]
)
// returns undefined if both tvl0 and tvl1 are undefined (pool not created)
const mean = (tvl0: number | undefined, sumTvl0: number, tvl1: number | undefined, sumTvl1: number) =>
tvl0 === undefined && tvl1 === undefined ? undefined : ((tvl0 ?? 0) + (tvl1 ?? 0)) / (sumTvl0 + sumTvl1) || 0
return {
block: poolTvl._meta.block.number,
distributions: {
[FeeAmount.LOW]: mean(
tvlByFeeTer[FeeAmount.LOW][0],
sumToken0Tvl,
tvlByFeeTer[FeeAmount.LOW][1],
sumToken1Tvl
),
[FeeAmount.MEDIUM]: mean(
tvlByFeeTer[FeeAmount.MEDIUM][0],
sumToken0Tvl,
tvlByFeeTer[FeeAmount.MEDIUM][1],
sumToken1Tvl
),
[FeeAmount.HIGH]: mean(
tvlByFeeTer[FeeAmount.HIGH][0],
sumToken0Tvl,
tvlByFeeTer[FeeAmount.HIGH][1],
sumToken1Tvl
),
},
}
},
}),
}),
})
export const { useGetFeeTierDistributionQuery } = dataApi
import { FeeAmount } from '@uniswap/v3-sdk'
export interface PoolTVL {
_meta: {
block: {
number: number
}
}
asToken0: {
feeTier: FeeAmount
totalValueLockedToken0: number
totalValueLockedToken1: number
}[]
asToken1: {
feeTier: FeeAmount
totalValueLockedToken0: number
totalValueLockedToken1: number
}[]
}
export interface FeeTierDistribution {
block: number
distributions: {
[FeeAmount.LOW]: number | undefined
[FeeAmount.MEDIUM]: number | undefined
[FeeAmount.HIGH]: number | undefined
}
}
...@@ -2404,13 +2404,13 @@ ...@@ -2404,13 +2404,13 @@
"@react-hook/event" "^1.2.1" "@react-hook/event" "^1.2.1"
"@react-hook/throttle" "^2.2.0" "@react-hook/throttle" "^2.2.0"
"@reduxjs/toolkit@^1.3.5": "@reduxjs/toolkit@^1.6.0":
version "1.5.1" version "1.6.0"
resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.5.1.tgz" resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.6.0.tgz#0a17c6941c57341f8b31e982352b495ab69d5add"
integrity sha512-PngZKuwVZsd+mimnmhiOQzoD0FiMjqVks6ituO1//Ft5UEX5Ca9of13NEjo//pU22Jk7z/mdXVsmDfgsig1osA== integrity sha512-eGL50G+Vj5AG5uD0lineb6rRtbs96M8+hxbcwkHpZ8LQcmt0Bm33WyBSnj5AweLkjQ7ZP+KFRDHiLMznljRQ3A==
dependencies: dependencies:
immer "^8.0.1" immer "^9.0.1"
redux "^4.0.0" redux "^4.1.0"
redux-thunk "^2.3.0" redux-thunk "^2.3.0"
reselect "^4.0.0" reselect "^4.0.0"
...@@ -5975,7 +5975,7 @@ colors@^1.1.2: ...@@ -5975,7 +5975,7 @@ colors@^1.1.2:
resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
combined-stream@^1.0.6, combined-stream@~1.0.6: combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8" version "1.0.8"
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
...@@ -6293,6 +6293,13 @@ cross-fetch@^2.1.0, cross-fetch@^2.1.1: ...@@ -6293,6 +6293,13 @@ cross-fetch@^2.1.0, cross-fetch@^2.1.1:
node-fetch "2.1.2" node-fetch "2.1.2"
whatwg-fetch "2.0.4" whatwg-fetch "2.0.4"
cross-fetch@^3.0.6:
version "3.1.4"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
dependencies:
node-fetch "2.6.1"
cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3" version "7.0.3"
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
...@@ -8275,6 +8282,11 @@ extglob@^2.0.4: ...@@ -8275,6 +8282,11 @@ extglob@^2.0.4:
snapdragon "^0.8.1" snapdragon "^0.8.1"
to-regex "^3.0.1" to-regex "^3.0.1"
extract-files@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a"
integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==
extract-zip@^1.7.0: extract-zip@^1.7.0:
version "1.7.0" version "1.7.0"
resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz" resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz"
...@@ -8606,6 +8618,15 @@ fork-ts-checker-webpack-plugin@4.1.6: ...@@ -8606,6 +8618,15 @@ fork-ts-checker-webpack-plugin@4.1.6:
tapable "^1.0.0" tapable "^1.0.0"
worker-rpc "^0.1.0" worker-rpc "^0.1.0"
form-data@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
...@@ -8949,6 +8970,20 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 ...@@ -8949,6 +8970,20 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
graphql-request@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.4.0.tgz#3a400cd5511eb3c064b1873afb059196bbea9c2b"
integrity sha512-acrTzidSlwAj8wBNO7Q/UQHS8T+z5qRGquCQRv9J1InwR01BBWV9ObnoE+JS5nCCEj8wSGS0yrDXVDoRiKZuOg==
dependencies:
cross-fetch "^3.0.6"
extract-files "^9.0.0"
form-data "^3.0.0"
graphql@^15.5.0:
version "15.5.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==
growly@^1.3.0: growly@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz" resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz"
...@@ -9376,10 +9411,10 @@ immer@8.0.1: ...@@ -9376,10 +9411,10 @@ immer@8.0.1:
resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz" resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz"
integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==
immer@^8.0.1: immer@^9.0.1:
version "8.0.4" version "9.0.3"
resolved "https://registry.npmjs.org/immer/-/immer-8.0.4.tgz" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.3.tgz#146e2ba8b84d4b1b15378143c2345559915097f4"
integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== integrity sha512-mONgeNSMuyjIe0lkQPa9YhdmTv8P19IeHV0biYhcXhbd5dhdB9HSK93zBpyKjp6wersSUgT5QyU0skmejUVP2A==
import-cwd@^2.0.0: import-cwd@^2.0.0:
version "2.1.0" version "2.1.0"
...@@ -11788,7 +11823,7 @@ node-fetch@2.1.2: ...@@ -11788,7 +11823,7 @@ node-fetch@2.1.2:
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz"
integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=
node-fetch@^2.6.0, node-fetch@^2.6.1: node-fetch@2.6.1, node-fetch@^2.6.0, node-fetch@^2.6.1:
version "2.6.1" version "2.6.1"
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
...@@ -14134,6 +14169,11 @@ recursive-readdir@2.2.2: ...@@ -14134,6 +14169,11 @@ recursive-readdir@2.2.2:
dependencies: dependencies:
minimatch "3.0.4" minimatch "3.0.4"
redux-devtools-extension@^2.13.9:
version "2.13.9"
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz#6b764e8028b507adcb75a1cae790f71e6be08ae7"
integrity sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==
redux-localstorage-simple@^2.3.1: redux-localstorage-simple@^2.3.1:
version "2.4.0" version "2.4.0"
resolved "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.4.0.tgz" resolved "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.4.0.tgz"
...@@ -14146,7 +14186,7 @@ redux-thunk@^2.3.0: ...@@ -14146,7 +14186,7 @@ redux-thunk@^2.3.0:
resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz" resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz"
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
redux@^4.0.0: redux@^4.0.0, redux@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz" resolved "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz"
integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g== integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment