From d388137e1c340a56c12772da0e329ca9b3f26742 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Wed, 17 Sep 2025 12:34:50 +0530 Subject: [PATCH 1/8] reward calculator --- .../reward-examples.mdx | 8 + .../RewardSimulator/index.module.scss | 84 +++++++ .../src/components/RewardSimulator/index.tsx | 232 ++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 apps/developer-hub/src/components/RewardSimulator/index.module.scss create mode 100644 apps/developer-hub/src/components/RewardSimulator/index.tsx diff --git a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx index c95c535013..4eb0b90c1b 100644 --- a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx +++ b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx @@ -203,3 +203,11 @@ C_{p_{option2}} &= 100 + 100 \cdot \sum_{s \in \text{\{$s_{6}$,.., $s_{10}$\}}} &= 100 + 50 = 150 \end{aligned} $$ + +## Reward Calculator + +Use the calculator below to calculate publisher and delegator rewards based on your inputs. + +import RewardSimulator from "../../../src/components/RewardSimulator"; + + diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss new file mode 100644 index 0000000000..9e92299e2d --- /dev/null +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -0,0 +1,84 @@ +@use "@pythnetwork/component-library/theme"; + +.card { + margin-top: theme.spacing(6); +} + +.inputGrid { + display: grid; + grid-template-columns: 1fr; + gap: theme.spacing(6); + padding: theme.spacing(4); + + @media (width >= 640px) { + grid-template-columns: 1fr 1fr; + } +} + +.inputGroup { + display: flex; + flex-direction: column; + gap: theme.spacing(2); +} + +.input { + padding: theme.spacing(2) theme.spacing(3); + border: 1px solid var(--color-fd-border); + border-radius: theme.border-radius("lg"); + background-color: var(--color-fd-background); + color: var(--color-fd-foreground); + transition: all 0.15s ease-in-out; + + &:focus { + outline: 2px solid var(--color-fd-accent); + outline-offset: -2px; + border-color: transparent; + } +} + +.resultsSection { + border-top: 1px solid var(--color-fd-border); + margin-top: theme.spacing(6); + padding-top: theme.spacing(6); +} + +.resultsGrid { + display: grid; + grid-template-columns: 1fr; + gap: theme.spacing(6); + + @media (width >= 640px) { + grid-template-columns: 1fr 1fr; + } +} + +.resultGroup { + display: flex; + flex-direction: column; + gap: theme.spacing(3); +} + +.resultTitle { + font-size: theme.font-size("lg"); + font-weight: theme.font-weight("semibold"); + color: var(--color-fd-foreground); +} + +.resultValues { + display: flex; + flex-direction: column; + gap: theme.spacing(2); +} + +.resultItem { + font-size: theme.font-size("sm"); + color: var(--color-fd-muted-foreground); +} + +.resultLabel { + font-weight: theme.font-weight("medium"); +} + +.resultValue { + font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; +} \ No newline at end of file diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx new file mode 100644 index 0000000000..5e845bb181 --- /dev/null +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -0,0 +1,232 @@ +"use client"; + +import { Card } from "@pythnetwork/component-library/Card"; +import { Label } from "@pythnetwork/component-library/unstyled/Label"; +import { Input } from "@pythnetwork/component-library/unstyled/TextField"; +import clsx from "clsx"; +import React, { useState, useEffect } from "react"; + +import styles from "./index.module.scss"; + +// Simple Math component for inline mathematical expressions +const MathExpression: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return {children}; +}; + +// Component for subscripts and superscripts +const Sub: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); +const Sup: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); + +const RewardSimulator: React.FC = () => { + const [publisherStake, setPublisherStake] = useState(200); + const [delegatorStake, setDelegatorStake] = useState(300); + const [maxCap, setMaxCap] = useState(500); + const [delegatorFee, setDelegatorFee] = useState(20); + const [rewardRate, setRewardRate] = useState(10); + + const [publisherReward, setPublisherReward] = useState(0); + const [delegatorReward, setDelegatorReward] = useState(0); + const [publisherRewardRate, setPublisherRewardRate] = useState(0); + const [delegatorRewardRate, setDelegatorRewardRate] = useState(0); + + useEffect(() => { + const calculateRewards = () => { + const totalStake = publisherStake + delegatorStake; + const eligibleAmount = Math.min(totalStake, maxCap); + const totalReward = (rewardRate / 100) * eligibleAmount; + + const publisherRewardBase = + (rewardRate / 100) * Math.min(publisherStake, maxCap); + const delegatorRewardBase = totalReward - publisherRewardBase; + + const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; + + const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; + const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; + + setPublisherReward(Number(finalPublisherReward.toFixed(2))); + setDelegatorReward(Number(finalDelegatorReward.toFixed(2))); + setPublisherRewardRate( + Number(((finalPublisherReward * 100) / publisherStake).toFixed(2)), + ); + setDelegatorRewardRate( + Number(((finalDelegatorReward * 100) / delegatorStake).toFixed(2)), + ); + }; + + calculateRewards(); + }, [publisherStake, delegatorStake, maxCap, delegatorFee, rewardRate]); + + return ( + +
+
+ + { + setPublisherStake(Number(e.target.value)); + }} + className={clsx(styles.input)} + min="0" + /> +
+
+ + { + setDelegatorStake(Number(e.target.value)); + }} + className={clsx(styles.input)} + min="0" + /> +
+
+ + { + setMaxCap(Number(e.target.value)); + }} + className={clsx(styles.input)} + min="0" + /> +
+
+ + { + setDelegatorFee(Number(e.target.value)); + }} + className={clsx(styles.input)} + min="0" + max="100" + step="0.1" + /> +
+
+ + { + setRewardRate(Number(e.target.value)); + }} + className={clsx(styles.input)} + min="0" + max="100" + step="0.1" + /> +
+
+
+
+
+

Calculated Rewards

+
+

+ + Publisher Reward ( + + Rpp + + ): + {" "} + + {publisherReward} + +

+

+ + Delegator Reward ( + + Rdp + + ): + {" "} + + {delegatorReward} + +

+
+
+
+

+ Calculated Reward Rates (Yearly) +

+
+

+ + Publisher Rate ( + + rpp + + ): + {" "} + + {publisherRewardRate}% + +

+

+ + Delegator Rate ( + + rdp + + ): + {" "} + + {delegatorRewardRate}% + +

+
+
+
+
+
+ ); +}; + +export default RewardSimulator; \ No newline at end of file From 032fae302426754fa804bcc67673c0e0afc72605 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Wed, 17 Sep 2025 15:05:36 +0530 Subject: [PATCH 2/8] design enhance --- .../RewardSimulator/index.module.scss | 9 ++-- .../src/components/RewardSimulator/index.tsx | 43 ++++++++++++------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss index 9e92299e2d..6b4156b348 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.module.scss +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -39,7 +39,7 @@ .resultsSection { border-top: 1px solid var(--color-fd-border); margin-top: theme.spacing(6); - padding-top: theme.spacing(6); + padding: theme.spacing(6) theme.spacing(4) 0; } .resultsGrid { @@ -67,7 +67,7 @@ .resultValues { display: flex; flex-direction: column; - gap: theme.spacing(2); + gap: theme.spacing(1); } .resultItem { @@ -80,5 +80,6 @@ } .resultValue { - font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; -} \ No newline at end of file + font-family: + ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; +} diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx index 5e845bb181..eaa3fbfd64 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.tsx +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -3,21 +3,22 @@ import { Card } from "@pythnetwork/component-library/Card"; import { Label } from "@pythnetwork/component-library/unstyled/Label"; import { Input } from "@pythnetwork/component-library/unstyled/TextField"; -import clsx from "clsx"; -import React, { useState, useEffect } from "react"; +import { clsx } from "clsx"; +import { useState, useEffect } from "react"; import styles from "./index.module.scss"; -// Simple Math component for inline mathematical expressions -const MathExpression: React.FC<{ children: React.ReactNode }> = ({ children }) => { - return {children}; -}; +// Components for mathematical notation +const MathExpression = ({ children }: { children: React.ReactNode }) => ( + {children} +); // Component for subscripts and superscripts -const Sub: React.FC<{ children: React.ReactNode }> = ({ children }) => ( +const Sub = ({ children }: { children: React.ReactNode }) => ( {children} ); -const Sup: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + +const Sup = ({ children }: { children: React.ReactNode }) => ( {children} ); @@ -73,7 +74,8 @@ const RewardSimulator: React.FC = () => { @@ -88,11 +90,13 @@ const RewardSimulator: React.FC = () => { min="0" /> +
@@ -107,6 +111,7 @@ const RewardSimulator: React.FC = () => { min="0" />
+
+
+
+
@@ -170,7 +178,8 @@ const RewardSimulator: React.FC = () => { Publisher Reward ( - Rpp + Rp + p ): {" "} @@ -182,7 +191,8 @@ const RewardSimulator: React.FC = () => { Delegator Reward ( - Rdp + Rd + p ): {" "} @@ -192,6 +202,7 @@ const RewardSimulator: React.FC = () => {

+

Calculated Reward Rates (Yearly) @@ -201,7 +212,8 @@ const RewardSimulator: React.FC = () => { Publisher Rate ( - rpp + rp + p ): {" "} @@ -213,7 +225,8 @@ const RewardSimulator: React.FC = () => { Delegator Rate ( - rdp + rd + p ): {" "} @@ -229,4 +242,4 @@ const RewardSimulator: React.FC = () => { ); }; -export default RewardSimulator; \ No newline at end of file +export default RewardSimulator; From 14c140fb3884e17da7846fcdad11e7d543adb50d Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Wed, 17 Sep 2025 15:28:37 +0530 Subject: [PATCH 3/8] use image import instead of url --- .../images}/OIS_Rewards_Example_Dark_1.png | Bin .../images}/OIS_Rewards_Example_Dark_2.png | Bin .../images}/OIS_Rewards_Example_Dark_3.png | Bin .../images}/OIS_Rewards_Example_Dark_4.png | Bin .../images}/OIS_Rewards_Example_Light_1.png | Bin .../images}/OIS_Rewards_Example_Light_2.png | Bin .../images}/OIS_Rewards_Example_Light_3.png | Bin .../images}/OIS_Rewards_Example_Light_4.png | Bin .../ois_slashing_investigation_dark.png | Bin .../ois_slashing_investigation_light.png | Bin .../images}/ois_slashing_pool_post_dark.png | Bin .../images}/ois_slashing_pool_post_light.png | Bin .../images}/ois_slashing_pool_pre_dark.png | Bin .../images}/ois_slashing_pool_pre_light.png | Bin .../reward-examples.mdx | 24 ++++++++++++------ .../slashing-rulebook.mdx | 18 ++++++++----- 16 files changed, 28 insertions(+), 14 deletions(-) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Dark_1.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Dark_2.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Dark_3.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Dark_4.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Light_1.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Light_2.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Light_3.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/OIS_Rewards_Example_Light_4.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_investigation_dark.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_investigation_light.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_pool_post_dark.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_pool_post_light.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_pool_pre_dark.png (100%) rename apps/developer-hub/{public/images/ois => content/docs/oracle-integrity-staking/images}/ois_slashing_pool_pre_light.png (100%) diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_1.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_1.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_1.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_1.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_2.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_2.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_2.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_2.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_3.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_3.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_3.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_3.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_4.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_4.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_4.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_4.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_1.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_1.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_1.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_1.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_2.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_2.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_2.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_2.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_3.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_3.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_3.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_3.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_4.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_4.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_4.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_4.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_investigation_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_investigation_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_investigation_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_investigation_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_light.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_post_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_post_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_post_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_post_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_light.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_pre_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_pre_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_pre_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_pre_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_light.png diff --git a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx index 4eb0b90c1b..fd9ce27931 100644 --- a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx +++ b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx @@ -5,6 +5,14 @@ description: >- --- import DualModeImage from "../../../src/components/DualModeImage"; +import OISExample1Dark from "./images/OIS_Rewards_Example_Dark_1.png"; +import OISExample1Light from "./images/OIS_Rewards_Example_Light_1.png"; +import OISExample2Dark from "./images/OIS_Rewards_Example_Dark_2.png"; +import OISExample2Light from "./images/OIS_Rewards_Example_Light_2.png"; +import OISExample3Dark from "./images/OIS_Rewards_Example_Dark_3.png"; +import OISExample3Light from "./images/OIS_Rewards_Example_Light_3.png"; +import OISExample4Dark from "./images/OIS_Rewards_Example_Dark_4.png"; +import OISExample4Light from "./images/OIS_Rewards_Example_Light_4.png"; NOTE: All the symbols used in the examples are explained in the [Mathematical Representation](./mathematical-representation) section. @@ -14,8 +22,8 @@ This example takes the case of one pool where the pool has stake from only the p
@@ -42,8 +50,8 @@ This example takes the case where the pool has stake from both the publisher and
@@ -70,8 +78,8 @@ This example takes the case where the combined stake of both the publisher and t
@@ -98,8 +106,8 @@ This example demonstrates how the delegation fee affect the reward distribution
diff --git a/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx b/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx index 55f1381743..a205031907 100644 --- a/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx +++ b/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx @@ -6,6 +6,12 @@ description: >- --- import DualModeImage from "../../../src/components/DualModeImage"; +import OISSlashingInvestigationDark from "./images/ois_slashing_investigation_dark.png"; +import OISSlashingInvestigationLight from "./images/ois_slashing_investigation_light.png"; +import OISSlashingPoolPreDark from "./images/ois_slashing_pool_pre_dark.png"; +import OISSlashingPoolPreLight from "./images/ois_slashing_pool_pre_light.png"; +import OISSlashingPoolPostDark from "./images/ois_slashing_pool_post_dark.png"; +import OISSlashingPoolPostLight from "./images/ois_slashing_pool_post_light.png"; # Purpose and Scope @@ -111,8 +117,8 @@ It was found that 7 of the 9 publishers were influencing the price of `FOO/USD` The other 2 publishers were found publish price closely to the mediuan of the reference data. @@ -122,8 +128,8 @@ The other 2 publishers were found publish price closely to the mediuan of the re - From the investigation, \$200K of preventable liquidations were identified from on chain data, the Pythian Council could adjust the amount of stake slashed to 500K PYTH or 100bps (assuming PYTH/USD = $0.40). @@ -134,8 +140,8 @@ The other 2 publishers were found publish price closely to the mediuan of the re - Delegators to `pool_1` would see their stake slashed by 100bps of 4M PYTH, ie. 40K PYTH, resulting in **3.96M** residual delegated stake. From 63721451370c314e4432c87a0b9934cd2e7e81e8 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Wed, 17 Sep 2025 20:07:19 +0530 Subject: [PATCH 4/8] use theme breakpoint and other comments --- .../RewardSimulator/index.module.scss | 4 +- .../src/components/RewardSimulator/index.tsx | 117 ++++++++---------- 2 files changed, 56 insertions(+), 65 deletions(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss index 6b4156b348..da5a2ea497 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.module.scss +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -10,7 +10,7 @@ gap: theme.spacing(6); padding: theme.spacing(4); - @media (width >= 640px) { + @include theme.breakpoint("sm") { grid-template-columns: 1fr 1fr; } } @@ -47,7 +47,7 @@ grid-template-columns: 1fr; gap: theme.spacing(6); - @media (width >= 640px) { + @include theme.breakpoint("sm") { grid-template-columns: 1fr 1fr; } } diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx index eaa3fbfd64..468b413bcb 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.tsx +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -3,14 +3,13 @@ import { Card } from "@pythnetwork/component-library/Card"; import { Label } from "@pythnetwork/component-library/unstyled/Label"; import { Input } from "@pythnetwork/component-library/unstyled/TextField"; -import { clsx } from "clsx"; import { useState, useEffect } from "react"; import styles from "./index.module.scss"; // Components for mathematical notation const MathExpression = ({ children }: { children: React.ReactNode }) => ( - {children} + {children} ); // Component for subscripts and superscripts @@ -35,31 +34,27 @@ const RewardSimulator: React.FC = () => { const [delegatorRewardRate, setDelegatorRewardRate] = useState(0); useEffect(() => { - const calculateRewards = () => { - const totalStake = publisherStake + delegatorStake; - const eligibleAmount = Math.min(totalStake, maxCap); - const totalReward = (rewardRate / 100) * eligibleAmount; - - const publisherRewardBase = - (rewardRate / 100) * Math.min(publisherStake, maxCap); - const delegatorRewardBase = totalReward - publisherRewardBase; - - const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; - - const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; - const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; - - setPublisherReward(Number(finalPublisherReward.toFixed(2))); - setDelegatorReward(Number(finalDelegatorReward.toFixed(2))); - setPublisherRewardRate( - Number(((finalPublisherReward * 100) / publisherStake).toFixed(2)), - ); - setDelegatorRewardRate( - Number(((finalDelegatorReward * 100) / delegatorStake).toFixed(2)), - ); - }; - - calculateRewards(); + const totalStake = publisherStake + delegatorStake; + const eligibleAmount = Math.min(totalStake, maxCap); + const totalReward = (rewardRate / 100) * eligibleAmount; + + const publisherRewardBase = + (rewardRate / 100) * Math.min(publisherStake, maxCap); + const delegatorRewardBase = totalReward - publisherRewardBase; + + const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; + + const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; + const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; + + setPublisherReward(Number(finalPublisherReward.toFixed(2))); + setDelegatorReward(Number(finalDelegatorReward.toFixed(2))); + setPublisherRewardRate( + Number(((finalPublisherReward * 100) / publisherStake).toFixed(2)), + ); + setDelegatorRewardRate( + Number(((finalDelegatorReward * 100) / delegatorStake).toFixed(2)), + ); }, [publisherStake, delegatorStake, maxCap, delegatorFee, rewardRate]); return ( @@ -67,10 +62,10 @@ const RewardSimulator: React.FC = () => { variant="secondary" title="Reward Simulator" nonInteractive - className={clsx(styles.card)} + className={styles.card} > -
-
+
+
-
+
-
+
-
+
@@ -143,14 +138,14 @@ const RewardSimulator: React.FC = () => { onChange={(e) => { setDelegatorFee(Number(e.target.value)); }} - className={clsx(styles.input)} + className={styles.input ?? ""} min="0" max="100" step="0.1" />
-
+
@@ -161,7 +156,7 @@ const RewardSimulator: React.FC = () => { onChange={(e) => { setRewardRate(Number(e.target.value)); }} - className={clsx(styles.input)} + className={styles.input ?? ""} min="0" max="100" step="0.1" @@ -169,13 +164,13 @@ const RewardSimulator: React.FC = () => {
-
-
-
-

Calculated Rewards

-
-

- +

+
+
+

Calculated Rewards

+
+

+ Publisher Reward ( Rp @@ -183,12 +178,10 @@ const RewardSimulator: React.FC = () => { ): {" "} - - {publisherReward} - + {publisherReward}

-

- +

+ Delegator Reward ( Rd @@ -196,20 +189,18 @@ const RewardSimulator: React.FC = () => { ): {" "} - - {delegatorReward} - + {delegatorReward}

-
-

+
+

Calculated Reward Rates (Yearly)

-
-

- +

+

+ Publisher Rate ( rp @@ -217,12 +208,12 @@ const RewardSimulator: React.FC = () => { ): {" "} - + {publisherRewardRate}%

-

- +

+ Delegator Rate ( rd @@ -230,7 +221,7 @@ const RewardSimulator: React.FC = () => { ): {" "} - + {delegatorRewardRate}%

From 32a29c24bb28a793b3f9f2297cde34d17e342924 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 18 Sep 2025 13:01:26 +0530 Subject: [PATCH 5/8] define font family, remove useeffects --- .../RewardSimulator/index.module.scss | 29 +- .../src/components/RewardSimulator/index.tsx | 327 +++++++++--------- packages/component-library/src/theme.scss | 15 + 3 files changed, 191 insertions(+), 180 deletions(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss index da5a2ea497..458d458171 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.module.scss +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -23,21 +23,21 @@ .input { padding: theme.spacing(2) theme.spacing(3); - border: 1px solid var(--color-fd-border); + border: 1px solid theme.color("border"); border-radius: theme.border-radius("lg"); - background-color: var(--color-fd-background); - color: var(--color-fd-foreground); + background-color: theme.color("background", "primary"); + color: theme.color("foreground"); transition: all 0.15s ease-in-out; &:focus { - outline: 2px solid var(--color-fd-accent); + outline: 2px solid theme.color("focus"); outline-offset: -2px; border-color: transparent; } } .resultsSection { - border-top: 1px solid var(--color-fd-border); + border-top: 1px solid theme.color("border"); margin-top: theme.spacing(6); padding: theme.spacing(6) theme.spacing(4) 0; } @@ -61,25 +61,26 @@ .resultTitle { font-size: theme.font-size("lg"); font-weight: theme.font-weight("semibold"); - color: var(--color-fd-foreground); + color: theme.color("foreground"); } -.resultValues { +.resultList { display: flex; flex-direction: column; gap: theme.spacing(1); + margin: 0; } -.resultItem { +.resultTerm { font-size: theme.font-size("sm"); - color: var(--color-fd-muted-foreground); -} - -.resultLabel { + color: theme.color("muted"); font-weight: theme.font-weight("medium"); + margin: 0; } .resultValue { - font-family: - ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; + font-family: theme.font-family("monospace"); + font-size: theme.font-size("sm"); + margin: 0; + margin-bottom: theme.spacing(2); } diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx index 468b413bcb..168c55489d 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.tsx +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -3,7 +3,7 @@ import { Card } from "@pythnetwork/component-library/Card"; import { Label } from "@pythnetwork/component-library/unstyled/Label"; import { Input } from "@pythnetwork/component-library/unstyled/TextField"; -import { useState, useEffect } from "react"; +import { useState, useCallback } from "react"; import styles from "./index.module.scss"; @@ -22,40 +22,55 @@ const Sup = ({ children }: { children: React.ReactNode }) => ( ); const RewardSimulator: React.FC = () => { - const [publisherStake, setPublisherStake] = useState(200); - const [delegatorStake, setDelegatorStake] = useState(300); - const [maxCap, setMaxCap] = useState(500); - const [delegatorFee, setDelegatorFee] = useState(20); - const [rewardRate, setRewardRate] = useState(10); - - const [publisherReward, setPublisherReward] = useState(0); - const [delegatorReward, setDelegatorReward] = useState(0); - const [publisherRewardRate, setPublisherRewardRate] = useState(0); - const [delegatorRewardRate, setDelegatorRewardRate] = useState(0); - - useEffect(() => { - const totalStake = publisherStake + delegatorStake; - const eligibleAmount = Math.min(totalStake, maxCap); - const totalReward = (rewardRate / 100) * eligibleAmount; - - const publisherRewardBase = - (rewardRate / 100) * Math.min(publisherStake, maxCap); - const delegatorRewardBase = totalReward - publisherRewardBase; - - const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; - - const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; - const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; - - setPublisherReward(Number(finalPublisherReward.toFixed(2))); - setDelegatorReward(Number(finalDelegatorReward.toFixed(2))); - setPublisherRewardRate( - Number(((finalPublisherReward * 100) / publisherStake).toFixed(2)), - ); - setDelegatorRewardRate( - Number(((finalDelegatorReward * 100) / delegatorStake).toFixed(2)), - ); - }, [publisherStake, delegatorStake, maxCap, delegatorFee, rewardRate]); + const [rewards, setRewards] = useState({ + // These are the initial values for the reward simulator based on default values + publisher: 26, + delegator: 24, + publisherRate: 13, + delegatorRate: 8, + }); + + const doSubmit = useCallback((e: React.FormEvent) => { + e.currentTarget.requestSubmit(); + }, []); + + const recalculateRewards = useCallback( + (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + + const publisherStake = Number(formData.get("publisherStake")) || 0; + const delegatorStake = Number(formData.get("delegatorStake")) || 0; + const maxCap = Number(formData.get("maxCap")) || 0; + const delegatorFee = Number(formData.get("delegatorFee")) || 0; + const rewardRate = Number(formData.get("rewardRate")) || 0; + + const totalStake = publisherStake + delegatorStake; + const eligibleAmount = Math.min(totalStake, maxCap); + const totalReward = (rewardRate / 100) * eligibleAmount; + + const publisherRewardBase = + (rewardRate / 100) * Math.min(publisherStake, maxCap); + const delegatorRewardBase = totalReward - publisherRewardBase; + + const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; + + const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; + const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; + + setRewards({ + publisher: Number(finalPublisherReward.toFixed(2)), + delegator: Number(finalDelegatorReward.toFixed(2)), + publisherRate: Number( + ((finalPublisherReward * 100) / publisherStake).toFixed(2), + ), + delegatorRate: Number( + ((finalDelegatorReward * 100) / delegatorStake).toFixed(2), + ), + }); + }, + [], + ); return ( { nonInteractive className={styles.card} > -
-
- - { - setPublisherStake(Number(e.target.value)); - }} - className={styles.input ?? ""} - min="0" - /> -
+
+
+
+ + +
-
- - { - setDelegatorStake(Number(e.target.value)); - }} - className={styles.input ?? ""} - min="0" - /> -
+
+ + +
-
- - { - setMaxCap(Number(e.target.value)); - }} - className={styles.input ?? ""} - min="0" - /> -
+
+ + +
-
- - { - setDelegatorFee(Number(e.target.value)); - }} - className={styles.input ?? ""} - min="0" - max="100" - step="0.1" - /> -
+
+ + +
-
- - { - setRewardRate(Number(e.target.value)); - }} - className={styles.input ?? ""} - min="0" - max="100" - step="0.1" - /> +
+ + +
-
- -
-
-
-

Calculated Rewards

-
-

- + +

+
+
+

Calculated Rewards

+
+
Publisher Reward ( Rp p ): - {" "} - {publisherReward} -

-

- +

+
{rewards.publisher}
+
Delegator Reward ( Rd p ): - {" "} - {delegatorReward} -

+
+
{rewards.delegator}
+
-
-
-

- Calculated Reward Rates (Yearly) -

-
-

- +

+

+ Calculated Reward Rates (Yearly) +

+
+
Publisher Rate ( rp p ): - {" "} - - {publisherRewardRate}% - -

-

- +

+
{rewards.publisherRate}%
+
Delegator Rate ( rd p ): - {" "} - - {delegatorRewardRate}% - -

+
+
{rewards.delegatorRate}%
+
-
+ ); }; diff --git a/packages/component-library/src/theme.scss b/packages/component-library/src/theme.scss index ba1e93b1d5..0587c74df4 100644 --- a/packages/component-library/src/theme.scss +++ b/packages/component-library/src/theme.scss @@ -30,6 +30,21 @@ $font-weight: ( @return map-get-strict($font-weight, $weight); } +$font-family: ( + "monospace": ( + "ui-monospace", + "sfmono-regular", + "consolas", + "Liberation Mono", + "menlo", + "monospace", + ), +); + +@function font-family($family) { + @return map-get-strict($font-family, $family); +} + $font-size: ( "xxs": 0.6875rem, "xs": 0.75rem, From 16903fd082eeb71c982c2678d0104eec4f5671bf Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 18 Sep 2025 13:22:30 +0530 Subject: [PATCH 6/8] formating --- apps/developer-hub/src/components/RewardSimulator/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx index 168c55489d..c647533c72 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.tsx +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -24,7 +24,7 @@ const Sup = ({ children }: { children: React.ReactNode }) => ( const RewardSimulator: React.FC = () => { const [rewards, setRewards] = useState({ // These are the initial values for the reward simulator based on default values - publisher: 26, + publisher: 26, delegator: 24, publisherRate: 13, delegatorRate: 8, From 84350cc7a584e00742e384adc6af593f7eee1bbd Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 18 Sep 2025 19:20:06 +0530 Subject: [PATCH 7/8] use tailwind font --- .../components/RewardSimulator/index.module.scss | 2 +- packages/component-library/src/theme.scss | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss index 458d458171..aeeab5b372 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.module.scss +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -79,7 +79,7 @@ } .resultValue { - font-family: theme.font-family("monospace"); + font-family: var(--font-mono); font-size: theme.font-size("sm"); margin: 0; margin-bottom: theme.spacing(2); diff --git a/packages/component-library/src/theme.scss b/packages/component-library/src/theme.scss index 0587c74df4..ba1e93b1d5 100644 --- a/packages/component-library/src/theme.scss +++ b/packages/component-library/src/theme.scss @@ -30,21 +30,6 @@ $font-weight: ( @return map-get-strict($font-weight, $weight); } -$font-family: ( - "monospace": ( - "ui-monospace", - "sfmono-regular", - "consolas", - "Liberation Mono", - "menlo", - "monospace", - ), -); - -@function font-family($family) { - @return map-get-strict($font-family, $family); -} - $font-size: ( "xxs": 0.6875rem, "xs": 0.75rem, From 742bdf80acf1afd353fdbb3f5070821ac836e400 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 18 Sep 2025 20:01:18 +0530 Subject: [PATCH 8/8] Revert "use tailwind font" This reverts commit 84350cc7a584e00742e384adc6af593f7eee1bbd. --- .../components/RewardSimulator/index.module.scss | 2 +- packages/component-library/src/theme.scss | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss index aeeab5b372..458d458171 100644 --- a/apps/developer-hub/src/components/RewardSimulator/index.module.scss +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -79,7 +79,7 @@ } .resultValue { - font-family: var(--font-mono); + font-family: theme.font-family("monospace"); font-size: theme.font-size("sm"); margin: 0; margin-bottom: theme.spacing(2); diff --git a/packages/component-library/src/theme.scss b/packages/component-library/src/theme.scss index ba1e93b1d5..0587c74df4 100644 --- a/packages/component-library/src/theme.scss +++ b/packages/component-library/src/theme.scss @@ -30,6 +30,21 @@ $font-weight: ( @return map-get-strict($font-weight, $weight); } +$font-family: ( + "monospace": ( + "ui-monospace", + "sfmono-regular", + "consolas", + "Liberation Mono", + "menlo", + "monospace", + ), +); + +@function font-family($family) { + @return map-get-strict($font-family, $family); +} + $font-size: ( "xxs": 0.6875rem, "xs": 0.75rem,