From df0c98e5fa5ca0876d46e7471cb63fb5fe6e2088 Mon Sep 17 00:00:00 2001 From: titix Date: Fri, 12 Jul 2024 09:54:06 -0300 Subject: [PATCH 1/6] feat: basic architecture --- src/components/CustomHead.tsx | 18 ++ src/components/index.ts | 1 + src/containers/Footer/index.tsx | 2 +- src/containers/Header/index.tsx | 2 +- src/data/chainMockData.ts | 190 ++++++++++++++++++ src/hooks/ScrollToTop.tsx | 19 -- src/hooks/index.ts | 3 +- src/hooks/useContext/index.ts | 1 + src/hooks/useContext/useData.tsx | 13 ++ .../{ => useContext}/useStateContext.tsx | 0 src/hooks/{ => useContext}/useTheme.tsx | 0 src/pages/[chain]/index.tsx | 14 ++ src/pages/index.tsx | 2 +- src/providers/DataProvider.tsx | 29 +++ src/types/Data.ts | 32 +++ src/types/index.ts | 1 + tsconfig.json | 2 +- 17 files changed, 304 insertions(+), 25 deletions(-) create mode 100644 src/components/CustomHead.tsx create mode 100644 src/data/chainMockData.ts delete mode 100644 src/hooks/ScrollToTop.tsx create mode 100644 src/hooks/useContext/index.ts create mode 100644 src/hooks/useContext/useData.tsx rename src/hooks/{ => useContext}/useStateContext.tsx (100%) rename src/hooks/{ => useContext}/useTheme.tsx (100%) create mode 100644 src/pages/[chain]/index.tsx create mode 100644 src/providers/DataProvider.tsx create mode 100644 src/types/Data.ts diff --git a/src/components/CustomHead.tsx b/src/components/CustomHead.tsx new file mode 100644 index 0000000..46a146b --- /dev/null +++ b/src/components/CustomHead.tsx @@ -0,0 +1,18 @@ +import Head from 'next/head'; + +interface MetadataProps { + title: string; + description?: string; + image?: string; + type?: string; +} + +export const CustomHead = ({ title }: MetadataProps) => { + return ( + + {`${title} - ZKchainHub`} + + + + ); +}; diff --git a/src/components/index.ts b/src/components/index.ts index 0fe1f0b..a25d295 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,2 +1,3 @@ export * from './Theme'; export * from './Disclaimer'; +export * from './CustomHead'; diff --git a/src/containers/Footer/index.tsx b/src/containers/Footer/index.tsx index 6fc8f48..5d98840 100644 --- a/src/containers/Footer/index.tsx +++ b/src/containers/Footer/index.tsx @@ -1,5 +1,5 @@ import { styled } from '@mui/material/styles'; -import { useCustomTheme } from '~/hooks/useTheme'; +import { useCustomTheme } from '~/hooks/useContext/useTheme'; import { FOOTER_HEIGHT } from '~/utils'; diff --git a/src/containers/Header/index.tsx b/src/containers/Header/index.tsx index 2caa8a9..6afb5cd 100644 --- a/src/containers/Header/index.tsx +++ b/src/containers/Header/index.tsx @@ -4,7 +4,7 @@ import { IconButton } from '@mui/material'; import LightModeIcon from '@mui/icons-material/LightMode'; import DarkModeIcon from '@mui/icons-material/DarkMode'; -import { useCustomTheme } from '~/hooks/useTheme'; +import { useCustomTheme } from '~/hooks/useContext/useTheme'; import { zIndex, HEADER_HEIGHT } from '~/utils'; export const Header = () => { diff --git a/src/data/chainMockData.ts b/src/data/chainMockData.ts new file mode 100644 index 0000000..3ea9a9b --- /dev/null +++ b/src/data/chainMockData.ts @@ -0,0 +1,190 @@ +export const mockData = [ + { + name: 'ZKSync Era', + chainId: 324, + website: 'https://example.com', + explorer: 'https://example.com', + launchDate: '2023-12-05', + environment: 'Production', + nativeToken: 'ETH', + chainType: 'ZKRollup', + lastBlock: 123456789, + lastBlockVerified: 123456788, + transactionsPerSecond: 15, + totalBatchesCommitted: 1234567890, + totalBatchesExecuted: 1234567890, + totalBatchesVerified: 123456788, + averageBlockTime: 100000, + tvl: { + ETH: { + value: 500000000, + address: '0x79db...d692', + }, + USDT: { + value: 100000000, + address: '0x79db...d692', + }, + USDC: { + value: 50000000, + address: '0x79db...d692', + }, + WBTC: { + value: 30000000, + address: '0x79db...d692', + }, + }, + rpcs: [ + { + status: 'Active', + url: 'https://lrpc.com', + }, + { + status: 'Active', + url: 'https://blastapi.com', + }, + { + status: 'Inactive', + url: 'https://llamarpc.com', + }, + { + status: 'Active', + url: 'https://alchemy.com', + }, + ], + feeParams: { + batchOverheadL1Gas: 1234567890, + computeOverheadPart: 1234567890, + maxGasPerBatch: 123456788, + }, + }, + { + name: 'Optimism', + chainId: 10, + website: 'https://optimism.io', + explorer: 'https://explorer.optimism.io', + launchDate: '2022-05-01', + environment: 'Production', + nativeToken: 'ETH', + chainType: 'Optimistic Rollup', + lastBlock: 987654321, + lastBlockVerified: 987654320, + transactionsPerSecond: 12, + totalBatchesCommitted: 987654321, + totalBatchesExecuted: 987654321, + totalBatchesVerified: 987654320, + averageBlockTime: 150000, + tvl: { + ETH: { + value: 700000000, + address: '0x1234...abcd', + }, + DAI: { + value: 200000000, + address: '0x1234...abcd', + }, + }, + rpcs: [ + { + status: 'Active', + url: 'https://mainnet.optimism.io', + }, + { + status: 'Inactive', + url: 'https://backup.optimism.io', + }, + ], + feeParams: { + batchOverheadL1Gas: 987654321, + computeOverheadPart: 987654321, + maxGasPerBatch: 987654320, + }, + }, + { + name: 'Arbitrum One', + chainId: 42161, + website: 'https://arbitrum.io', + explorer: 'https://explorer.arbitrum.io', + launchDate: '2021-08-31', + environment: 'Production', + nativeToken: 'ETH', + chainType: 'Optimistic Rollup', + lastBlock: 112233445, + lastBlockVerified: 112233444, + transactionsPerSecond: 20, + totalBatchesCommitted: 112233445, + totalBatchesExecuted: 112233445, + totalBatchesVerified: 112233444, + averageBlockTime: 80000, + tvl: { + ETH: { + value: 800000000, + address: '0xabcd...1234', + }, + LINK: { + value: 150000000, + address: '0xabcd...1234', + }, + USDC: { + value: 60000000, + address: '0xabcd...1234', + }, + }, + rpcs: [ + { + status: 'Active', + url: 'https://arb1.arbitrum.io', + }, + ], + feeParams: { + batchOverheadL1Gas: 112233445, + computeOverheadPart: 112233445, + maxGasPerBatch: 112233444, + }, + }, + { + name: 'Polygon', + chainId: 137, + website: 'https://polygon.technology', + explorer: 'https://explorer.matic.network', + launchDate: '2020-05-18', + environment: 'Production', + nativeToken: 'MATIC', + chainType: 'Sidechain', + lastBlock: 998877665, + lastBlockVerified: 998877664, + transactionsPerSecond: 30, + totalBatchesCommitted: 998877665, + totalBatchesExecuted: 998877665, + totalBatchesVerified: 998877664, + averageBlockTime: 20000, + tvl: { + MATIC: { + value: 400000000, + address: '0x5678...efgh', + }, + AAVE: { + value: 50000000, + address: '0x5678...efgh', + }, + WBTC: { + value: 25000000, + address: '0x5678...efgh', + }, + }, + rpcs: [ + { + status: 'Active', + url: 'https://rpc-mainnet.maticvigil.com', + }, + { + status: 'Active', + url: 'https://rpc-mainnet.matic.network', + }, + ], + feeParams: { + batchOverheadL1Gas: 998877665, + computeOverheadPart: 998877665, + maxGasPerBatch: 998877664, + }, + }, +]; diff --git a/src/hooks/ScrollToTop.tsx b/src/hooks/ScrollToTop.tsx deleted file mode 100644 index 1f720d7..0000000 --- a/src/hooks/ScrollToTop.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useEffect } from 'react'; -import { useRouter } from 'next/router'; - -export function ScrollToTop() { - const router = useRouter(); - - useEffect(() => { - const handleRouteChange = () => { - window.scrollTo(0, 0); - }; - router.events.on('routeChangeComplete', handleRouteChange); - - return () => { - router.events.off('routeChangeComplete', handleRouteChange); - }; - }, [router.events]); - - return null; -} diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 3ffc027..af3d0f4 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,2 +1 @@ -export * from './ScrollToTop'; -export * from './useStateContext'; +export * from './useContext'; diff --git a/src/hooks/useContext/index.ts b/src/hooks/useContext/index.ts new file mode 100644 index 0000000..92f170c --- /dev/null +++ b/src/hooks/useContext/index.ts @@ -0,0 +1 @@ +export * from './useStateContext'; diff --git a/src/hooks/useContext/useData.tsx b/src/hooks/useContext/useData.tsx new file mode 100644 index 0000000..43e0a8a --- /dev/null +++ b/src/hooks/useContext/useData.tsx @@ -0,0 +1,13 @@ +import { useContext } from 'react'; + +import { DataContext } from '~/providers/DataProvider'; + +export const useData = () => { + const context = useContext(DataContext); + + if (context === undefined) { + throw new Error('useData must be used within a StateProvider'); + } + + return context; +}; diff --git a/src/hooks/useStateContext.tsx b/src/hooks/useContext/useStateContext.tsx similarity index 100% rename from src/hooks/useStateContext.tsx rename to src/hooks/useContext/useStateContext.tsx diff --git a/src/hooks/useTheme.tsx b/src/hooks/useContext/useTheme.tsx similarity index 100% rename from src/hooks/useTheme.tsx rename to src/hooks/useContext/useTheme.tsx diff --git a/src/pages/[chain]/index.tsx b/src/pages/[chain]/index.tsx new file mode 100644 index 0000000..a472e99 --- /dev/null +++ b/src/pages/[chain]/index.tsx @@ -0,0 +1,14 @@ +import { CustomHead } from '~/components'; + +const Chain = () => { + const title = 'Chain placeholder'; + + return ( + <> + + {/* TODO: Add chain page containers */} + + ); +}; + +export default Chain; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 2283214..e78f744 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -6,7 +6,7 @@ const Home = () => { return ( <> - Web3 Boilerplate + ZKchainHub diff --git a/src/providers/DataProvider.tsx b/src/providers/DataProvider.tsx new file mode 100644 index 0000000..c4fc115 --- /dev/null +++ b/src/providers/DataProvider.tsx @@ -0,0 +1,29 @@ +import { createContext, useState } from 'react'; + +import { ChainData } from '~/types'; + +type ContextType = { + selectedChain?: ChainData; + setSelectedChain: (val: ChainData) => void; +}; + +interface DataProps { + children: React.ReactElement; +} + +export const DataContext = createContext({} as ContextType); + +export const DataProvider = ({ children }: DataProps) => { + const [selectedChain, setSelectedChain] = useState(); + + return ( + + {children} + + ); +}; diff --git a/src/types/Data.ts b/src/types/Data.ts new file mode 100644 index 0000000..ee96ebb --- /dev/null +++ b/src/types/Data.ts @@ -0,0 +1,32 @@ +export interface ChainData { + name: string; + chainId: number; + website: string; + explorer: string; + launchDate: string; + environment: string; + nativeToken: string; + chainType: string; + lastBlock: number; + lastBlockVerified: number; + transactionsPerSecond: number; + totalBatchesCommitted: number; + totalBatchesExecuted: number; + totalBatchesVerified: number; + averageBlockTime: number; + tvl: { + [token: string]: { + value: number; + address: string; + }; + }; + rpcs: { + status: string; + url: string; + }[]; + feeParams: { + batchOverheadL1Gas: number; + computeOverheadPart: number; + maxGasPerBatch: number; + }; +} diff --git a/src/types/index.ts b/src/types/index.ts index 54d9f8d..f5e98b2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,2 +1,3 @@ export * from './Config'; export * from './Theme'; +export * from './Data'; diff --git a/tsconfig.json b/tsconfig.json index 08b37f1..91e94bf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,6 +26,6 @@ "~/*": ["src/*"] } }, - "include": ["./src", "./dist/types/**/*.ts", "./next-env.d.ts", "./cypress/**/*.ts", "./jest.config.ts"], + "include": ["./src", "./dist/types/**/*.ts", "./next-env.d.ts", "./cypress/**/*.ts", "./jest.config.ts", "src/data/chainMockData.ts"], "exclude": ["./node_modules"] } \ No newline at end of file From 3e405d26f37aa123ebb1552ba6a1ddad2b1ea353 Mon Sep 17 00:00:00 2001 From: titix Date: Fri, 12 Jul 2024 17:37:48 -0300 Subject: [PATCH 2/6] feat: data fetching --- .env.example | 1 + .github/workflows/test.yml | 1 + src/config/env.ts | 2 + src/data/chainMockData.json | 60 ++++++++++ src/data/chainMockData.ts | 190 -------------------------------- src/data/ecosystemMockData.json | 92 ++++++++++++++++ src/pages/error.tsx | 5 + src/pages/index.tsx | 4 +- src/providers/DataProvider.tsx | 50 ++++++++- src/providers/index.tsx | 18 ++- src/types/Config.ts | 1 + src/types/Data.ts | 15 +++ src/types/index.ts | 6 +- src/utils/index.ts | 3 +- src/utils/services.ts | 29 +++++ 15 files changed, 274 insertions(+), 203 deletions(-) create mode 100644 src/data/chainMockData.json delete mode 100644 src/data/chainMockData.ts create mode 100644 src/data/ecosystemMockData.json create mode 100644 src/pages/error.tsx create mode 100644 src/utils/services.ts diff --git a/.env.example b/.env.example index fec4611..9607267 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ +NEXT_PUBLIC_API_URL= # Example: https://api.example.com NEXT_PUBLIC_RPC_URL= # Example: https://localhost:8545 NEXT_PUBLIC_PROJECT_ID= # ProjectID from WalletConnect NEXT_PUBLIC_ALCHEMY_KEY= # API key from Alchemy \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ea0cf54..2d3da82 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,7 @@ jobs: echo "NEXT_PUBLIC_RPC_URL=${{ secrets.NEXT_PUBLIC_RPC_URL }}" >> .env echo "NEXT_PUBLIC_PROJECT_ID=${{ secrets.NEXT_PUBLIC_PROJECT_ID }}" >> .env echo "NEXT_PUBLIC_ALCHEMY_KEY=${{ secrets.NEXT_PUBLIC_ALCHEMY_KEY }}" >> .env + echo "NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}" >> .env - name: run Cypress and Jest uses: cypress-io/github-action@v6 diff --git a/src/config/env.ts b/src/config/env.ts index 4d3ba54..dd425c6 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -4,10 +4,12 @@ export const getEnv = (): Env => { const NEXT_PUBLIC_RPC_URL = process.env.NEXT_PUBLIC_RPC_URL; const NEXT_PUBLIC_PROJECT_ID = process.env.NEXT_PUBLIC_PROJECT_ID; const NEXT_PUBLIC_ALCHEMY_KEY = process.env.NEXT_PUBLIC_ALCHEMY_KEY; + const NEXT_PUBLIC_API_URL = process.env.NEXT_PUBLIC_API_BASE_URL; return { RPC_URL: NEXT_PUBLIC_RPC_URL as string, PROJECT_ID: NEXT_PUBLIC_PROJECT_ID as string, ALCHEMY_KEY: NEXT_PUBLIC_ALCHEMY_KEY as string, + API_URL: NEXT_PUBLIC_API_URL as string, }; }; diff --git a/src/data/chainMockData.json b/src/data/chainMockData.json new file mode 100644 index 0000000..b7fe7b1 --- /dev/null +++ b/src/data/chainMockData.json @@ -0,0 +1,60 @@ +[ + { + "name": "ZKSync Era", + "chainId": 324, + "website": "https://example.com", + "explorer": "https://example.com", + "launchDate": "2023-12-05", + "environment": "Production", + "nativeToken": "ETH", + "chainType": "ZKRollup", + "lastBlock": 123456789, + "lastBlockVerified": 123456788, + "transactionsPerSecond": 15, + "totalBatchesCommitted": 1234567890, + "totalBatchesExecuted": 1234567890, + "totalBatchesVerified": 123456788, + "averageBlockTime": 100000, + "tvl": { + "ETH": { + "value": 500000000, + "address": "0x79db...d692" + }, + "USDT": { + "value": 100000000, + "address": "0x79db...d692" + }, + "USDC": { + "value": 50000000, + "address": "0x79db...d692" + }, + "WBTC": { + "value": 30000000, + "address": "0x79db...d692" + } + }, + "rpcs": [ + { + "status": "Active", + "url": "https://lrpc.com" + }, + { + "status": "Active", + "url": "https://blastapi.com" + }, + { + "status": "Inactive", + "url": "https://llamarpc.com" + }, + { + "status": "Active", + "url": "https://alchemy.com" + } + ], + "feeParams": { + "batchOverheadL1Gas": 1234567890, + "computeOverheadPart": 1234567890, + "maxGasPerBatch": 123456788 + } + } +] \ No newline at end of file diff --git a/src/data/chainMockData.ts b/src/data/chainMockData.ts deleted file mode 100644 index 3ea9a9b..0000000 --- a/src/data/chainMockData.ts +++ /dev/null @@ -1,190 +0,0 @@ -export const mockData = [ - { - name: 'ZKSync Era', - chainId: 324, - website: 'https://example.com', - explorer: 'https://example.com', - launchDate: '2023-12-05', - environment: 'Production', - nativeToken: 'ETH', - chainType: 'ZKRollup', - lastBlock: 123456789, - lastBlockVerified: 123456788, - transactionsPerSecond: 15, - totalBatchesCommitted: 1234567890, - totalBatchesExecuted: 1234567890, - totalBatchesVerified: 123456788, - averageBlockTime: 100000, - tvl: { - ETH: { - value: 500000000, - address: '0x79db...d692', - }, - USDT: { - value: 100000000, - address: '0x79db...d692', - }, - USDC: { - value: 50000000, - address: '0x79db...d692', - }, - WBTC: { - value: 30000000, - address: '0x79db...d692', - }, - }, - rpcs: [ - { - status: 'Active', - url: 'https://lrpc.com', - }, - { - status: 'Active', - url: 'https://blastapi.com', - }, - { - status: 'Inactive', - url: 'https://llamarpc.com', - }, - { - status: 'Active', - url: 'https://alchemy.com', - }, - ], - feeParams: { - batchOverheadL1Gas: 1234567890, - computeOverheadPart: 1234567890, - maxGasPerBatch: 123456788, - }, - }, - { - name: 'Optimism', - chainId: 10, - website: 'https://optimism.io', - explorer: 'https://explorer.optimism.io', - launchDate: '2022-05-01', - environment: 'Production', - nativeToken: 'ETH', - chainType: 'Optimistic Rollup', - lastBlock: 987654321, - lastBlockVerified: 987654320, - transactionsPerSecond: 12, - totalBatchesCommitted: 987654321, - totalBatchesExecuted: 987654321, - totalBatchesVerified: 987654320, - averageBlockTime: 150000, - tvl: { - ETH: { - value: 700000000, - address: '0x1234...abcd', - }, - DAI: { - value: 200000000, - address: '0x1234...abcd', - }, - }, - rpcs: [ - { - status: 'Active', - url: 'https://mainnet.optimism.io', - }, - { - status: 'Inactive', - url: 'https://backup.optimism.io', - }, - ], - feeParams: { - batchOverheadL1Gas: 987654321, - computeOverheadPart: 987654321, - maxGasPerBatch: 987654320, - }, - }, - { - name: 'Arbitrum One', - chainId: 42161, - website: 'https://arbitrum.io', - explorer: 'https://explorer.arbitrum.io', - launchDate: '2021-08-31', - environment: 'Production', - nativeToken: 'ETH', - chainType: 'Optimistic Rollup', - lastBlock: 112233445, - lastBlockVerified: 112233444, - transactionsPerSecond: 20, - totalBatchesCommitted: 112233445, - totalBatchesExecuted: 112233445, - totalBatchesVerified: 112233444, - averageBlockTime: 80000, - tvl: { - ETH: { - value: 800000000, - address: '0xabcd...1234', - }, - LINK: { - value: 150000000, - address: '0xabcd...1234', - }, - USDC: { - value: 60000000, - address: '0xabcd...1234', - }, - }, - rpcs: [ - { - status: 'Active', - url: 'https://arb1.arbitrum.io', - }, - ], - feeParams: { - batchOverheadL1Gas: 112233445, - computeOverheadPart: 112233445, - maxGasPerBatch: 112233444, - }, - }, - { - name: 'Polygon', - chainId: 137, - website: 'https://polygon.technology', - explorer: 'https://explorer.matic.network', - launchDate: '2020-05-18', - environment: 'Production', - nativeToken: 'MATIC', - chainType: 'Sidechain', - lastBlock: 998877665, - lastBlockVerified: 998877664, - transactionsPerSecond: 30, - totalBatchesCommitted: 998877665, - totalBatchesExecuted: 998877665, - totalBatchesVerified: 998877664, - averageBlockTime: 20000, - tvl: { - MATIC: { - value: 400000000, - address: '0x5678...efgh', - }, - AAVE: { - value: 50000000, - address: '0x5678...efgh', - }, - WBTC: { - value: 25000000, - address: '0x5678...efgh', - }, - }, - rpcs: [ - { - status: 'Active', - url: 'https://rpc-mainnet.maticvigil.com', - }, - { - status: 'Active', - url: 'https://rpc-mainnet.matic.network', - }, - ], - feeParams: { - batchOverheadL1Gas: 998877665, - computeOverheadPart: 998877665, - maxGasPerBatch: 998877664, - }, - }, -]; diff --git a/src/data/ecosystemMockData.json b/src/data/ecosystemMockData.json new file mode 100644 index 0000000..8605087 --- /dev/null +++ b/src/data/ecosystemMockData.json @@ -0,0 +1,92 @@ +{ + "chains": [ + { + "name": "zkSync Era", + "id": 324, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "Teva Chain", + "id": 100, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "Cronos zkEVM", + "id": 101, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "GRVT", + "id": 102, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "Lens", + "id": 103, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "ZKChain 104", + "id": 104, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "ZKChain 105", + "id": 105, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + } + ], + "tvl": [ + { + "token": "ETH", + "value": 557596566 + }, + { + "token": "USDC", + "value": 90091851 + }, + { + "token": "KOI", + "value": 32757850 + }, + { + "token": "USDT", + "value": 18021853 + }, + { + "token": "WBTC", + "value": 12620248 + }, + { + "token": "wstETH", + "value": 3552439 + }, + { + "token": "MUTE", + "value": 2071481 + }, + { + "token": "rETH", + "value": 1404096 + }, + { + "token": "DAI", + "value": 1080375 + } + ] + } + \ No newline at end of file diff --git a/src/pages/error.tsx b/src/pages/error.tsx new file mode 100644 index 0000000..cb4879f --- /dev/null +++ b/src/pages/error.tsx @@ -0,0 +1,5 @@ +const ErrorPage = () => { + return
Sorry, something went wrong.
; +}; + +export default ErrorPage; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index e78f744..d753b21 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,7 +2,7 @@ import Head from 'next/head'; import { Landing } from '~/containers'; -const Home = () => { +const Ecosystem = () => { return ( <> @@ -13,4 +13,4 @@ const Home = () => { ); }; -export default Home; +export default Ecosystem; diff --git a/src/providers/DataProvider.tsx b/src/providers/DataProvider.tsx index c4fc115..720f5ba 100644 --- a/src/providers/DataProvider.tsx +++ b/src/providers/DataProvider.tsx @@ -1,10 +1,19 @@ -import { createContext, useState } from 'react'; +import { createContext, useState, useEffect } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useRouter } from 'next/router'; -import { ChainData } from '~/types'; +import { ChainData, EcosystemData } from '~/types'; +import { fetchEcosystemData, fetchChainData } from '~/utils'; type ContextType = { selectedChain?: ChainData; setSelectedChain: (val: ChainData) => void; + + isEcosystemLoading: boolean; + isChainLoading: boolean; + + ecosystemData: EcosystemData; + chainData: ChainData; }; interface DataProps { @@ -15,12 +24,49 @@ export const DataContext = createContext({} as ContextType); export const DataProvider = ({ children }: DataProps) => { const [selectedChain, setSelectedChain] = useState(); + const router = useRouter(); + + const { + isLoading: isEcosystemLoading, + data: ecosystemData, + isError: isEcosystemError, + } = useQuery({ + queryKey: ['ecosystem'], + queryFn: fetchEcosystemData, + }); + + const { + isLoading: isChainLoading, + data: chainData, + isError: isChainError, + refetch: refetchChainData, + } = useQuery({ + queryKey: ['chainData', selectedChain?.chainId], + queryFn: () => fetchChainData(selectedChain!.chainId!), + enabled: !!selectedChain?.chainId, + }); + + useEffect(() => { + if (selectedChain) { + refetchChainData(); + } + }, [selectedChain, refetchChainData]); + + useEffect(() => { + if (isEcosystemError || isChainError) { + router.push('/error'); + } + }, [isEcosystemError, isChainError, router]); return ( {children} diff --git a/src/providers/index.tsx b/src/providers/index.tsx index 3047956..b702aa5 100644 --- a/src/providers/index.tsx +++ b/src/providers/index.tsx @@ -1,19 +1,27 @@ import type { ReactNode } from 'react'; +import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; import { StateProvider } from './StateProvider'; import { ThemeProvider } from './ThemeProvider'; import { WalletProvider } from './WalletProvider'; +import { DataProvider } from './DataProvider'; type Props = { children: ReactNode; }; +const queryClient = new QueryClient(); + export const Providers = ({ children }: Props) => { return ( - - - {children} - - + + + + + {children} + + + + ); }; diff --git a/src/types/Config.ts b/src/types/Config.ts index 7537f5c..3bd98b1 100644 --- a/src/types/Config.ts +++ b/src/types/Config.ts @@ -2,6 +2,7 @@ export interface Env { RPC_URL: string; PROJECT_ID: string; ALCHEMY_KEY: string; + API_URL: string; } export interface Constants { diff --git a/src/types/Data.ts b/src/types/Data.ts index ee96ebb..4598036 100644 --- a/src/types/Data.ts +++ b/src/types/Data.ts @@ -30,3 +30,18 @@ export interface ChainData { maxGasPerBatch: number; }; } + +export interface EcosystemData { + chain: { + name: string; + id: number; + nativeToken: string; + tvl: { + [token: string]: number; + }; + type: string; + }; + tvl: { + [token: string]: number; + }[]; +} diff --git a/src/types/index.ts b/src/types/index.ts index f5e98b2..4b0c6e3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,3 @@ -export * from './Config'; -export * from './Theme'; -export * from './Data'; +export * from './config'; +export * from './theme'; +export * from './data'; diff --git a/src/utils/index.ts b/src/utils/index.ts index a54ea12..9c03d2a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,5 @@ export * from './getTheme'; -export * from './Variables'; +export * from './variables'; export * from './config'; export * from './format'; +export * from './services'; diff --git a/src/utils/services.ts b/src/utils/services.ts new file mode 100644 index 0000000..6c9490b --- /dev/null +++ b/src/utils/services.ts @@ -0,0 +1,29 @@ +import { getConfig } from '~/config'; +import ecosystemMockData from '~/data/ecosystemMockData.json'; +import chainMockData from '~/data/chainMockData.json'; + +const { API_URL } = getConfig(); + +export const fetchEcosystemData = async () => { + // temporary for mock data + if (!API_URL) { + return Promise.resolve(ecosystemMockData); + } + const res = await fetch(`${API_URL}/ecosystem`); + if (!res.ok) { + throw new Error('Failed to fetch ecosystem data'); + } + return res.json(); +}; + +export const fetchChainData = async (chainId: number) => { + // temporary for mock data + if (!API_URL) { + return Promise.resolve(chainMockData); + } + const res = await fetch(`${API_URL}/zkchain/${chainId}`); + if (!res.ok) { + throw new Error('Failed to fetch chain data'); + } + return res.json(); +}; From 1138baf463d77c247c23bca8bec3f802997870d9 Mon Sep 17 00:00:00 2001 From: titix Date: Fri, 12 Jul 2024 17:41:51 -0300 Subject: [PATCH 3/6] style: file name --- src/utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 9c03d2a..2b5edbb 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,5 @@ export * from './getTheme'; -export * from './variables'; +export * from './Variables'; export * from './config'; export * from './format'; export * from './services'; From 1a5f8e5f27dfef0c91156cd6042cc1ccf32bf5e3 Mon Sep 17 00:00:00 2001 From: titix Date: Fri, 12 Jul 2024 17:45:11 -0300 Subject: [PATCH 4/6] style: file name --- src/types/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/index.ts b/src/types/index.ts index 4b0c6e3..f5e98b2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,3 @@ -export * from './config'; -export * from './theme'; -export * from './data'; +export * from './Config'; +export * from './Theme'; +export * from './Data'; From a0ca85a36329a9756e54dd1153398aac21fa697c Mon Sep 17 00:00:00 2001 From: titix Date: Fri, 12 Jul 2024 17:47:53 -0300 Subject: [PATCH 5/6] style: json formatting --- src/data/chainMockData.json | 2 +- src/data/ecosystemMockData.json | 181 ++++++++++++++++---------------- 2 files changed, 91 insertions(+), 92 deletions(-) diff --git a/src/data/chainMockData.json b/src/data/chainMockData.json index b7fe7b1..767de09 100644 --- a/src/data/chainMockData.json +++ b/src/data/chainMockData.json @@ -57,4 +57,4 @@ "maxGasPerBatch": 123456788 } } -] \ No newline at end of file +] diff --git a/src/data/ecosystemMockData.json b/src/data/ecosystemMockData.json index 8605087..f738e79 100644 --- a/src/data/ecosystemMockData.json +++ b/src/data/ecosystemMockData.json @@ -1,92 +1,91 @@ { - "chains": [ - { - "name": "zkSync Era", - "id": 324, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "ZKRollup" - }, - { - "name": "Teva Chain", - "id": 100, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "ZKRollup" - }, - { - "name": "Cronos zkEVM", - "id": 101, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "Validium" - }, - { - "name": "GRVT", - "id": 102, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "Validium" - }, - { - "name": "Lens", - "id": 103, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "Validium" - }, - { - "name": "ZKChain 104", - "id": 104, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "ZKRollup" - }, - { - "name": "ZKChain 105", - "id": 105, - "nativeToken": "ETH", - "tvl": 1000000, - "type": "Validium" - } - ], - "tvl": [ - { - "token": "ETH", - "value": 557596566 - }, - { - "token": "USDC", - "value": 90091851 - }, - { - "token": "KOI", - "value": 32757850 - }, - { - "token": "USDT", - "value": 18021853 - }, - { - "token": "WBTC", - "value": 12620248 - }, - { - "token": "wstETH", - "value": 3552439 - }, - { - "token": "MUTE", - "value": 2071481 - }, - { - "token": "rETH", - "value": 1404096 - }, - { - "token": "DAI", - "value": 1080375 - } - ] - } - \ No newline at end of file + "chains": [ + { + "name": "zkSync Era", + "id": 324, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "Teva Chain", + "id": 100, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "Cronos zkEVM", + "id": 101, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "GRVT", + "id": 102, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "Lens", + "id": 103, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + }, + { + "name": "ZKChain 104", + "id": 104, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "ZKRollup" + }, + { + "name": "ZKChain 105", + "id": 105, + "nativeToken": "ETH", + "tvl": 1000000, + "type": "Validium" + } + ], + "tvl": [ + { + "token": "ETH", + "value": 557596566 + }, + { + "token": "USDC", + "value": 90091851 + }, + { + "token": "KOI", + "value": 32757850 + }, + { + "token": "USDT", + "value": 18021853 + }, + { + "token": "WBTC", + "value": 12620248 + }, + { + "token": "wstETH", + "value": 3552439 + }, + { + "token": "MUTE", + "value": 2071481 + }, + { + "token": "rETH", + "value": 1404096 + }, + { + "token": "DAI", + "value": 1080375 + } + ] +} From 7ab5a8dbe0db96f671a82cd4c5df3bbb5049542e Mon Sep 17 00:00:00 2001 From: titix Date: Mon, 15 Jul 2024 16:55:00 -0300 Subject: [PATCH 6/6] fix: queryClient | remove refetch effect --- src/providers/DataProvider.tsx | 14 +++++--------- src/providers/index.tsx | 19 +++++++------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/providers/DataProvider.tsx b/src/providers/DataProvider.tsx index 720f5ba..f8d02a3 100644 --- a/src/providers/DataProvider.tsx +++ b/src/providers/DataProvider.tsx @@ -1,5 +1,5 @@ -import { createContext, useState, useEffect } from 'react'; -import { useQuery } from '@tanstack/react-query'; +import { createContext, useState, useEffect, ReactNode } from 'react'; +import { useQuery, UseQueryResult } from '@tanstack/react-query'; import { useRouter } from 'next/router'; import { ChainData, EcosystemData } from '~/types'; @@ -11,13 +11,14 @@ type ContextType = { isEcosystemLoading: boolean; isChainLoading: boolean; + refetchChainData: (options: { throwOnError: boolean; cancelRefetch: boolean }) => Promise; ecosystemData: EcosystemData; chainData: ChainData; }; interface DataProps { - children: React.ReactElement; + children: ReactNode; } export const DataContext = createContext({} as ContextType); @@ -46,12 +47,6 @@ export const DataProvider = ({ children }: DataProps) => { enabled: !!selectedChain?.chainId, }); - useEffect(() => { - if (selectedChain) { - refetchChainData(); - } - }, [selectedChain, refetchChainData]); - useEffect(() => { if (isEcosystemError || isChainError) { router.push('/error'); @@ -67,6 +62,7 @@ export const DataProvider = ({ children }: DataProps) => { isChainLoading, ecosystemData, chainData, + refetchChainData, }} > {children} diff --git a/src/providers/index.tsx b/src/providers/index.tsx index b702aa5..6bfc7e8 100644 --- a/src/providers/index.tsx +++ b/src/providers/index.tsx @@ -1,5 +1,4 @@ import type { ReactNode } from 'react'; -import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; import { StateProvider } from './StateProvider'; import { ThemeProvider } from './ThemeProvider'; @@ -10,18 +9,14 @@ type Props = { children: ReactNode; }; -const queryClient = new QueryClient(); - export const Providers = ({ children }: Props) => { return ( - - - - - {children} - - - - + + + + {children} + + + ); };