From 0ab16f895e01577e3d5b522aaf41fc5f4957b1d0 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 26 Oct 2023 18:32:02 +0100 Subject: [PATCH 1/5] RYSK-497: New ARB icon. --- packages/front-end/src/Icons/ARB.tsx | 39 +++++++++++++++++++++++++++ packages/front-end/src/Icons/index.ts | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 packages/front-end/src/Icons/ARB.tsx diff --git a/packages/front-end/src/Icons/ARB.tsx b/packages/front-end/src/Icons/ARB.tsx new file mode 100644 index 000000000..89fe951ef --- /dev/null +++ b/packages/front-end/src/Icons/ARB.tsx @@ -0,0 +1,39 @@ +import type { SVGProps } from "react"; + +export const ARB = (props: SVGProps) => ( + + + + + + + + + +); diff --git a/packages/front-end/src/Icons/index.ts b/packages/front-end/src/Icons/index.ts index d27448416..22a67eeba 100644 --- a/packages/front-end/src/Icons/index.ts +++ b/packages/front-end/src/Icons/index.ts @@ -1,3 +1,4 @@ +import { ARB } from "./ARB"; import { Change } from "./Change"; import { ChevronUpDown } from "./ChevronUpDown"; import { Close } from "./Close"; @@ -23,6 +24,7 @@ import { UpChevron } from "./UpChevron"; import { WETH } from "./WETH"; export { + ARB, Change, ChevronUpDown, Close, From f89b23d8f8f904faa3f5b737c12767ac0991d3c7 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 26 Oct 2023 18:32:38 +0100 Subject: [PATCH 2/5] RYSK-497: New rewards page. --- .../front-end/src/clients/Apollo/Queries.ts | 1 + .../components/Rewards/components/Active.tsx | 83 +++++++++++++++++++ .../Rewards/components/Footnotes.tsx | 5 ++ .../components/Rewards/components/Header.tsx | 15 ++++ .../components/Rewards/components/Info.tsx | 30 +++++++ .../components/Rewards/components/Table.tsx | 58 +++++++++++++ .../Rewards/hooks/useAirdropData.tsx | 44 ++++++++++ .../src/components/Rewards/index.tsx | 20 +++++ .../front-end/src/components/Rewards/types.ts | 23 +++++ packages/front-end/src/pages/Rewards.tsx | 3 + 10 files changed, 282 insertions(+) create mode 100644 packages/front-end/src/components/Rewards/components/Active.tsx create mode 100644 packages/front-end/src/components/Rewards/components/Footnotes.tsx create mode 100644 packages/front-end/src/components/Rewards/components/Header.tsx create mode 100644 packages/front-end/src/components/Rewards/components/Info.tsx create mode 100644 packages/front-end/src/components/Rewards/components/Table.tsx create mode 100644 packages/front-end/src/components/Rewards/hooks/useAirdropData.tsx create mode 100644 packages/front-end/src/components/Rewards/index.tsx create mode 100644 packages/front-end/src/components/Rewards/types.ts create mode 100644 packages/front-end/src/pages/Rewards.tsx diff --git a/packages/front-end/src/clients/Apollo/Queries.ts b/packages/front-end/src/clients/Apollo/Queries.ts index 90875cb7e..366d73443 100644 --- a/packages/front-end/src/clients/Apollo/Queries.ts +++ b/packages/front-end/src/clients/Apollo/Queries.ts @@ -2,6 +2,7 @@ export enum QueriesEnum { DASHBOARD_USER_POSITIONS = "DASHBOARD_USER_POSITIONS", INITIAL_DATA = "INITIAL_DATA", ORACLE_ASSETS = "ORACLE_ASSETS", + REWARDS = "REWARDS", TRANSACTIONS = "TRANSACTIONS", USER_EPOCH_PNL = "USER_EPOCH_PNL", USER_VAULT = "USER_VAULT", diff --git a/packages/front-end/src/components/Rewards/components/Active.tsx b/packages/front-end/src/components/Rewards/components/Active.tsx new file mode 100644 index 000000000..bd1907258 --- /dev/null +++ b/packages/front-end/src/components/Rewards/components/Active.tsx @@ -0,0 +1,83 @@ +import dayjs from "dayjs"; +import { Link as RouterLink } from "react-router-dom"; + +import { Link } from "src/Icons"; + +const rewardPrograms = [ + { + dates: { + start: dayjs.unix(1698998400), + end: dayjs.unix(1707465600), + }, + info: ( + <> + {`The Arbitrum short term incentive program will provide `} + {`35.6k ARB`} + {` per week, split evenly between liquidity providers and traders. Anyone with a deposit in the DHV when the weekly epoch is executed will be eligible for rewards. Equally, every contract traded during the epoch will be eligible to earn a share of the weekly rewards based on different trading params. To find out more about eligibility and distribution, deposit into the vault, or make a trade, please follow the link below.`} + + ), + links: [ + { + external: true, + href: "https://medium.rysk.finance/arbitrum-stip-rewards-for-rysk-6929609e85d7", + label: "Learn more about the Arbitrum STIP rewards.", + }, + { + external: false, + href: "/vault", + label: "Deposit now to earn rewards.", + }, + { + external: false, + href: "/", + label: "Start trading now.", + }, + ], + title: "Arbitrum STIP", + }, +]; + +export const Active = () => ( +
+

{`Active reward programs`}

+ + {rewardPrograms.map(({ dates, info, title, links }) => ( +
+

+ {title} + + + {` - `} + + +

+ +

{info}

+ + {links.map(({ external, href, label }) => { + return external ? ( + + + {label} + + ) : ( + + + {label} + + ); + })} +
+ ))} +
+); diff --git a/packages/front-end/src/components/Rewards/components/Footnotes.tsx b/packages/front-end/src/components/Rewards/components/Footnotes.tsx new file mode 100644 index 000000000..084b4d036 --- /dev/null +++ b/packages/front-end/src/components/Rewards/components/Footnotes.tsx @@ -0,0 +1,5 @@ +export const Footnotes = () => ( +
+ {`* Calculated as the USD value of the tokens at the time of distribution.`} +
+); diff --git a/packages/front-end/src/components/Rewards/components/Header.tsx b/packages/front-end/src/components/Rewards/components/Header.tsx new file mode 100644 index 000000000..3202c440b --- /dev/null +++ b/packages/front-end/src/components/Rewards/components/Header.tsx @@ -0,0 +1,15 @@ +export const Header = () => ( +
+
+

{`Rysk Rewards`}

+

{`Earn rewards for LPing and Trading on Rysk`}

+
+ + Rysk logo +
+); diff --git a/packages/front-end/src/components/Rewards/components/Info.tsx b/packages/front-end/src/components/Rewards/components/Info.tsx new file mode 100644 index 000000000..1298585f1 --- /dev/null +++ b/packages/front-end/src/components/Rewards/components/Info.tsx @@ -0,0 +1,30 @@ +import type { RecipientsProps } from "../types"; + +import { RyskCountUp } from "src/components/shared/RyskCountUp"; +import { ARB } from "src/Icons"; + +export const Info = ({ recipients, tokens, value }: RecipientsProps) => ( +
+ +

+ +

+

{`Reward recipients`}

+
+ + +

+ + +

+

{`Distributed`}

+
+ + +

+ +

+

{`Total value*`}

+
+
+); diff --git a/packages/front-end/src/components/Rewards/components/Table.tsx b/packages/front-end/src/components/Rewards/components/Table.tsx new file mode 100644 index 000000000..d35cc0abd --- /dev/null +++ b/packages/front-end/src/components/Rewards/components/Table.tsx @@ -0,0 +1,58 @@ +import type { TableProps } from "../types"; + +import { useAccount } from "wagmi"; + +import { ARB } from "src/Icons"; +import { RyskCountUp } from "src/components/shared/RyskCountUp"; +import { Convert } from "src/utils/Convert"; +import { shorthandContractAddress } from "src/utils/helpers"; + +export const Table = ({ recipients }: TableProps) => { + const { address } = useAccount(); + + return ( +
+ + + + + + + + + + + + {recipients.map(({ id, totalTokens, totalValue }, index) => { + const isUser = id === address?.toLowerCase(); + + return ( + + {isUser && ( + + + + + + ); + })} + +
{`Rank`}{`Address`}{`Received`}{`Total value*`}
+ )} + {`# ${index + 1}`}{shorthandContractAddress(id)} + +

+ +

+
+ +
+
+ ); +}; diff --git a/packages/front-end/src/components/Rewards/hooks/useAirdropData.tsx b/packages/front-end/src/components/Rewards/hooks/useAirdropData.tsx new file mode 100644 index 000000000..f03b09cbd --- /dev/null +++ b/packages/front-end/src/components/Rewards/hooks/useAirdropData.tsx @@ -0,0 +1,44 @@ +import type { RewardsQuery, UseAirdropDataValues } from "../types"; + +import { gql, useQuery } from "@apollo/client"; + +import { QueriesEnum } from "src/clients/Apollo/Queries"; +import { Convert } from "src/utils/Convert"; +import { logError } from "src/utils/logError"; + +/** + * Hook to fetch graph data for airdrops. + * Returns the list of airdrop recipients, the total tokens distributed and their total USD value. + * + * @returns [totalTokens, totalValue] - [total tokens distributed, total USD value of those tokens] + */ +export const useAirdropData = (): UseAirdropDataValues => { + const { data } = useQuery( + gql(` + query ${QueriesEnum.REWARDS} { + airdropRecipients (first: 100, orderBy: totalValue, orderDirection: desc) { + id + totalTokens + totalValue + } + } + `), + { + onError: logError, + } + ); + + if (!data) return [[], 0, 0]; + + const [totalTokens, totalValue] = data.airdropRecipients.reduce( + ([totalTokens, totalValue], recipient) => { + const tokens = Convert.fromWei(recipient.totalTokens).toInt(); + const value = Convert.fromStr(recipient.totalValue).toInt(); + + return [totalTokens + tokens, totalValue + value]; + }, + [0, 0] + ); + + return [data.airdropRecipients, totalTokens, totalValue]; +}; diff --git a/packages/front-end/src/components/Rewards/index.tsx b/packages/front-end/src/components/Rewards/index.tsx new file mode 100644 index 000000000..bcb28c9c9 --- /dev/null +++ b/packages/front-end/src/components/Rewards/index.tsx @@ -0,0 +1,20 @@ +import { Header } from "./components/Header"; +import { Active } from "./components/Active"; +import { Footnotes } from "./components/Footnotes"; +import { Info } from "./components/Info"; +import { Table } from "./components/Table"; +import { useAirdropData } from "./hooks/useAirdropData"; + +export const RewardsContent = () => { + const [recipients, totalTokens, totalValue] = useAirdropData(); + + return ( +
+
+ + + + + + ); +}; diff --git a/packages/front-end/src/components/Rewards/types.ts b/packages/front-end/src/components/Rewards/types.ts new file mode 100644 index 000000000..ff8fb3764 --- /dev/null +++ b/packages/front-end/src/components/Rewards/types.ts @@ -0,0 +1,23 @@ +export interface RewardsQuery { + airdropRecipients: { + id: HexString; + totalTokens: string; + totalValue: string; + }[]; +} + +export type UseAirdropDataValues = [ + RewardsQuery["airdropRecipients"], + number, + number, +]; + +export interface RecipientsProps { + recipients: RewardsQuery["airdropRecipients"]; + tokens: number; + value: number; +} + +export interface TableProps { + recipients: RewardsQuery["airdropRecipients"]; +} \ No newline at end of file diff --git a/packages/front-end/src/pages/Rewards.tsx b/packages/front-end/src/pages/Rewards.tsx new file mode 100644 index 000000000..6b8cd4a6a --- /dev/null +++ b/packages/front-end/src/pages/Rewards.tsx @@ -0,0 +1,3 @@ +import { RewardsContent } from "src/components/Rewards"; + +export const Rewards = () => ; From 154e1ad108f64c7d36fe5a9a015210ca68115d9d Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 26 Oct 2023 18:32:53 +0100 Subject: [PATCH 3/5] RYSK-497: Add rewards page to navigation and header. --- packages/front-end/src/App.tsx | 6 ++++-- packages/front-end/src/components/Header.tsx | 1 + packages/front-end/src/config/appPaths.ts | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/front-end/src/App.tsx b/packages/front-end/src/App.tsx index fa4b7e7cd..859d7fc0c 100644 --- a/packages/front-end/src/App.tsx +++ b/packages/front-end/src/App.tsx @@ -1,4 +1,4 @@ -import { Route, Routes, Navigate } from "react-router-dom"; +import { Navigate, Route, Routes } from "react-router-dom"; import { ToastContainer } from "react-toastify"; import ApolloProvider from "./clients/Apollo/Apollo"; @@ -8,14 +8,15 @@ import { Header } from "./components/Header"; import { Init } from "./components/Init"; import { MobileWarning } from "./components/MobileWarning"; import { AppPaths } from "./config/appPaths"; +import { useScrollToTop } from "./hooks/useScrollToTop"; import { Dashboard } from "./pages/Dashboard"; import { OTC } from "./pages/OTC"; import { OptionsTrading } from "./pages/OptionsTrading"; import { PrivacyPolicy } from "./pages/PrivacyPolicy"; +import { Rewards } from "./pages/Rewards"; import { TermsOfService } from "./pages/TermsOfService"; import { Vault } from "./pages/Vault"; import { GlobalContextProvider } from "./state/GlobalContext"; -import { useScrollToTop } from "./hooks/useScrollToTop"; import "react-toastify/dist/ReactToastify.css"; import "./App.css"; @@ -41,6 +42,7 @@ function App() { path={AppPaths.PRIVACY_POLICY} element={} /> + } /> } diff --git a/packages/front-end/src/components/Header.tsx b/packages/front-end/src/components/Header.tsx index 0bd9df235..f79f6db2c 100644 --- a/packages/front-end/src/components/Header.tsx +++ b/packages/front-end/src/components/Header.tsx @@ -16,6 +16,7 @@ const links = [ { id: "header-options", path: AppPaths.TRADE, label: "Trade Options" }, { id: "header-vault", path: AppPaths.VAULT, label: "Vault" }, { id: "header-dashboard", path: AppPaths.DASHBOARD, label: "Dashboard" }, + { id: "header-rewards", path: AppPaths.REWARDS, label: "Rewards" }, ]; export const Header = () => { diff --git a/packages/front-end/src/config/appPaths.ts b/packages/front-end/src/config/appPaths.ts index abddfea6d..130d55242 100644 --- a/packages/front-end/src/config/appPaths.ts +++ b/packages/front-end/src/config/appPaths.ts @@ -4,6 +4,7 @@ export enum AppPaths { HOME = "/", OTC = "/otc", PRIVACY_POLICY = "/privacy-policy", + REWARDS = "/rewards", TERMS_OF_SERVICE = "/terms-of-service", TRADE = "/options", VAULT = "/vault", From dc2dc7dc0ad6079456137725ab484c66d0561a16 Mon Sep 17 00:00:00 2001 From: Tim Dunphy <54942744+MeanBoyCousin@users.noreply.github.com> Date: Fri, 3 Nov 2023 16:49:07 +0000 Subject: [PATCH 4/5] Copy change on blog label. Co-authored-by: Dan --- packages/front-end/src/components/Rewards/components/Active.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/front-end/src/components/Rewards/components/Active.tsx b/packages/front-end/src/components/Rewards/components/Active.tsx index bd1907258..81659f496 100644 --- a/packages/front-end/src/components/Rewards/components/Active.tsx +++ b/packages/front-end/src/components/Rewards/components/Active.tsx @@ -20,7 +20,7 @@ const rewardPrograms = [ { external: true, href: "https://medium.rysk.finance/arbitrum-stip-rewards-for-rysk-6929609e85d7", - label: "Learn more about the Arbitrum STIP rewards.", + label: "Learn more about the rewards.", }, { external: false, From 259d690d65eb846eb16a57a0c831593e256807c3 Mon Sep 17 00:00:00 2001 From: Tim Dunphy <54942744+MeanBoyCousin@users.noreply.github.com> Date: Fri, 3 Nov 2023 16:49:32 +0000 Subject: [PATCH 5/5] Copy change on trading label. Co-authored-by: Dan --- packages/front-end/src/components/Rewards/components/Active.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/front-end/src/components/Rewards/components/Active.tsx b/packages/front-end/src/components/Rewards/components/Active.tsx index 81659f496..6574e41b0 100644 --- a/packages/front-end/src/components/Rewards/components/Active.tsx +++ b/packages/front-end/src/components/Rewards/components/Active.tsx @@ -30,7 +30,7 @@ const rewardPrograms = [ { external: false, href: "/", - label: "Start trading now.", + label: "Trade options now to earn rewards.", }, ], title: "Arbitrum STIP",