From 4d17d82eacb66f76654c5c98f7655b170c833041 Mon Sep 17 00:00:00 2001 From: QuanPT <77958905+quanpt-orai@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:32:33 +0700 Subject: [PATCH] Feat/add gpu credit page (#12) * feat: mock ui * feat: add UI before connect github header feat: add UI after connected github feat: add UI for header after connected github feat: add logic store code when connected to github feat: add redirect page when connected Github feat: add csrf token when connected Github feat: add logout with github feat: add redirect to origin page when connect github * refactor: remove duplicate icon * feat: add login by github function - refactor cumbersome file names * feat(gpu credit): integrate with apis * feat: add api check credit balance - sync refresh token into 1 request * feat: add error handle for login failed * feat: add error message when query failed * feat: add env vars for github login --------- Co-authored-by: ledanghuy1811 --- .env.example | 5 +- package.json | 5 +- src/assets/icons/github.svg | 10 + src/assets/icons/gpu_credit.svg | 10 + src/assets/icons/gpu_staking.svg | 13 +- src/assets/icons/key.svg | 10 + src/assets/icons/logout-git.svg | 3 + src/assets/icons/nav-arrow-down.svg | 5 + src/assets/images/bg-gpu-credit-balance.png | Bin 0 -> 86868 bytes src/assets/images/connected-img.png | Bin 0 -> 2467 bytes src/assets/images/flicker-dot.svg | 4 + src/assets/images/jupyterhub.png | Bin 0 -> 2486 bytes src/assets/images/no-credit-usage-history.svg | 12 + src/components/Button/Button.module.scss | 18 + src/components/Button/Button.tsx | 5 +- src/components/GithubConnect/helper.ts | 11 + .../GithubConnect/index.module.scss | 101 +++++ src/components/GithubConnect/index.tsx | 114 ++++++ src/components/Table/Table.module.scss | 4 + src/components/Table/Table.tsx | 46 ++- src/layouts/Menu.module.scss | 28 +- src/layouts/Menu.tsx | 25 +- src/layouts/Sidebar.tsx | 2 + src/pages/GithubLogin/index.module.scss | 54 +++ src/pages/GithubLogin/index.tsx | 64 ++++ src/pages/GpuCredit/index.module.scss | 282 ++++++++++++++ src/pages/GpuCredit/index.tsx | 362 ++++++++++++++++++ src/reducer/auth.ts | 40 ++ src/reducer/type.ts | 9 + src/rest/request.ts | 50 ++- src/routes.tsx | 5 +- src/store/configure.ts | 4 +- src/utils/githubCode.ts | 13 + tsconfig.json | 2 +- yarn.lock | 24 +- 35 files changed, 1297 insertions(+), 43 deletions(-) create mode 100644 src/assets/icons/github.svg create mode 100644 src/assets/icons/gpu_credit.svg create mode 100644 src/assets/icons/key.svg create mode 100644 src/assets/icons/logout-git.svg create mode 100644 src/assets/icons/nav-arrow-down.svg create mode 100644 src/assets/images/bg-gpu-credit-balance.png create mode 100644 src/assets/images/connected-img.png create mode 100644 src/assets/images/flicker-dot.svg create mode 100644 src/assets/images/jupyterhub.png create mode 100644 src/assets/images/no-credit-usage-history.svg create mode 100644 src/components/GithubConnect/helper.ts create mode 100644 src/components/GithubConnect/index.module.scss create mode 100644 src/components/GithubConnect/index.tsx create mode 100644 src/pages/GithubLogin/index.module.scss create mode 100644 src/pages/GithubLogin/index.tsx create mode 100644 src/pages/GpuCredit/index.module.scss create mode 100644 src/pages/GpuCredit/index.tsx create mode 100644 src/reducer/auth.ts create mode 100644 src/utils/githubCode.ts diff --git a/.env.example b/.env.example index 5b42f8092..a0b44f771 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,7 @@ REACT_APP_BASE_API_URL=https://api.oraidex.io REACT_APP_KADO_API_KEY=df0d2b3f-d829-4453-a4f6-1d6e8870e8f4 REACT_APP_MIX_PANEL_ENVIRONMENT=acbafd21a85654933cbb0332c5a6f4f8 -REACT_APP_STRAPI_BASE_URL=https://nice-fireworks-d26703b63e.strapiapp.com \ No newline at end of file +REACT_APP_STRAPI_BASE_URL=https://nice-fireworks-d26703b63e.strapiapp.com + +REACT_APP_GITHUB_CLIENT_ID=Ov23liRkvPuKiJCYPmXi +REACT_APP_BASE_GPU_API_URL=https://api-gpu-hub.orai.io diff --git a/package.json b/package.json index 88e649c6c..b7e0ab65f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@sentry/react": "^7.47.0", "@tanstack/react-query": "^4.32.6", "@tharsis/proto": "^0.1.17", - "@tippyjs/react": "^4.2.0", + "@tippyjs/react": "^4.2.6", "@walletconnect/browser-utils": "^1.8.0", "@walletconnect/ethereum-provider": "^1.7.8", "axios": "^0.26.1", @@ -33,7 +33,9 @@ "big-integer": "^1.6.52", "bitcoin-units": "^1.0.0", "chain-registry": "^1.63.86", + "chart.js": "^4.4.4", "classnames": "^2.2.6", + "dotenv": "^16.4.5", "ethers": "^5.0.15", "idb-keyval": "^6.2.1", "lightweight-charts": "^4.1.3", @@ -43,6 +45,7 @@ "qr-code-styling": "1.6.0-rc.1", "qrcode": "^1.5.3", "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.1.1", "react-modal": "^3.16.1", diff --git a/src/assets/icons/github.svg b/src/assets/icons/github.svg new file mode 100644 index 000000000..b85c07f00 --- /dev/null +++ b/src/assets/icons/github.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/gpu_credit.svg b/src/assets/icons/gpu_credit.svg new file mode 100644 index 000000000..d90720dae --- /dev/null +++ b/src/assets/icons/gpu_credit.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/gpu_staking.svg b/src/assets/icons/gpu_staking.svg index d90720dae..26f7959c2 100644 --- a/src/assets/icons/gpu_staking.svg +++ b/src/assets/icons/gpu_staking.svg @@ -1,10 +1,5 @@ - - - - - - - - - + + + + diff --git a/src/assets/icons/key.svg b/src/assets/icons/key.svg new file mode 100644 index 000000000..41d456774 --- /dev/null +++ b/src/assets/icons/key.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/logout-git.svg b/src/assets/icons/logout-git.svg new file mode 100644 index 000000000..5f5e2b10e --- /dev/null +++ b/src/assets/icons/logout-git.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/nav-arrow-down.svg b/src/assets/icons/nav-arrow-down.svg new file mode 100644 index 000000000..8f923a3d8 --- /dev/null +++ b/src/assets/icons/nav-arrow-down.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/images/bg-gpu-credit-balance.png b/src/assets/images/bg-gpu-credit-balance.png new file mode 100644 index 0000000000000000000000000000000000000000..1f7ad1a0c9486301986277d6b3db25a22eb08315 GIT binary patch literal 86868 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 hG|kie^KbJ??| + + + diff --git a/src/assets/images/jupyterhub.png b/src/assets/images/jupyterhub.png new file mode 100644 index 0000000000000000000000000000000000000000..9238ebee853eee99f0cc7223ea8154d9054c621d GIT binary patch literal 2486 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 AHUIzs literal 0 HcmV?d00001 diff --git a/src/assets/images/no-credit-usage-history.svg b/src/assets/images/no-credit-usage-history.svg new file mode 100644 index 000000000..f241f00ed --- /dev/null +++ b/src/assets/images/no-credit-usage-history.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/components/Button/Button.module.scss b/src/components/Button/Button.module.scss index 81b5171de..b77dfe1b6 100644 --- a/src/components/Button/Button.module.scss +++ b/src/components/Button/Button.module.scss @@ -147,3 +147,21 @@ padding: 4px 16px; border-radius: 8px; } + +.fourth { + padding: var(--dimension-padding-btn-y-padding-l, 16px) var(--dimension-padding-btn-x-padding-m, 12px); + color: var(--Colors-Primary-Text-action, #b999f3); + text-align: center; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; /* 142.857% */ + border: 1px solid transparent; + border-radius: var(--Dimension-Corner-Radius-button, 8px); + + &:hover { + opacity: 1; + border: 1px solid var(--Colors-Neutral-Border-default, #383b40); + background: var(--Colors-Neutral-Surface-hover, #47474b); + } +} diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 85843c182..a51838670 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -14,10 +14,11 @@ type ButtonType = | 'third' | 'third-sm' | 'error' - | 'error-sm'; + | 'error-sm' + | 'fourth'; interface Props { type: ButtonType; - onClick: (event: React.MouseEvent) => void; + onClick?: (event: React.MouseEvent) => void; children: React.ReactElement | React.ReactNode; disabled?: boolean; icon?: React.ReactElement | React.ReactNode; diff --git a/src/components/GithubConnect/helper.ts b/src/components/GithubConnect/helper.ts new file mode 100644 index 000000000..e179babe9 --- /dev/null +++ b/src/components/GithubConnect/helper.ts @@ -0,0 +1,11 @@ +import crypto from 'crypto'; +import { setLatestCsrf } from 'utils/githubCode'; + +export const handleConnectGithub = () => { + const csrf = crypto.randomBytes(16).toString('hex'); + setLatestCsrf(csrf); + + window.location.assign( + `https://github.com/login/oauth/authorize?client_id=${process.env.REACT_APP_GITHUB_CLIENT_ID}&state=${csrf}` + ); +}; diff --git a/src/components/GithubConnect/index.module.scss b/src/components/GithubConnect/index.module.scss new file mode 100644 index 000000000..f09f043cc --- /dev/null +++ b/src/components/GithubConnect/index.module.scss @@ -0,0 +1,101 @@ +@import 'src/styles/mixins'; +@import 'src/styles/themes'; + +.wrapper { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + border-right: 1px solid var(--Colors-Neutral-Border-light, #242627); +} + +.connected-btn { + margin-right: 8px; +} + +.connected-area { + padding: 6px var(--Dimension-Spacing-input-x-spacing, 16px); + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + border-left: 1px solid var(--Colors-Neutral-Border-light, #242627); + cursor: pointer; + + &:hover { + opacity: 0.8; + } +} + +.connected-img { + width: 36px; + height: 36px; + border-radius: var(--Dimension-Corner-Radius-badge, 99px); + border: 1px solid var(--Colors-Neutral-Border-default, #383b40); +} + +.connected-content { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.connected-info { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + gap: 2px; + + text-align: center; + font-size: 14px; + font-style: normal; + line-height: 150%; /* 21px */ + + .connected-info--name { + color: var(--Colors-Neutral-Text-title, #efefef); + font-weight: 400; + } + + .connected-info--credit { + color: var(--Colors-Neutral-Text-text-token-name, #f7f7f7); + font-weight: 600; + } +} + +.connected-modal { + width: 180px; + display: flex; + flex-direction: column; + padding: 8px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + border-radius: 8px; + border: 1px solid var(--Colors-Neutral-Border-default, #383b40); + background-color: var(--Colors-Neutral-Surface-card, #18181a); +} + +.connected-modal-option { + display: flex; + height: var(--Dimensions-40, 40px); + padding: 12px 8px; + align-items: center; + justify-content: space-between; + gap: 12px; + align-self: stretch; + cursor: pointer; + + &:hover { + opacity: 0.8; + } +} + +.modal-option-name { + color: var(--Colors-Neutral-Text-title, #f7f7f7); + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 120%; /* 19.2px */ +} diff --git a/src/components/GithubConnect/index.tsx b/src/components/GithubConnect/index.tsx new file mode 100644 index 000000000..93660105a --- /dev/null +++ b/src/components/GithubConnect/index.tsx @@ -0,0 +1,114 @@ +import React, { useEffect } from 'react'; +import classNames from 'classnames/bind'; +import HeadlessTippy from '@tippyjs/react/headless'; +import { useDispatch, useSelector } from 'react-redux'; +import { toast } from 'react-toastify'; + +import { Button } from 'components/Button'; +import { RootState } from 'store/configure'; +import { setCredit, reset } from 'reducer/auth'; +import { axiosAuth as axios } from 'rest/request'; +import { ReactComponent as GitHubIcon } from 'assets/icons/github.svg'; +import ConnectedImg from 'assets/images/connected-img.png'; +import DropdownIcon from 'assets/icons/nav-arrow-down.svg'; +import LogoutIcon from 'assets/icons/logout-git.svg'; +import { handleConnectGithub } from './helper'; +import styles from './index.module.scss'; +import 'tippy.js/dist/tippy.css'; // optional for styling + +const cx = classNames.bind(styles); + +const baseApiUrl = process.env.REACT_APP_BASE_GPU_API_URL; +export const GithubConnect: React.FC = () => { + const dispatch = useDispatch(); + const accountName = useSelector((state: RootState) => state.auth.accountName); + const credit = useSelector((state: RootState) => state.auth.credit); + const { access: accessToken } = useSelector((state: RootState) => state.auth.token); + + useEffect(() => { + const getCreditData = async () => { + let resp; + try { + resp = await axios.get(`${baseApiUrl}/credit-remain`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }); + } catch (e) { + console.error('Credit remain:', e); + + toast.error('Failed to query credit balance'); + } + resp && dispatch(setCredit(resp.data.creditRemain)); + }; + accessToken && getCreditData(); + }, [accessToken]); + + return ( +

+
+ +
+ + {accountName ? ( + { + const options: { name: string; icon?: string; onCLick?: React.MouseEventHandler }[] = [ + { + name: 'Manage your credits' + }, + { + name: 'Log out', + icon: LogoutIcon, + onCLick: () => { + // remove token + dispatch(reset()); + } + } + ]; + return ( +
+ {options.map((option, index) => ( +
+

{option.name}

+ {option.icon && {`${option.name}} +
+ ))} +
+ ); + }} + > +
+
+ Connected Img +
+ +
+
+

{accountName}

+

{credit} credits

+
+ + dropdown icon +
+
+
+ ) : ( +
+ +
+ )} +
+ ); +}; diff --git a/src/components/Table/Table.module.scss b/src/components/Table/Table.module.scss index 3778ef1c4..21888fbff 100644 --- a/src/components/Table/Table.module.scss +++ b/src/components/Table/Table.module.scss @@ -120,5 +120,9 @@ padding-right: 10px; } } + &.no-data { + display: flex; + justify-content: center; + } } } diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index bc9d93549..a0222b590 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,9 +1,12 @@ +import cn from 'classnames/bind'; import { ReactComponent as SortDownIcon } from 'assets/icons/down_icon.svg'; import { ReactComponent as SortUpIcon } from 'assets/icons/up_icon.svg'; -import { compareNumber } from 'helper'; +import { compareNumber, divNumber } from 'helper'; import { ReactNode, useState } from 'react'; import styles from './Table.module.scss'; +const cx = cn.bind(styles); + export type HeaderDataType = { name: string; accessor: (data: T) => ReactNode | string | undefined; @@ -20,6 +23,7 @@ export type TableProps = { data: T[]; stylesColumn?: React.CSSProperties; handleClickRow?: (event: React.MouseEvent, record: T) => void; + noData?: ReactNode; }; export enum SortType { @@ -112,7 +116,8 @@ export const Table = ({ headers, data, handleClickRow, - stylesColumn + stylesColumn, + noData }: TableProps) => { const [sort, setSort] = useState>({ [defaultSorted]: SortType.DESC @@ -137,6 +142,7 @@ export const Table = ({ setSort(newSort); sortDataSource(data, newSort); }; + const isNoData = !data.length && noData; return ( @@ -164,21 +170,27 @@ export const Table = ({ })} - - {sortDataSource(data, sort).map((datum, index) => { - return ( - handleClickRow && handleClickRow(event, datum)}> - {Object.keys(headers).map((key, index) => { - const customStyle = getCustomStyleByColumnKey(headers, key); - return ( - - ); - })} - - ); - })} + + {isNoData + ? noData + : sortDataSource(data, sort).map((datum, index) => { + return ( + handleClickRow && handleClickRow(event, datum)} + > + {Object.keys(headers).map((key, index) => { + const customStyle = getCustomStyleByColumnKey(headers, key); + return ( + + ); + })} + + ); + })}
- {headers[key].accessor(datum)} -
+ {headers[key].accessor(datum)} +
); diff --git a/src/layouts/Menu.module.scss b/src/layouts/Menu.module.scss index 3a8cb16d1..2a90fd2d6 100644 --- a/src/layouts/Menu.module.scss +++ b/src/layouts/Menu.module.scss @@ -3,7 +3,7 @@ .menu { display: flex; - justify-content: space-between; + // justify-content: center; position: fixed; width: 100%; top: 0; @@ -168,6 +168,30 @@ } } +.wrapMenuRight { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; +} + +.menuMiddle { + display: flex; + align-items: center; + justify-content: center; + gap: var(--dimension-spacing-col-between-md, 8px); + padding: 16px; + + .menuMiddleText { + color: var(--colors-neutral-text-body, #b4b7bb); + font-family: 'IBM Plex Sans'; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; /* 142.857% */ + } +} + .menuLeft { display: flex; align-items: center; @@ -195,7 +219,7 @@ .menuRight { display: flex; align-items: center; - gap: 16px; + gap: 8px; font-weight: 500; padding-right: 20px; diff --git a/src/layouts/Menu.tsx b/src/layouts/Menu.tsx index adf1a2ff3..a6b19f9db 100644 --- a/src/layouts/Menu.tsx +++ b/src/layouts/Menu.tsx @@ -11,6 +11,8 @@ import React, { ReactNode, useContext, useEffect, useRef, useState } from 'react import { Link, useLocation } from 'react-router-dom'; import styles from './Menu.module.scss'; import Sidebar from './Sidebar'; +import TopBarIcon from 'assets/images/flicker-dot.svg'; +import { GithubConnect } from 'components/GithubConnect'; const Menu: React.FC = () => { const location = useLocation(); @@ -118,11 +120,24 @@ const Menu: React.FC = () => { -
-
- - - + +
+
+ top_bar_icon + +
+ Millions of EVM wallet users will soon be able to join the Oraichain ecosystem with ease! +
+
+ +
+ + +
+ + + +
diff --git a/src/layouts/Sidebar.tsx b/src/layouts/Sidebar.tsx index 2c20fb2c4..fd28b7272 100644 --- a/src/layouts/Sidebar.tsx +++ b/src/layouts/Sidebar.tsx @@ -2,6 +2,7 @@ import { ReactComponent as BuyCryptoIcon } from 'assets/icons/buy_crypto.svg'; import { ReactComponent as CoHavestIcon } from 'assets/icons/co_harvest.svg'; import { ReactComponent as GovernanceIcon } from 'assets/icons/governance.svg'; import { ReactComponent as GpuStakingIcon } from 'assets/icons/gpu_staking.svg'; +import { ReactComponent as GpuCreditIcon } from 'assets/icons/gpu_credit.svg'; import { ReactComponent as HomeBaseIcon } from 'assets/icons/homebase.svg'; import { ReactComponent as GitIcon } from 'assets/icons/ic_github.svg'; import { ReactComponent as DiscordIcon } from 'assets/icons/ic_discord.svg'; @@ -103,6 +104,7 @@ const Sidebar: React.FC<{}> = React.memo((props) => {
{renderLink('/homebase', 'Homebase', setLink, )} {renderLink('/gpu-staking', 'GPU Staking', setLink, )} + {renderLink('/gpu-credit', 'GPU Credit', setLink, )} {renderLink( 'https://scan.orai.io/validators', 'ORAI Staking', diff --git a/src/pages/GithubLogin/index.module.scss b/src/pages/GithubLogin/index.module.scss new file mode 100644 index 000000000..336bdb0c3 --- /dev/null +++ b/src/pages/GithubLogin/index.module.scss @@ -0,0 +1,54 @@ +.wrapper { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 20px; + margin-top: 100px; +} + +.redirect { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + + .desc { + text-align: center; + font-size: 30px; + } +} + +.loader-wrap { + height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 6px 0; + + .loader { + width: 30px; + aspect-ratio: 2; + --_g: no-repeat radial-gradient(circle closest-side, #a19d9d 90%, #6b696900); + background: var(--_g) 0% 50%, var(--_g) 50% 50%, var(--_g) 100% 50%; + background-size: calc(100% / 3) 50%; + animation: l3 1s infinite linear; + } + @keyframes l3 { + 20% { + background-position: 0% 0%, 50% 50%, 100% 50%; + } + 40% { + background-position: 0% 100%, 50% 0%, 100% 50%; + } + 60% { + background-position: 0% 50%, 50% 100%, 100% 0%; + } + 80% { + background-position: 0% 50%, 50% 50%, 100% 100%; + } + } +} diff --git a/src/pages/GithubLogin/index.tsx b/src/pages/GithubLogin/index.tsx new file mode 100644 index 000000000..e12a5eed9 --- /dev/null +++ b/src/pages/GithubLogin/index.tsx @@ -0,0 +1,64 @@ +import React, { useEffect } from 'react'; +import classNames from 'classnames/bind'; +import { useDispatch } from 'react-redux'; +import { toast } from 'react-toastify'; +import { useLocation } from 'react-router-dom'; + +import axios from 'rest/request'; +import { setAccountName, setCredit, setTokens } from 'reducer/auth'; +import { getLatestCsrf } from 'utils/githubCode'; +import styles from './index.module.scss'; + +const cx = classNames.bind(styles); + +const GithubLogin: React.FC = () => { + const dispatch = useDispatch(); + const { search } = useLocation(); + + const urlParams = new URLSearchParams(search); + const code = urlParams.get('code'); + const latestCsrf = urlParams.get('state'); + + useEffect(() => { + const login = async () => { + const resp = await axios.post(`${process.env.REACT_APP_BASE_GPU_API_URL}/github-auth`, { code }); + + const { accessToken, refreshToken, creditRemain, username } = resp.data; + + dispatch(setTokens({ access: accessToken, refresh: refreshToken })); + dispatch(setCredit(creditRemain)); + dispatch(setAccountName(username)); + }; + + if (code && latestCsrf && latestCsrf === getLatestCsrf()) { + // TODO: refactor this for better UX + login().then(() => { + toast.success('Login success'); + setTimeout(() => { + window.history.back(); + }, 3); + }).catch(() => { + toast.error('Login failed'); + setTimeout(() => { + window.location.assign('/'); + }, 5); + }); + } else { + // TODO: print error message + console.log('not login'); + } + }, [code, latestCsrf]); + + return ( +
+
+
Logging in by Github
+
+
+
+
+
+ ); +}; + +export default GithubLogin; diff --git a/src/pages/GpuCredit/index.module.scss b/src/pages/GpuCredit/index.module.scss new file mode 100644 index 000000000..ebb3c7b24 --- /dev/null +++ b/src/pages/GpuCredit/index.module.scss @@ -0,0 +1,282 @@ +@import 'src/styles/mixins'; +@import 'src/styles/themes'; + +.container { + display: inline-flex; + // padding: 32px 0px; + flex-direction: column; + align-items: flex-start; + gap: 56px; + + .title { + color: var(--Colors-Neutral-Text-heading, #f7f7f7); + font-size: 24px; + font-weight: bold; + line-height: 28px; + } + + a.external { + color: var(--Colors-Primary-Text-action, #b999f3); + font-family: 'IBM Plex Sans'; + font-size: 16px; + font-weight: 500; + line-height: 20px; /* 125% */ + + @include mobile { + display: none; + } + + svg { + path { + fill: #b999f3; + } + + vertical-align: sub; + width: 20px; + height: 20px; + } + } + + .statistics { + display: flex; + gap: var(--Dimensions-40, 40px); + + align-self: stretch; + align-items: stretch; + + & > * { + flex: 1; + + display: flex; + flex-direction: column; + gap: 16px; + } + + .daily-credit-usage { + .chart { + padding-top: 20px; + + canvas { + max-height: 250px; + } + } + } + + .gpu-statistics { + .content { + flex-grow: 1; + + .basic-info { + // width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + + & > * { + flex: 1; + } + + .header { + color: var(--Colors-Neutral-Text-placeholder, #83838a); + } + .value { + font-size: 1.5em; + } + } + + .gpu-detail { + display: flex; + flex-direction: column; + gap: 24px; + + & > * { + flex: 1; + } + + .gpu { + display: flex; + flex-direction: column; + gap: 12px; + + .usage { + display: flex; + justify-content: space-between; + + .text { + color: var(--Colors-Neutral-Text-placeholder, #83838a); + } + } + .progress { + height: var(--Dimensions-16, 16px); + border: var(--Colors-Neutral-Border-default, #383b40) 1px solid; + + .percent-value { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + border: var(--Colors-Neutral-Border-progress-bar, #83838a) 1px solid; + background-color: var(--Colors-Neutral-Surface-progess-bar, rgba(131, 131, 138, 0.5)); + } + } + } + .link { + line-height: 32px; + } + } + } + } + } + + .personal-info { + padding: 32px 24px 32px 24px; + border-radius: var(--Dimension-Corner-Radius-row, 8px); + background: linear-gradient(180deg, #1f1f20 0%, #141416 321px); + + display: flex; + flex-direction: column; + gap: 24px; + + .intro { + display: flex; + gap: 32px; + + & > .text { + width: 60%; + display: flex; + flex-direction: column; + gap: 32px; + + .content { + display: flex; + flex-direction: column; + gap: 24px; + + p { + color: var(--Colors-Neutral-Text-placeholder, #83838a); + } + + .link { + line-height: 32px; + } + } + } + .interaction { + flex-grow: 1; + display: flex; + flex-direction: column; + gap: 16px; + + .credit-balance { + background-image: url('../../assets/images/bg-gpu-credit-balance.png'); + background-repeat: no-repeat; + background-size: cover; + border-radius: 8px; + border: 1px solid var(--Colors-Neutral-Border-default, #383b40); + flex-grow: 1; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 24px; + + .info { + display: flex; + flex-direction: column; + align-items: center; + + .text { + font-size: 16px; + line-height: 24px; + } + .value { + font-size: 32px; + line-height: 130%; + color: var(--Colors-Neutral-Text-heading, #f7f7f7); + } + } + .list-buttons { + display: flex; + gap: 16px; + + button { + padding: 14px 24px; + + &:disabled { + opacity: 1; + color: var(--Colors-Neutral-Text-disable, #47474b); + + display: flex; + justify-content: center; + + svg { + path { + fill: var(--Colors-Neutral-Text-disable, #47474b); + } + + width: 20px; + height: 20px; + } + } + } + } + } + + .go-to-panel { + display: flex; + justify-content: space-between; + gap: 16px; + + a { + flex: 1; + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 12px; + cursor: pointer; + border-radius: var(--Dimension-Corner-Radius-check-box, 4px); + border: 1px solid var(--Colors-Neutral-Border-light, #242627); + // width: 45%; + } + } + } + } + .credit-usage-history { + display: flex; + flex-direction: column; + gap: 16px; + + .title { + line-height: 24px; + } + .table { + border-radius: var(--Dimension-Corner-Radius-row, 8px); + border: 1px solid var(--Colors-Neutral-Border-default, #383b40); + padding-bottom: 24px; + + th { + color: var(--Colors-Neutral-Text-placeholder, #83838a); + font-family: 'IBM Plex Sans'; + font-size: 12px; + font-weight: 400; + line-height: 150%; /* 18px */ + letter-spacing: 0.012px; + } + + .no-data { + height: 222px; + border-bottom: none; + + td { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + } + } + } + } +} diff --git a/src/pages/GpuCredit/index.tsx b/src/pages/GpuCredit/index.tsx new file mode 100644 index 000000000..edaa43f50 --- /dev/null +++ b/src/pages/GpuCredit/index.tsx @@ -0,0 +1,362 @@ +import { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { toast } from 'react-toastify'; +import cn from 'classnames/bind'; +import { Bar } from 'react-chartjs-2'; +import { CategoryScale, BarElement } from 'chart.js'; +import Chart from 'chart.js/auto'; + +import Content from 'layouts/Content'; +import { ReactComponent as JumpIcon } from 'assets/icons/jump.svg'; +import { ReactComponent as GitHubIcon } from 'assets/icons/github.svg'; +import { ReactComponent as NoCreditUsageHistoryIcon } from 'assets/images/no-credit-usage-history.svg'; +import { ReactComponent as AddIcon } from 'assets/icons/Add.svg'; +import { ReactComponent as TimeIcon } from 'assets/icons/time.svg'; +import { ReactComponent as KeyIcon } from 'assets/icons/key.svg'; +import JupyterHubImg from 'assets/images/jupyterhub.png'; +import { Table, TableHeaderProps } from 'components/Table'; +import { Button } from 'components/Button'; +import { handleConnectGithub } from 'components/GithubConnect/helper'; +import { RootState } from 'store/configure'; +import axios, { axiosAuth } from 'rest/request'; +import styles from './index.module.scss'; + +const cx = cn.bind(styles); +Chart.register(CategoryScale, BarElement); +const baseApiUrl = process.env.REACT_APP_BASE_GPU_API_URL; + +const GpuCredit: React.FC<{}> = () => { + const [gpuStatistics, setGpuStatistics] = useState({ + totalCards: 12, + totalVRAM: 295, + totalUsage: 0 + }); + const [gpuStatus, setGpuStatus] = useState([]); + const [creditUsageHistoryData, setCreditUsageHistoryData] = useState([]); + const [dailyCreditUsage, setDailyCreditUsage] = useState([]); + + const tokens = useSelector((state: RootState) => state.auth.token); + const credit = useSelector((state: RootState) => state.auth.credit); + const loggedIn = !!tokens.access; + + const [chartData, setChartData] = useState({ + labels: dailyCreditUsage.map((data) => new Date(data.date).getDate()), + datasets: [ + { + // label: undefined, + data: dailyCreditUsage.map((data) => data.credit), + backgroundColor: ['#7332E7'], + borderColor: '#B999F3', + borderWidth: 2, + borderRadius: 4, + borderSkipped: false, + barThickness: 20 + } + ] + }); + + useEffect(() => { + if (loggedIn) { + const getData = async () => { + let promises; + + try { + promises = await Promise.all([ + axiosAuth.get(`${baseApiUrl}/credit-usage-history?filter=negative`, { + headers: { Authorization: `Bearer ${tokens.access}` } + }), + axiosAuth.get(`${baseApiUrl}/credit-usage-per-day`, { + headers: { Authorization: `Bearer ${tokens.access}` } + }) + ]); + } catch (e) { + console.error('Credit usage history:', e); + + toast.error('Failed to qery credit usage'); + } + + // TODO: refactor this, promises may get [undefined, undefined] due to interceptors + if (promises && promises[0] && promises[1]) { + const creditUsageHistory = promises[0].data.creditUsageHistory; + const totalCreditUsageEachDay = promises[1].data.totalCreditUsageEachDay; + + setCreditUsageHistoryData(creditUsageHistory); + setDailyCreditUsage(totalCreditUsageEachDay); + } + }; + getData(); + } else { + axios + .get(`${baseApiUrl}/credit-usage-per-day-of-server`) + .then(({ data }) => { + setDailyCreditUsage(data.totalCreditUsageEachDayByServer); + }) + .catch((e) => { + console.error('Credit usage per day:', e); + + // TODO: handle error + toast.error('Failed to fetch daily credit usage'); + }); + } + + axios + .get(`${baseApiUrl}/gpu-statistics`) + .then(({ data }) => { + const gpuStatisticsData = { + totalCards: data.numberOfCards, + totalVRAM: Math.round(data.totalVRAM), + totalUsage: data.totalUsage.toFixed(2).replace(/\.0+$/, '') + }; + setGpuStatistics(gpuStatisticsData); + + // TODO: set interval + // TODO: set real data + const gpuStatusData = data.hosts + .sort((host1, host2) => host2.vramUsage - host1.vramUsage) + .slice(0, 2) + .map((host) => ({ + name: `${host.name} ${host.gpuNumber}x ${host.gpuName}`, + capacity: Math.floor(host.totalVRAM), + currentUsage: Math.floor(host.vramUsage) + })); + setGpuStatus(gpuStatusData); + }) + .catch((e) => { + console.error('gpu-statistics:', e); + + // TODO: handle error + toast.error('Failed to fetch gpu statistics'); + }); + }, [tokens]); + + useEffect(() => { + setChartData({ + labels: dailyCreditUsage.map((data) => new Date(data.date).getDate()), + datasets: [ + { + // label: undefined, + data: dailyCreditUsage.map((data) => data.credit), + backgroundColor: ['#7332E7'], + borderColor: '#B999F3', + borderWidth: 2, + borderRadius: 4, + borderSkipped: false, + barThickness: 20 + } + ] + }); + }, [dailyCreditUsage]); + + const gpuStatusElements = gpuStatus.map((detail, idx) => { + const percentUsage = Math.floor((detail.currentUsage / detail.capacity) * 100); + return ( +
+
+
{detail.name} Usage:
+
+ {Math.floor(detail.currentUsage)}/{detail.capacity} GB +
+
+
+
+ {percentUsage}% +
+
+
+ ); + }); + + const creditUsageHistoryHeaders: TableHeaderProps = { + timestamp: { + name: 'TIMESTAMP', + accessor: (data) => new Date(data.timestamp).toISOString().replace(/T.+$/, ''), + width: '30%', + align: 'left', + padding: `0px 0px 0px 24px` + }, + action: { + name: 'ACTION', + accessor: (data) => data.action, + width: '40%', + align: 'left' + }, + creditUsage: { + name: 'CREDIT USAGE', + accessor: (data) => data.credit, + width: '30%', + align: 'left' + } + }; + + return ( + +
+
+
+

Total Credit Usage Each Day

+
+ +
+
+
+
+
+
+
+

Decentralized GPU Infra

+
+

+ Decentralized GPU infra is crucial for the advancement of AI x Blockchain. DApps builders that are + eager to scale AI in Blockchain environment can apply for GPU Credits offered by Oraichain Labs and + expand their project capabilities. +
+ GPU Credits Offering supercharges AI businesses and empowers them to thrive on blockchain environment. + Decentralized GPU infrastructure is crucial for the advancement of AI x Blockchain. +
+ With Decentralized GPU Infra, projects can:
+ - Optimize cost +
- Reduce common infrastructure risks of relying on a single provider. +

+ + Learn more  {} + +
+
+
+
+
+
Your Credits
+
{tokens.access ? credit : 0}
+
+
+ {loggedIn ? ( + <> + + + + ) : ( + + )} +
+
+ +
+
+
+

Credit Usage History

+
+ + + + } + /> + + + + + + ); +}; + +export default GpuCredit; diff --git a/src/reducer/auth.ts b/src/reducer/auth.ts new file mode 100644 index 000000000..5baddaabb --- /dev/null +++ b/src/reducer/auth.ts @@ -0,0 +1,40 @@ +import type { PayloadAction } from '@reduxjs/toolkit'; +import { createSlice } from '@reduxjs/toolkit'; +import { AuthState } from './type'; + +const initialState: AuthState = { + token: { + access: '', + refresh: '' + }, + accountName: '', + credit: 0 +}; + +const authSlice = createSlice({ + name: 'auth', + initialState, + reducers: { + setTokens: (state, action: PayloadAction) => { + state.token = action.payload; + }, + setAccountName: (state, action: PayloadAction) => { + state.accountName = action.payload; + }, + setCredit: (state, action: PayloadAction) => { + state.credit = action.payload; + }, + reset: (state) => { + state.token = { + access: '', + refresh: '' + }; + state.accountName = ''; + state.credit = 0; + } + } +}); + +export const { setTokens, setAccountName, setCredit, reset } = authSlice.actions; + +export default authSlice.reducer; diff --git a/src/reducer/type.ts b/src/reducer/type.ts index 8d9f13ecc..7166f064f 100644 --- a/src/reducer/type.ts +++ b/src/reducer/type.ts @@ -196,6 +196,15 @@ export interface OrderResponseContract { orders: OrderDetailFromContract[]; } +export interface AuthState { + token: { + access: string; + refresh: string; + }; + accountName: string; + credit: number; +} + export enum OrderStatus { OPEN = 'OPEN', FUL_FILLED = 'FUL_FILLED', diff --git a/src/rest/request.ts b/src/rest/request.ts index 10708ca06..ccb5140d7 100644 --- a/src/rest/request.ts +++ b/src/rest/request.ts @@ -1,8 +1,10 @@ import Axios from 'axios'; +import { store } from 'store/configure'; +import { setTokens, reset } from 'reducer/auth'; import { throttleAdapterEnhancer, retryAdapterEnhancer } from 'axios-extensions'; import { AXIOS_TIMEOUT, AXIOS_THROTTLE_THRESHOLD } from '@oraichain/oraidex-common'; -const axios = Axios.create({ +export default Axios.create({ timeout: AXIOS_TIMEOUT, retryTimes: 3, // cache will be enabled by default in 2 seconds @@ -14,4 +16,48 @@ const axios = Axios.create({ baseURL: process.env.REACT_APP_BASE_API_URL }); -export default axios; +export const axiosAuth = Axios.create({ + timeout: AXIOS_TIMEOUT, + adapter: retryAdapterEnhancer( + throttleAdapterEnhancer(Axios.defaults.adapter!, { + threshold: AXIOS_THROTTLE_THRESHOLD + }) + ), + baseURL: process.env.REACT_APP_BASE_GPU_API_URL +}); + +let refreshTokenPromise; + +const getRefreshToken = () => { + return Axios.post(`${process.env.REACT_APP_BASE_GPU_API_URL}/refresh-token`, { + refreshToken: store.getState().auth.token.refresh + }); +}; + +axiosAuth.interceptors.response.use( + (res) => res, + (error) => { + if (error.response?.status === 401) { + if (!refreshTokenPromise) { + // check for an existing in-progress request + // if nothing is in-progress, start a new refresh token request + refreshTokenPromise = getRefreshToken().then((resp) => { + refreshTokenPromise = null; // clear state + return resp.data; // resolve with the new token + }); + } + return refreshTokenPromise + .then((tokens) => { + const newTokens = { + access: tokens.accessToken, + refresh: tokens.refreshToken + }; + store.dispatch(setTokens(newTokens)); + }) + .catch(() => { + store.dispatch(reset()); + }); + } + return Promise.reject(error); + } +); diff --git a/src/routes.tsx b/src/routes.tsx index 1dae340b4..a6cc6d435 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -3,9 +3,10 @@ import Loader from 'components/Loader'; import NotFound from 'pages/NotFound'; import { Suspense } from 'react'; import { Route, Routes } from 'react-router-dom'; - +import GpuCredit from 'pages/GpuCredit'; import GpuStaking from 'pages/GpuStaking'; import UniversalSwap from 'pages/UniversalSwap/index'; +import GithubLogin from 'pages/GithubLogin'; export default () => ( ( } /> } /> } /> + } /> + } /> } /> diff --git a/src/store/configure.ts b/src/store/configure.ts index 824ea36b8..963f2fdb7 100644 --- a/src/store/configure.ts +++ b/src/store/configure.ts @@ -6,6 +6,7 @@ import tradingReducer from '../reducer/tradingSlice'; import walletReducer from '../reducer/wallet'; import poolChartReducer from '../reducer/poolChartSlice'; import AddressBookReducer from '../reducer/addressBook'; +import AuthReducer from '../reducer/auth'; import storage from 'redux-persist/lib/storage'; import { persistReducer, persistStore } from 'redux-persist'; import { PERSIST_CONFIG_KEY } from './constants'; @@ -22,7 +23,8 @@ const rootReducer = combineReducers({ trading: tradingReducer, wallet: walletReducer, poolChart: poolChartReducer, - addressBook: AddressBookReducer + addressBook: AddressBookReducer, + auth: AuthReducer }); const persistedReducer = persistReducer(rootPersistConfig, rootReducer); diff --git a/src/utils/githubCode.ts b/src/utils/githubCode.ts new file mode 100644 index 000000000..4aaae771d --- /dev/null +++ b/src/utils/githubCode.ts @@ -0,0 +1,13 @@ +const LATEST_CSRF_TOKEN = 'latest_csrf_token'; + +export const setLatestCsrf = (csrf: string) => { + // if (localStorage.getItem(LATEST_CSRF_TOKEN)) { + // return; + // } + // console.log('SET NEW CSRF', csrf); + localStorage.setItem(LATEST_CSRF_TOKEN, csrf); +}; + +export const getLatestCsrf = () => { + return localStorage.getItem(LATEST_CSRF_TOKEN); +}; diff --git a/tsconfig.json b/tsconfig.json index dc13a8ee9..47843fcab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,4 +30,4 @@ "exclude": [ "node_modules", ] -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 317dd8837..c9aca70cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2757,6 +2757,11 @@ dependencies: hash-sum "^2.0.0" +"@kurkle/color@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f" + integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw== + "@leapwallet/cosmos-snap-provider@0.1.25": version "0.1.25" resolved "https://registry.yarnpkg.com/@leapwallet/cosmos-snap-provider/-/cosmos-snap-provider-0.1.25.tgz#f256cd4c7ef89aa9209ed8dbaf16487db24bde10" @@ -3730,7 +3735,7 @@ sha3 "^2.1.4" shx "^0.3.4" -"@tippyjs/react@^4.2.0": +"@tippyjs/react@^4.2.6": version "4.2.6" resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.6.tgz#971677a599bf663f20bb1c60a62b9555b749cc71" integrity sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw== @@ -6169,6 +6174,13 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +chart.js@^4.4.4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.4.tgz#b682d2e7249f7a0cbb1b1d31c840266ae9db64b7" + integrity sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA== + dependencies: + "@kurkle/color" "^0.3.0" + check-types@^11.2.3: version "11.2.3" resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.2.3.tgz#1ffdf68faae4e941fce252840b1787b8edc93b71" @@ -7384,6 +7396,11 @@ dotenv@^16.3.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.1.tgz#1d9931f1d3e5d2959350d1250efab299561f7f11" integrity sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ== +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -13792,6 +13809,11 @@ react-app-rewired@^2.2.1: dependencies: semver "^5.6.0" +react-chartjs-2@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz#43c1e3549071c00a1a083ecbd26c1ad34d385f5d" + integrity sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA== + react-dev-utils@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73"
+ + No records found +