feat: data api connection (#4396)

* split relay into two environments, refactored schema grabbing, implemented api call for token price graph
This commit is contained in:
cartcrom 2022-08-19 15:31:10 -04:00 committed by GitHub
parent 9b07d8ce64
commit 85742c5785
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 2260 additions and 3542 deletions

5
.env

@ -1,3 +1,8 @@
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_FORTMATIC_KEY="pk_live_357F77728B8EB880"
REACT_APP_AMPLITUDE_TEST_KEY="add-the-real-test-key-if-you-need-to-test-amplitude-events"
REACT_APP_AWS_API_REGION="us-east-2"
REACT_APP_AWS_API_ACCESS_KEY="AKIAYJJWW6AQ47ODATHN"
REACT_APP_AWS_API_ACCESS_SECRET="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"
REACT_APP_AWS_X_API_KEY="z9dReS5UtHu7iTrUsTuWRozLthi3AxOZlvobrIdr14"
REACT_APP_AWS_API_ENDPOINT="https://beta.api.uniswap.org/v1/graphql"

1
.gitignore vendored

@ -9,7 +9,6 @@
/src/locales/**/pseudo.po
# generated graphql types
/src/graphql/schema/
__generated__/
# dependencies

@ -1,7 +1,6 @@
overrideExisting: true
schema: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'
documents: 'src/**/!(*.d).{ts,tsx}'
generates:
./src/graphql/schema/schema.graphql:
./src/graphql/thegraph/schema/schema.graphql:
plugins:
- schema-ast

18
fetch-schema.js Normal file

@ -0,0 +1,18 @@
/* eslint-disable */
require('dotenv').config({ path: '.env.local' })
const { exec } = require('child_process')
const dataConfig = require('./relay.config')
const thegraphConfig = require('./relay_thegraph.config')
/* eslint-enable */
const THEGRAPH_API_URL = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'
exec(`get-graphql-schema ${THEGRAPH_API_URL} > ${thegraphConfig.schema}`)
const API_URL = process.env.REACT_APP_GQL_API_URL
const API_KEY = process.env.REACT_APP_GQL_API_KEY
if (API_URL && API_KEY) {
exec(`get-graphql-schema ${API_URL} --h X-API-KEY=${API_KEY} > ${dataConfig.schema}`)
} else {
console.log('REACT_APP_GQL_API_URL or REACT_APP_GQL_API_KEY is missing from env.local')
}

@ -8,8 +8,10 @@
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"./node_modules/@uniswap/**/artifacts/contracts/**/*[!dbg].json\"",
"contracts:compile": "yarn contracts:compile:abi && yarn contracts:compile:v3",
"relay": "relay-compiler",
"graphql:generate": "graphql-codegen --config codegen.yml && yarn relay",
"relay": "relay-compiler relay.config.js",
"relay-thegraph": "relay-compiler relay_thegraph.config.js",
"graphql:fetch": "node fetch-schema.js",
"graphql:generate": "yarn relay && yarn relay-thegraph",
"prei18n:extract": "node prei18n-extract.js",
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "yarn i18n:extract && lingui compile",
@ -23,11 +25,6 @@
"cypress:open": "cypress open --browser chrome --e2e",
"cypress:run": "cypress run --browser chrome --e2e"
},
"relay": {
"src": "./src",
"language": "typescript",
"schema": "./src/graphql/schema/schema.graphql"
},
"jest": {
"collectCoverageFrom": [
"src/components/**/*.ts*",
@ -63,9 +60,6 @@
"devDependencies": {
"@craco/craco": "6.4.3",
"@ethersproject/experimental": "^5.4.0",
"@graphql-codegen/cli": "1.21.5",
"@graphql-codegen/schema-ast": "^2.5.1",
"@graphql-codegen/typescript-rtk-query": "^1.1.1",
"@lingui/cli": "^3.9.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1",
@ -95,9 +89,9 @@
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4",
"@typescript-eslint/parser": "^4",
"babel-plugin-relay": "^14.1.0",
"@vanilla-extract/babel-plugin": "^1.1.7",
"@vanilla-extract/webpack-plugin": "^2.1.11",
"babel-plugin-relay": "^14.1.0",
"cypress": "^10.3.1",
"env-cmd": "^10.1.0",
"eslint": "^7.11.0",
@ -173,6 +167,7 @@
"ajv": "^6.12.3",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
"aws4fetch": "^1.0.13",
"cids": "^1.0.0",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.2.0",
@ -181,6 +176,7 @@
"ethers": "^5.1.4",
"firebase": "^9.1.3",
"focus-visible": "^5.2.0",
"get-graphql-schema": "^2.1.2",
"graphql": "^16.5.0",
"graphql-request": "^3.4.0",
"immer": "^9.0.6",
@ -216,7 +212,6 @@
"rebass": "^4.0.7",
"redux": "^4.1.2",
"redux-localstorage-simple": "^2.3.1",
"relay-hooks": "^7.1.0",
"setimmediate": "^1.0.5",
"styled-components": "^5.3.5",
"tiny-invariant": "^1.2.0",

@ -1,5 +1,5 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const exec = require('child_process').exec
const { exec } = require('child_process')
const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)
if (isWindows) {

6
relay.config.js Normal file

@ -0,0 +1,6 @@
module.exports = {
src: './src',
language: 'typescript',
schema: './src/graphql/data/schema.graphql',
exclude: ['**/node_modules/**', '**/__mocks__/**', '**/__generated__/**', '**/thegraph/**'],
}

9
relay_thegraph.config.js Normal file

@ -0,0 +1,9 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const defaultConfig = require('./relay.config')
module.exports = {
src: defaultConfig.src,
language: defaultConfig.language,
schema: './src/graphql/thegraph/schema.graphql',
exclude: ['**/node_modules/**', '**/__mocks__/**', '**/__generated__/**', '**/data/**'],
}

@ -1,3 +1,4 @@
import { Token } from '@uniswap/sdk-core'
import { AxisBottom, TickFormatter } from '@visx/axis'
import { localPoint } from '@visx/event'
import { EventType } from '@visx/event/lib/types'
@ -5,6 +6,7 @@ import { GlyphCircle } from '@visx/glyph'
import { Line } from '@visx/shape'
import { filterTimeAtom } from 'components/Tokens/state'
import { bisect, curveBasis, NumberValue, scaleLinear } from 'd3'
import { useTokenPriceQuery } from 'graphql/data/TokenPriceQuery'
import { useActiveLocale } from 'hooks/useActiveLocale'
import { TimePeriod } from 'hooks/useExplorePageQuery'
import { useAtom } from 'jotai'
@ -22,21 +24,22 @@ import {
weekFormatter,
} from 'utils/formatChartTimes'
import data from '../../Charts/data.json'
import LineChart from '../../Charts/LineChart'
// TODO: This should be combined with the logic in TimeSelector.
const TIME_DISPLAYS: [TimePeriod, string][] = [
[TimePeriod.hour, '1H'],
[TimePeriod.day, '1D'],
[TimePeriod.week, '1W'],
[TimePeriod.month, '1M'],
[TimePeriod.year, '1Y'],
[TimePeriod.all, 'All'],
[TimePeriod.HOUR, '1H'],
[TimePeriod.DAY, '1D'],
[TimePeriod.WEEK, '1W'],
[TimePeriod.MONTH, '1M'],
[TimePeriod.YEAR, '1Y'],
[TimePeriod.ALL, 'All'],
]
type PricePoint = { value: number; timestamp: number }
const DATA_EMPTY = { value: 0, timestamp: 0 }
function getPriceBounds(pricePoints: PricePoint[]): [number, number] {
const prices = pricePoints.map((x) => x.value)
const min = Math.min(...prices)
@ -125,17 +128,17 @@ function tickFormat(
locale: string
): [TickFormatter<NumberValue>, (v: number) => string, number[]] {
switch (timePeriod) {
case TimePeriod.hour:
case TimePeriod.HOUR:
return [hourFormatter(locale), dayHourFormatter(locale), getTicks(startTimestamp, endTimestamp)]
case TimePeriod.day:
case TimePeriod.DAY:
return [hourFormatter(locale), dayHourFormatter(locale), getTicks(startTimestamp, endTimestamp)]
case TimePeriod.week:
case TimePeriod.WEEK:
return [weekFormatter(locale), dayHourFormatter(locale), getTicks(startTimestamp, endTimestamp, 6)]
case TimePeriod.month:
case TimePeriod.MONTH:
return [monthDayFormatter(locale), dayHourFormatter(locale), getTicks(startTimestamp, endTimestamp)]
case TimePeriod.year:
case TimePeriod.YEAR:
return [monthFormatter(locale), monthYearDayFormatter(locale), getTicks(startTimestamp, endTimestamp)]
case TimePeriod.all:
case TimePeriod.ALL:
return [monthYearFormatter(locale), monthYearDayFormatter(locale), getTicks(startTimestamp, endTimestamp)]
}
}
@ -147,19 +150,26 @@ const crosshairDateOverhang = 80
interface PriceChartProps {
width: number
height: number
token: Token
}
export function PriceChart({ width, height }: PriceChartProps) {
export function PriceChart({ width, height, token }: PriceChartProps) {
const [timePeriod, setTimePeriod] = useAtom(filterTimeAtom)
const locale = useActiveLocale()
const theme = useTheme()
// TODO: Add network selector input, consider using backend type instead of current front end selector type
const pricePoints: PricePoint[] = useTokenPriceQuery(token.address, timePeriod, 'ETHEREUM').filter(
(p): p is PricePoint => Boolean(p && p.value)
)
const hasData = pricePoints.length !== 0
/* TODO: Implement API calls & cache to use here */
const pricePoints = data[timePeriod]
const startingPrice = pricePoints[0]
const endingPrice = pricePoints[pricePoints.length - 1]
const initialState = { pricePoint: endingPrice, xCoordinate: null }
const [selected, setSelected] = useState<{ pricePoint: PricePoint; xCoordinate: number | null }>(initialState)
const startingPrice = hasData ? pricePoints[0] : DATA_EMPTY
const endingPrice = hasData ? pricePoints[pricePoints.length - 1] : DATA_EMPTY
const [displayPrice, setDisplayPrice] = useState(startingPrice)
const [crosshair, setCrosshair] = useState<number | null>(null)
const graphWidth = width + crosshairDateOverhang
const graphHeight = height - timeOptionsHeight
@ -190,25 +200,36 @@ export function PriceChart({ width, height }: PriceChartProps) {
pricePoint = x0.valueOf() - d0.timestamp.valueOf() > d1.timestamp.valueOf() - x0.valueOf() ? d1 : d0
}
setSelected({ pricePoint, xCoordinate: timeScale(pricePoint.timestamp) })
setCrosshair(timeScale(pricePoint.timestamp))
setDisplayPrice(pricePoint)
},
[timeScale, pricePoints]
)
const resetDisplay = useCallback(() => {
setCrosshair(null)
setDisplayPrice(endingPrice)
}, [setCrosshair, setDisplayPrice, endingPrice])
// TODO: connect to loading state
if (!hasData) {
return null
}
const [tickFormatter, crosshairDateFormatter, ticks] = tickFormat(
startingPrice.timestamp,
endingPrice.timestamp,
timePeriod,
locale
)
const [delta, arrow] = getDelta(startingPrice.value, selected.pricePoint.value)
const [delta, arrow] = getDelta(startingPrice.value, displayPrice.value)
const crosshairEdgeMax = width * 0.97
const crosshairAtEdge = !!selected.xCoordinate && selected.xCoordinate > crosshairEdgeMax
const crosshairAtEdge = !!crosshair && crosshair > crosshairEdgeMax
return (
<>
<ChartHeader>
<TokenPrice>${selected.pricePoint.value.toFixed(2)}</TokenPrice>
<TokenPrice>${displayPrice.value.toFixed(2)}</TokenPrice>
<DeltaContainer>
{delta}
<ArrowCell>{arrow}</ArrowCell>
@ -220,12 +241,12 @@ export function PriceChart({ width, height }: PriceChartProps) {
getY={(p: PricePoint) => rdScale(p.value)}
marginTop={margin.top}
/* Default curve doesn't look good for the ALL chart */
curve={timePeriod === TimePeriod.all ? curveBasis : undefined}
curve={timePeriod === TimePeriod.ALL ? curveBasis : undefined}
strokeWidth={2}
width={graphWidth}
height={graphHeight}
>
{selected.xCoordinate !== null ? (
{crosshair !== null ? (
<g>
<AxisBottom
scale={timeScale}
@ -244,25 +265,25 @@ export function PriceChart({ width, height }: PriceChartProps) {
})}
/>
<text
x={selected.xCoordinate + (crosshairAtEdge ? -4 : 4)}
x={crosshair + (crosshairAtEdge ? -4 : 4)}
y={margin.crosshair + 10}
textAnchor={crosshairAtEdge ? 'end' : 'start'}
fontSize={12}
fill={theme.textSecondary}
>
{crosshairDateFormatter(selected.pricePoint.timestamp)}
{crosshairDateFormatter(displayPrice.timestamp)}
</text>
<Line
from={{ x: selected.xCoordinate, y: margin.crosshair }}
to={{ x: selected.xCoordinate, y: graphHeight }}
from={{ x: crosshair, y: margin.crosshair }}
to={{ x: crosshair, y: graphHeight }}
stroke={theme.backgroundOutline}
strokeWidth={1}
pointerEvents="none"
strokeDasharray="4,4"
/>
<GlyphCircle
left={selected.xCoordinate}
top={rdScale(selected.pricePoint.value) + margin.top}
left={crosshair}
top={rdScale(displayPrice.value) + margin.top}
size={50}
fill={theme.accentActive}
stroke={theme.backgroundOutline}
@ -281,7 +302,7 @@ export function PriceChart({ width, height }: PriceChartProps) {
onTouchStart={handleHover}
onTouchMove={handleHover}
onMouseMove={handleHover}
onMouseLeave={() => setSelected(initialState)}
onMouseLeave={resetDisplay}
/>
</LineChart>
<TimeOptionsWrapper>

@ -290,7 +290,7 @@ export default function LoadedTokenDetail({ address }: { address: string }) {
</TokenActions>
</TokenInfoContainer>
<ChartContainer>
<ParentSize>{({ width, height }) => <PriceChart width={width} height={height} />}</ParentSize>
<ParentSize>{({ width, height }) => <PriceChart token={token} width={width} height={height} />}</ParentSize>
</ChartContainer>
</ChartHeader>
<AboutSection>

@ -18,7 +18,7 @@ export const TIME_DISPLAYS: { [key: string]: string } = {
year: '1Y',
}
const TIMES = [TimePeriod.hour, TimePeriod.day, TimePeriod.week, TimePeriod.month, TimePeriod.year]
const TIMES = [TimePeriod.HOUR, TimePeriod.DAY, TimePeriod.WEEK, TimePeriod.MONTH, TimePeriod.YEAR]
const InternalMenuItem = styled.div`
flex: 1;

@ -293,7 +293,7 @@ const LogoContainer = styled.div`
`
/* formatting for volume with timeframe header display */
function getHeaderDisplay(category: string, timeframe: string): string {
function getHeaderDisplay(category: string, timeframe: TimePeriod): string {
if (category === Category.volume) return `${TIME_DISPLAYS[timeframe]} ${category}`
return category
}

@ -10,7 +10,7 @@ export const favoritesAtom = atomWithStorage<string[]>('favorites', [])
export const showFavoritesAtom = atomWithStorage<boolean>('showFavorites', false)
export const filterStringAtom = atomWithReset<string>('')
export const filterNetworkAtom = atom<SupportedChainId>(SupportedChainId.MAINNET)
export const filterTimeAtom = atom<TimePeriod>(TimePeriod.day)
export const filterTimeAtom = atom<TimePeriod>(TimePeriod.DAY)
export const sortCategoryAtom = atom<Category>(Category.marketCap)
export const sortDirectionAtom = atom<SortDirection>(SortDirection.decreasing)

@ -1,167 +0,0 @@
/**
* @generated SignedSource<<0becdf63598262462f6fa0cabb891ad0>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest, Query } from 'relay-runtime';
export type AllV3TicksQuery$variables = {
poolAddress: string;
skip: number;
};
export type AllV3TicksQuery$data = {
readonly ticks: ReadonlyArray<{
readonly liquidityNet: any;
readonly price0: any;
readonly price1: any;
readonly tick: any;
}>;
};
export type AllV3TicksQuery = {
response: AllV3TicksQuery$data;
variables: AllV3TicksQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "poolAddress"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "skip"
}
],
v1 = [
{
"kind": "Literal",
"name": "first",
"value": 1000
},
{
"kind": "Literal",
"name": "orderBy",
"value": "tickIdx"
},
{
"kind": "Variable",
"name": "skip",
"variableName": "skip"
},
{
"fields": [
{
"kind": "Variable",
"name": "poolAddress",
"variableName": "poolAddress"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v2 = {
"alias": "tick",
"args": null,
"kind": "ScalarField",
"name": "tickIdx",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "liquidityNet",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "price0",
"storageKey": null
},
v5 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "price1",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "AllV3TicksQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": "Tick",
"kind": "LinkedField",
"name": "ticks",
"plural": true,
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/)
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "AllV3TicksQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": "Tick",
"kind": "LinkedField",
"name": "ticks",
"plural": true,
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "9f2d65b1e565e3d0ecbe7b1f908ebc83",
"id": null,
"metadata": {},
"name": "AllV3TicksQuery",
"operationKind": "query",
"text": "query AllV3TicksQuery(\n $poolAddress: String!\n $skip: Int!\n) {\n ticks(first: 1000, skip: $skip, where: {poolAddress: $poolAddress}, orderBy: tickIdx) {\n tick: tickIdx\n liquidityNet\n price0\n price1\n id\n }\n}\n"
}
};
})();
(node as any).hash = "82709c11c929a8eb6caf2ab1df2b99cc";
export default node;

@ -1,242 +0,0 @@
/**
* @generated SignedSource<<5761481cf3bba524864626a7f965c0d7>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest, Query } from 'relay-runtime';
export type FeeTierDistributionQuery$variables = {
token0: string;
token1: string;
};
export type FeeTierDistributionQuery$data = {
readonly _meta: {
readonly block: {
readonly number: number;
};
} | null;
readonly asToken0: ReadonlyArray<{
readonly feeTier: any;
readonly totalValueLockedToken0: any;
readonly totalValueLockedToken1: any;
}>;
readonly asToken1: ReadonlyArray<{
readonly feeTier: any;
readonly totalValueLockedToken0: any;
readonly totalValueLockedToken1: any;
}>;
};
export type FeeTierDistributionQuery = {
response: FeeTierDistributionQuery$data;
variables: FeeTierDistributionQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "token0"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "token1"
}
],
v1 = {
"alias": null,
"args": null,
"concreteType": "_Meta_",
"kind": "LinkedField",
"name": "_meta",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "_Block_",
"kind": "LinkedField",
"name": "block",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "number",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
},
v2 = {
"kind": "Literal",
"name": "orderBy",
"value": "totalValueLockedToken0"
},
v3 = {
"kind": "Literal",
"name": "orderDirection",
"value": "desc"
},
v4 = [
(v2/*: any*/),
(v3/*: any*/),
{
"fields": [
{
"kind": "Variable",
"name": "token0",
"variableName": "token0"
},
{
"kind": "Variable",
"name": "token1",
"variableName": "token1"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v5 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "feeTier",
"storageKey": null
},
v6 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalValueLockedToken0",
"storageKey": null
},
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalValueLockedToken1",
"storageKey": null
},
v8 = [
(v5/*: any*/),
(v6/*: any*/),
(v7/*: any*/)
],
v9 = [
(v2/*: any*/),
(v3/*: any*/),
{
"fields": [
{
"kind": "Variable",
"name": "token0",
"variableName": "token1"
},
{
"kind": "Variable",
"name": "token1",
"variableName": "token0"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v10 = [
(v5/*: any*/),
(v6/*: any*/),
(v7/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "FeeTierDistributionQuery",
"selections": [
(v1/*: any*/),
{
"alias": "asToken0",
"args": (v4/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v8/*: any*/),
"storageKey": null
},
{
"alias": "asToken1",
"args": (v9/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v8/*: any*/),
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "FeeTierDistributionQuery",
"selections": [
(v1/*: any*/),
{
"alias": "asToken0",
"args": (v4/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v10/*: any*/),
"storageKey": null
},
{
"alias": "asToken1",
"args": (v9/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v10/*: any*/),
"storageKey": null
}
]
},
"params": {
"cacheID": "d989fcfb8fc9ef13bdc6de811e574284",
"id": null,
"metadata": {},
"name": "FeeTierDistributionQuery",
"operationKind": "query",
"text": "query FeeTierDistributionQuery(\n $token0: String!\n $token1: String!\n) {\n _meta {\n block {\n number\n }\n }\n asToken0: pools(orderBy: totalValueLockedToken0, orderDirection: desc, where: {token0: $token0, token1: $token1}) {\n feeTier\n totalValueLockedToken0\n totalValueLockedToken1\n id\n }\n asToken1: pools(orderBy: totalValueLockedToken0, orderDirection: desc, where: {token0: $token1, token1: $token0}) {\n feeTier\n totalValueLockedToken0\n totalValueLockedToken1\n id\n }\n}\n"
}
};
})();
(node as any).hash = "ac9cd4bfdc24db90dbb2bf8a7508009f";
export default node;

@ -0,0 +1,69 @@
import graphql from 'babel-plugin-relay/macro'
import { TimePeriod } from 'hooks/useExplorePageQuery'
import { useLazyLoadQuery } from 'react-relay'
import type { Chain, TokenPriceQuery as TokenPriceQueryType } from './__generated__/TokenPriceQuery.graphql'
export function useTokenPriceQuery(address: string, timePeriod: TimePeriod, chain: Chain) {
const tokenPrices = useLazyLoadQuery<TokenPriceQueryType>(
graphql`
query TokenPriceQuery($contract: ContractInput) {
tokenProjects(contracts: [$contract]) {
name
markets(currencies: [USD]) {
priceHistory1H: priceHistory(duration: HOUR) {
timestamp
value
}
priceHistory1D: priceHistory(duration: DAY) {
timestamp
value
}
priceHistory1W: priceHistory(duration: WEEK) {
timestamp
value
}
priceHistory1M: priceHistory(duration: MONTH) {
timestamp
value
}
priceHistory1Y: priceHistory(duration: YEAR) {
timestamp
value
}
}
tokens {
chain
address
symbol
decimals
}
}
}
`,
{
contract: {
address,
chain,
},
}
)
const { priceHistory1H, priceHistory1D, priceHistory1W, priceHistory1M, priceHistory1Y } =
tokenPrices.tokenProjects?.[0]?.markets?.[0] ?? {}
switch (timePeriod) {
case TimePeriod.HOUR:
return priceHistory1H ?? []
case TimePeriod.DAY:
return priceHistory1D ?? []
case TimePeriod.WEEK:
return priceHistory1W ?? []
case TimePeriod.MONTH:
return priceHistory1M ?? []
case TimePeriod.YEAR:
return priceHistory1Y ?? []
case TimePeriod.ALL:
//TODO: Add functionality for ALL, without requesting it at same time as rest of data for performance reasons
return priceHistory1Y ?? []
}
}

@ -0,0 +1,35 @@
import { AwsClient } from 'aws4fetch'
import { Variables } from 'react-relay'
import { GraphQLResponse, RequestParameters } from 'relay-runtime'
const AWS_API_REGION = process.env.REACT_APP_AWS_API_REGION
const AWS_API_ACCESS_KEY = process.env.REACT_APP_AWS_API_ACCESS_KEY
const AWS_API_ACCESS_SECRET = process.env.REACT_APP_AWS_API_ACCESS_SECRET
const AWS_X_API_KEY = process.env.REACT_APP_AWS_X_API_KEY
const URL = process.env.REACT_APP_AWS_API_ENDPOINT
if (!AWS_API_REGION || !AWS_API_ACCESS_KEY || !AWS_API_ACCESS_SECRET || !AWS_X_API_KEY || !URL) {
throw new Error('AWS KEYS MISSING FROM ENVIRONMENT')
}
const aws = new AwsClient({
accessKeyId: AWS_API_ACCESS_KEY, // required, akin to AWS_ACCESS_KEY_ID
secretAccessKey: AWS_API_ACCESS_SECRET, // required, akin to AWS_SECRET_ACCESS_KEY
service: 'execute-api',
region: AWS_API_REGION, // AWS region, by default parsed at fetch time
})
const headers = {
'Content-Type': 'application/json',
'x-api-key': AWS_X_API_KEY,
}
const fetchQuery = (params: RequestParameters, variables: Variables): Promise<GraphQLResponse> => {
const body = JSON.stringify({
query: params.text, // GraphQL text from input
variables,
})
return aws.fetch(URL, { body, headers }).then((res) => res.json())
}
export default fetchQuery

@ -0,0 +1,398 @@
"""This directive allows results to be deferred during execution"""
directive @defer on FIELD
"""
Tells the service this field/object has access authorized by an API key.
"""
directive @aws_api_key on OBJECT | FIELD_DEFINITION
"""
Tells the service this field/object has access authorized by sigv4 signing.
"""
directive @aws_iam on OBJECT | FIELD_DEFINITION
"""
Tells the service which subscriptions will be published to when this mutation is
called. This directive is deprecated use @aws_susbscribe directive instead.
"""
directive @aws_publish(
"""
List of subscriptions which will be published to when this mutation is called.
"""
subscriptions: [String]
) on FIELD_DEFINITION
"""
Tells the service this field/object has access authorized by an OIDC token.
"""
directive @aws_oidc on OBJECT | FIELD_DEFINITION
"""
Tells the service this field/object has access authorized by a Cognito User Pools token.
"""
directive @aws_cognito_user_pools(
"""List of cognito user pool groups which have access on this field"""
cognito_groups: [String]
) on OBJECT | FIELD_DEFINITION
"""
Tells the service this field/object has access authorized by a Lambda Authorizer.
"""
directive @aws_lambda on OBJECT | FIELD_DEFINITION
"""Tells the service which mutation triggers this subscription."""
directive @aws_subscribe(
"""
List of mutations which will trigger this subscription when they are called.
"""
mutations: [String]
) on FIELD_DEFINITION
"""Directs the schema to enforce authorization on a field"""
directive @aws_auth(
"""List of cognito user pool groups which have access on this field"""
cognito_groups: [String]
) on FIELD_DEFINITION
enum ActivityType {
APPROVE
CANCEL
CLAIM
SEND
RECEIVE
SWAP
DEPLOYMENT
UNKNOWN
money
market
LEND
BORROW
REPAY
WITHDRAW
NFT
MINT
BURN
Staking
STAKE
UNSTAKE
}
type Amount implements IAmount {
id: ID!
currency: Currency
value: Float
}
type AssetActivity {
id: ID!
timestamp: Int!
type: ActivityType!
gasUsed: Float
transaction: Transaction!
assetChanges: [AssetChange]!
}
union AssetChange = TokenTransfer | NftTransfer | TokenApproval | NftApproval | NftApproveForAll
enum Chain {
ARBITRUM
ETHEREUM
ETHEREUM_GOERLI
OPTIMISM
POLYGON
}
input ContractInput {
chain: Chain!
address: String
}
enum Currency {
USD
ETH
}
enum HighLow {
HIGH
LOW
}
enum HistoryDuration {
HOUR
DAY
WEEK
MONTH
YEAR
MAX
}
interface IAmount {
currency: Currency
value: Float
}
interface IContract {
chain: Chain!
address: String
}
enum MarketSortableField {
MARKET_CAP
VOLUME
}
type NftApproval {
id: ID!
nftStandard: NftStandard!
""" can be erc20 or erc1155"""
asset: NftAsset!
approvedAddress: String!
}
type NftApproveForAll {
id: ID!
nftStandard: NftStandard!
""" can be erc721 or erc1155"""
asset: NftAsset!
operatorAddress: String!
approved: Boolean!
}
type NftAsset {
id: ID!
collection: NftCollection
description: String
imageUrl: String
thumbnailUrl: String
animationUrl: String
smallImageUrl: String
name: String
nftContract: NftContract
"""
TODO: may need to be array to support erc1155 cases. not needed at the moment so will revisit.
ownerAddress: String
"""
tokenId: String
traits: [NftAssetTrait]
}
enum NftAssetSortableField {
PRICE
}
type NftAssetTrait {
id: ID!
name: String
rarity: Float
value: String
}
type NftBalance {
id: ID!
ownedAsset: NftAsset
}
type NftCollection {
id: ID!
collectionId: String
"""
TODO: support querying for collection assets here
assets(page: Int, pageSize: Int, orderBy: NftAssetSortableField): [NftAsset]
"""
bannerImageUrl: String
description: String
discordUrl: String
homepageUrl: String
imageUrl: String
instagramName: String
markets(currencies: [Currency!]!): [NftCollectionMarket]
name: String
nftContracts: [NftContract]
openseaUrl: String
"""
TODO: support collection-level traits.
traits: [NftCollectionTraits] (not needed yet)
"""
twitterName: String
isVerified: Boolean
numAssets: Int
}
type NftCollectionMarket {
id: ID!
floorPrice: Amount
owners: Int
volume24h: Amount
totalVolume: Amount
}
type NftCollectionTraits {
id: ID!
name: String
values: [String]
}
type NftContract implements IContract {
id: ID!
address: String
chain: Chain!
name: String
standard: NftStandard
symbol: String
totalSupply: Int
}
enum NftMarketSortableField {
VOLUME
FLOOR_PRICE
}
enum NftStandard {
ERC721
ERC1155
NONCOMPLIANT
}
type NftTransfer {
id: ID!
nftStandard: NftStandard!
asset: NftAsset!
sender: String!
recipient: String!
direction: TransactionDirection!
}
type Portfolio {
id: ID!
ownerAddress: String!
tokensTotalDenominatedValue: Amount
tokensTotalDenominatedValueHistory(duration: HistoryDuration): [TimestampedAmount]
tokenBalances: [TokenBalance]
assetsValueUSD: Float
totalValueUSD: Float
assetsValue: Float
totalValue: Float
absoluteChange24H: Float
relativeChange24H: Float
nftBalances: [NftBalance]
}
type Query {
tokens(contracts: [ContractInput]): [Token]
tokenProjects(contracts: [ContractInput]): [TokenProject]
topTokenProjects(orderBy: MarketSortableField, page: Int, pageSize: Int, currency: Currency): [TokenProject]
searchTokens(searchQuery: String!): [Token]
assetActivities(address: String!, page: Int, pageSize: Int): [AssetActivity]
portfolio(ownerAddress: String!): Portfolio
portfolios(ownerAddresses: [String!]!): [Portfolio]
nftCollectionsById(collectionIds: [String]): [NftCollection]
}
type TimestampedAmount implements IAmount {
id: ID!
currency: Currency
value: Float
timestamp: Int!
}
type Token implements IContract {
id: ID!
chain: Chain!
address: String
standard: TokenStandard
decimals: Int
name: String
symbol: String
}
type TokenApproval {
id: ID!
tokenStandard: TokenStandard!
""" can be erc20 or erc1155"""
asset: Token!
approvedAddress: String!
quantity: String!
}
type TokenBalance {
id: ID!
quantity: Float
denominatedValue: Amount
ownerAddress: String!
token: Token
tokenProjectMarket: TokenProjectMarket
}
type TokenProject {
id: ID!
name: String
tokens: [Token!]!
description: String
twitterName: String
homepageUrl: String
logoUrl: String
markets(currencies: [Currency!]!): [TokenProjectMarket]
}
type TokenProjectMarket {
id: ID!
tokenProject: TokenProject!
currency: Currency!
price: Amount
volume24h: Amount
pricePercentChange24h: Amount
marketCap: Amount
fullyDilutedMarketCap: Amount
priceHistory(duration: HistoryDuration!): [TimestampedAmount]
volume(duration: HistoryDuration!): Amount
pricePercentChange(duration: HistoryDuration!): Amount
priceHighLow(duration: HistoryDuration!, highLow: HighLow!): Amount
}
enum TokenStandard {
NATIVE
ERC20
ERC1155
}
type TokenTransfer {
id: ID!
tokenStandard: TokenStandard!
asset: Token!
sender: String!
recipient: String!
quantity: String!
direction: TransactionDirection!
transactedValue: Amount
}
type Transaction {
id: ID!
blockNumber: Int!
from: String!
to: String!
hash: String!
nonce: Int!
gasLimit: Float
maxFeePerGas: Float
status: TransactionStatus!
}
enum TransactionDirection {
IN
OUT
SELF
}
enum TransactionStatus {
FAILED
CONFIRMED
PENDING
}

@ -1,13 +1,14 @@
import graphql from 'babel-plugin-relay/macro'
import useInterval from 'lib/hooks/useInterval'
import { useCallback, useEffect, useState } from 'react'
import { fetchQuery, useRelayEnvironment } from 'relay-hooks'
import { fetchQuery } from 'react-relay'
import { useAppSelector } from 'state/hooks'
import type {
AllV3TicksQuery as AllV3TicksQueryType,
AllV3TicksQuery$data,
} from './__generated__/AllV3TicksQuery.graphql'
import environment from './RelayEnvironment'
const query = graphql`
query AllV3TicksQuery($poolAddress: String!, $skip: Int!) {
@ -28,7 +29,6 @@ export default function useAllV3TicksQuery(poolAddress: string | undefined, skip
const [error, setError] = useState<any>(null)
const [isLoading, setIsLoading] = useState(true)
const chainId = useAppSelector((state) => state.application.chainId)
const environment = useRelayEnvironment()
const refreshData = useCallback(() => {
if (poolAddress && chainId) {
@ -43,7 +43,7 @@ export default function useAllV3TicksQuery(poolAddress: string | undefined, skip
} else {
setIsLoading(false)
}
}, [poolAddress, skip, chainId, environment])
}, [poolAddress, skip, chainId])
// Trigger fetch on first load
useEffect(refreshData, [refreshData, poolAddress, skip])

@ -1,13 +1,14 @@
import graphql from 'babel-plugin-relay/macro'
import useInterval from 'lib/hooks/useInterval'
import { useCallback, useEffect, useState } from 'react'
import { fetchQuery, useRelayEnvironment } from 'relay-hooks'
import { fetchQuery } from 'react-relay'
import { useAppSelector } from 'state/hooks'
import type {
FeeTierDistributionQuery as FeeTierDistributionQueryType,
FeeTierDistributionQuery$data,
} from './__generated__/FeeTierDistributionQuery.graphql'
import environment from './RelayEnvironment'
const query = graphql`
query FeeTierDistributionQuery($token0: String!, $token1: String!) {
@ -45,7 +46,6 @@ export default function useFeeTierDistributionQuery(
const [data, setData] = useState<FeeTierDistributionQuery$data | null>(null)
const [error, setError] = useState<any>(null)
const [isLoading, setIsLoading] = useState(true)
const environment = useRelayEnvironment()
const chainId = useAppSelector((state) => state.application.chainId)
const refreshData = useCallback(() => {
@ -59,7 +59,7 @@ export default function useFeeTierDistributionQuery(
complete: () => setIsLoading(false),
})
}
}, [token0, token1, chainId, environment])
}, [token0, token1, chainId])
// Trigger fetch on first load
useEffect(refreshData, [refreshData, token0, token1])

@ -0,0 +1,9 @@
import { Environment, Network, RecordSource, Store } from 'relay-runtime'
import fetchGraphQL from './fetchGraphQL'
// Export a singleton instance of Relay Environment configured with our network function:
export default new Environment({
network: Network.create(fetchGraphQL),
store: new Store(new RecordSource()),
})

@ -8,7 +8,7 @@ import { SupportedChainId } from 'constants/chains'
import { Variables } from 'react-relay'
import { GraphQLResponse, ObservableFromValue, RequestParameters } from 'relay-runtime'
import store, { AppState } from '../state/index'
import store, { AppState } from '../../state/index'
const CHAIN_SUBGRAPH_URL: Record<number, string> = {
[SupportedChainId.MAINNET]: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3',

@ -1,167 +0,0 @@
/**
* @generated SignedSource<<0becdf63598262462f6fa0cabb891ad0>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest, Query } from 'relay-runtime';
export type AllV3TicksQuery$variables = {
poolAddress: string;
skip: number;
};
export type AllV3TicksQuery$data = {
readonly ticks: ReadonlyArray<{
readonly liquidityNet: any;
readonly price0: any;
readonly price1: any;
readonly tick: any;
}>;
};
export type AllV3TicksQuery = {
response: AllV3TicksQuery$data;
variables: AllV3TicksQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "poolAddress"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "skip"
}
],
v1 = [
{
"kind": "Literal",
"name": "first",
"value": 1000
},
{
"kind": "Literal",
"name": "orderBy",
"value": "tickIdx"
},
{
"kind": "Variable",
"name": "skip",
"variableName": "skip"
},
{
"fields": [
{
"kind": "Variable",
"name": "poolAddress",
"variableName": "poolAddress"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v2 = {
"alias": "tick",
"args": null,
"kind": "ScalarField",
"name": "tickIdx",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "liquidityNet",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "price0",
"storageKey": null
},
v5 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "price1",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "AllV3TicksQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": "Tick",
"kind": "LinkedField",
"name": "ticks",
"plural": true,
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/)
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "AllV3TicksQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": "Tick",
"kind": "LinkedField",
"name": "ticks",
"plural": true,
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "9f2d65b1e565e3d0ecbe7b1f908ebc83",
"id": null,
"metadata": {},
"name": "AllV3TicksQuery",
"operationKind": "query",
"text": "query AllV3TicksQuery(\n $poolAddress: String!\n $skip: Int!\n) {\n ticks(first: 1000, skip: $skip, where: {poolAddress: $poolAddress}, orderBy: tickIdx) {\n tick: tickIdx\n liquidityNet\n price0\n price1\n id\n }\n}\n"
}
};
})();
(node as any).hash = "82709c11c929a8eb6caf2ab1df2b99cc";
export default node;

@ -1,242 +0,0 @@
/**
* @generated SignedSource<<5761481cf3bba524864626a7f965c0d7>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest, Query } from 'relay-runtime';
export type FeeTierDistributionQuery$variables = {
token0: string;
token1: string;
};
export type FeeTierDistributionQuery$data = {
readonly _meta: {
readonly block: {
readonly number: number;
};
} | null;
readonly asToken0: ReadonlyArray<{
readonly feeTier: any;
readonly totalValueLockedToken0: any;
readonly totalValueLockedToken1: any;
}>;
readonly asToken1: ReadonlyArray<{
readonly feeTier: any;
readonly totalValueLockedToken0: any;
readonly totalValueLockedToken1: any;
}>;
};
export type FeeTierDistributionQuery = {
response: FeeTierDistributionQuery$data;
variables: FeeTierDistributionQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "token0"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "token1"
}
],
v1 = {
"alias": null,
"args": null,
"concreteType": "_Meta_",
"kind": "LinkedField",
"name": "_meta",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "_Block_",
"kind": "LinkedField",
"name": "block",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "number",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
},
v2 = {
"kind": "Literal",
"name": "orderBy",
"value": "totalValueLockedToken0"
},
v3 = {
"kind": "Literal",
"name": "orderDirection",
"value": "desc"
},
v4 = [
(v2/*: any*/),
(v3/*: any*/),
{
"fields": [
{
"kind": "Variable",
"name": "token0",
"variableName": "token0"
},
{
"kind": "Variable",
"name": "token1",
"variableName": "token1"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v5 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "feeTier",
"storageKey": null
},
v6 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalValueLockedToken0",
"storageKey": null
},
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalValueLockedToken1",
"storageKey": null
},
v8 = [
(v5/*: any*/),
(v6/*: any*/),
(v7/*: any*/)
],
v9 = [
(v2/*: any*/),
(v3/*: any*/),
{
"fields": [
{
"kind": "Variable",
"name": "token0",
"variableName": "token1"
},
{
"kind": "Variable",
"name": "token1",
"variableName": "token0"
}
],
"kind": "ObjectValue",
"name": "where"
}
],
v10 = [
(v5/*: any*/),
(v6/*: any*/),
(v7/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "FeeTierDistributionQuery",
"selections": [
(v1/*: any*/),
{
"alias": "asToken0",
"args": (v4/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v8/*: any*/),
"storageKey": null
},
{
"alias": "asToken1",
"args": (v9/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v8/*: any*/),
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "FeeTierDistributionQuery",
"selections": [
(v1/*: any*/),
{
"alias": "asToken0",
"args": (v4/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v10/*: any*/),
"storageKey": null
},
{
"alias": "asToken1",
"args": (v9/*: any*/),
"concreteType": "Pool",
"kind": "LinkedField",
"name": "pools",
"plural": true,
"selections": (v10/*: any*/),
"storageKey": null
}
]
},
"params": {
"cacheID": "d989fcfb8fc9ef13bdc6de811e574284",
"id": null,
"metadata": {},
"name": "FeeTierDistributionQuery",
"operationKind": "query",
"text": "query FeeTierDistributionQuery(\n $token0: String!\n $token1: String!\n) {\n _meta {\n block {\n number\n }\n }\n asToken0: pools(orderBy: totalValueLockedToken0, orderDirection: desc, where: {token0: $token0, token1: $token1}) {\n feeTier\n totalValueLockedToken0\n totalValueLockedToken1\n id\n }\n asToken1: pools(orderBy: totalValueLockedToken0, orderDirection: desc, where: {token0: $token1, token1: $token0}) {\n feeTier\n totalValueLockedToken0\n totalValueLockedToken1\n id\n }\n}\n"
}
};
})();
(node as any).hash = "ac9cd4bfdc24db90dbb2bf8a7508009f";
export default node;

@ -1,12 +1,12 @@
import { useEffect, useState } from 'react'
export enum TimePeriod {
hour = 'hour',
day = 'day',
week = 'week',
month = 'month',
year = 'year',
all = 'all',
HOUR,
DAY,
WEEK,
MONTH,
YEAR,
ALL,
}
export type TokenData = {
@ -35,12 +35,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 3.05,
delta: 12,
volume: {
[TimePeriod.hour]: 25_000,
[TimePeriod.day]: 619_000,
[TimePeriod.week]: 16_800_000,
[TimePeriod.month]: 58_920_000,
[TimePeriod.year]: 690_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 25_000,
[TimePeriod.DAY]: 619_000,
[TimePeriod.WEEK]: 16_800_000,
[TimePeriod.MONTH]: 58_920_000,
[TimePeriod.YEAR]: 690_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -52,12 +52,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 9.26543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -69,12 +69,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -86,12 +86,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -79,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 10_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 10_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -103,12 +103,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 10.66543,
delta: 56,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 7_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 7_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -120,12 +120,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: 60,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -137,12 +137,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: 560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 108_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 108_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -154,12 +154,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -50,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 10_000_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 10_000_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -171,12 +171,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 4.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -188,12 +188,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: 60,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 2_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 2_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -205,12 +205,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -222,12 +222,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -239,12 +239,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -256,12 +256,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: 70,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -273,12 +273,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -50,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -290,12 +290,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},
@ -307,12 +307,12 @@ const FAKE_TOP_TOKENS_RESULT: TokenData = {
price: 0.66543,
delta: -560,
volume: {
[TimePeriod.hour]: 5_000,
[TimePeriod.day]: 100_000,
[TimePeriod.week]: 800_000,
[TimePeriod.month]: 4_920_000,
[TimePeriod.year]: 100_920_000,
[TimePeriod.all]: 690_920_000,
[TimePeriod.HOUR]: 5_000,
[TimePeriod.DAY]: 100_000,
[TimePeriod.WEEK]: 800_000,
[TimePeriod.MONTH]: 4_920_000,
[TimePeriod.YEAR]: 100_920_000,
[TimePeriod.ALL]: 690_920_000,
},
isFavorite: false,
},

@ -5,7 +5,7 @@ import useBlockNumber from 'lib/hooks/useBlockNumber'
import ms from 'ms.macro'
import { useMemo } from 'react'
import useFeeTierDistributionQuery from '../graphql/FeeTierDistributionQuery'
import useFeeTierDistributionQuery from '../graphql/thegraph/FeeTierDistributionQuery'
import { PoolState, usePool } from './usePools'
// maximum number of blocks past which we consider the data stale

@ -3,7 +3,7 @@ import { FeeAmount, nearestUsableTick, Pool, TICK_SPACINGS, tickToPrice } from '
import { useWeb3React } from '@web3-react/core'
import { SupportedChainId } from 'constants/chains'
import { ZERO_ADDRESS } from 'constants/misc'
import useAllV3TicksQuery, { TickData } from 'graphql/AllV3TicksQuery'
import useAllV3TicksQuery, { TickData } from 'graphql/thegraph/AllV3TicksQuery'
import JSBI from 'jsbi'
import { useSingleContractMultipleData } from 'lib/hooks/multicall'
import ms from 'ms.macro'

@ -4,15 +4,15 @@ import 'polyfills'
import 'components/analytics'
import { FeatureFlagsProvider } from 'featureFlags'
import RelayEnvironment from 'graphql/RelayEnvironment'
import RelayEnvironment from 'graphql/data/RelayEnvironment'
import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import { MulticallUpdater } from 'lib/state/multicall'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { QueryClient, QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux'
import { RelayEnvironmentProvider } from 'react-relay'
import { HashRouter } from 'react-router-dom'
import { RelayEnvironmentProvider } from 'relay-hooks'
import Blocklist from './components/Blocklist'
import Web3Provider from './components/Web3Provider'

@ -3,7 +3,7 @@ import { tickToPrice } from '@uniswap/v3-sdk'
import { TickProcessed } from 'hooks/usePoolTickData'
import JSBI from 'jsbi'
import { Ticks } from '../graphql/AllV3TicksQuery'
import { Ticks } from '../graphql/thegraph/AllV3TicksQuery'
const PRICE_FIXED_DIGITS = 8

1637
yarn.lock

File diff suppressed because it is too large Load Diff