diff --git a/apps/hub/src/app/validators/components/cutting-board-configuration.tsx b/apps/hub/src/app/validators/components/cutting-board-configuration.tsx
deleted file mode 100644
index 4aedc0a3c..000000000
--- a/apps/hub/src/app/validators/components/cutting-board-configuration.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-import { useMemo, useState } from "react";
-import { usePollGaugesData } from "@bera/berajs";
-import { Combobox } from "@bera/shared-ui";
-import { BeraChart } from "@bera/ui/bera-chart";
-import { Button } from "@bera/ui/button";
-import { Icons } from "@bera/ui/icons";
-import { Input } from "@bera/ui/input";
-
-export const CuttingBoardConfiguration = () => {
- const [gauges, setGauges] = useState<
- { address: string; distribution: number; color: number }[]
- >([{ address: "", distribution: 0, color: Math.random() * 360 }]);
- const { data, isLoading } = usePollGaugesData();
-
- const colourPalette = [0, 240, 120, 300, 60, 180, 270];
-
- const gaugesData = useMemo(() => {
- return data?.vaults?.map((gauge: any) => ({
- vaultAddress: gauge.vaultAddress,
- stakingTokenAddress: gauge.stakingToken.stakingTokenAddress,
- symbol: gauge.stakingToken.symbol,
- name: gauge.stakingToken.name,
- }));
- }, [data]);
-
- const handleAddGauge = () => {
- setGauges([
- ...gauges,
- { address: "", distribution: 0, color: Math.random() * 360 },
- ]);
- };
-
- const handleDeleteGauge = (index: number) => {
- setGauges(gauges.filter((_, i) => i !== index));
- };
-
- const handleGaugeChange = (
- index: number,
- field: "address" | "distribution",
- value: string | number,
- ) => {
- const updatedGauges = gauges.map((gauge, i) => {
- if (i === index) {
- return { ...gauge, [field]: value };
- }
- return gauge;
- });
- setGauges(updatedGauges);
- };
-
- const totalDistribution = gauges.reduce(
- (sum, gauge) => sum + gauge.distribution,
- 0,
- );
-
- const pieChartData = useMemo(() => {
- return {
- labels: gauges.map((gauge) => gauge.address || "Unassigned"),
- datasets: [
- {
- data: gauges.map((gauge) => gauge.distribution),
- hoverBorderWidth: 5,
- borderRadius: 8,
- spacing: 5,
- borderWidth: 0,
- backgroundColor: gauges.map(
- (gauge, index) =>
- `hsl(${
- colourPalette[index]
- ? colourPalette[index]
- : Math.random() * 360
- }, 70%, 40%)`,
- ),
- hoverBorderColor: gauges.map(
- (gauge, index) =>
- `hsl(${
- colourPalette[index]
- ? colourPalette[index]
- : Math.random() * 360
- }, 70%, 40%)`,
- ),
- // borderColor: "colours",
- },
- ],
- };
- }, [gauges]);
-
- const pieChartOptions = {
- responsive: true,
- cutout: "70%",
- radius: "95%",
- plugins: {
- legend: {
- display: false,
- },
- tooltip: {
- callbacks: {
- label: (context: any) => {
- const label = context.label || "";
- const value = context.parsed || 0;
- return `${label}: ${value}%`;
- },
- },
- },
- },
- };
-
- return (
-
-
- {gauges.map((gauge, index) => (
-
- ({
- value: gaugeData.vaultAddress,
- label: `${gaugeData.symbol} - ${gaugeData.name}`,
- })) || []
- }
- onSelect={(selectedValue) =>
- handleGaugeChange(index, "address", selectedValue)
- }
- />
- {
- const value = e.target.value;
- const [integerPart, decimalPart] = value.split(".");
- const formattedValue = decimalPart
- ? `${integerPart}.${decimalPart.slice(0, 2)}`
- : value;
- handleGaugeChange(
- index,
- "distribution",
- parseFloat(formattedValue),
- );
- }}
- placeholder="Distribution"
- outerClassName="w-fit"
- className="w-48 text-right"
- onKeyDown={(e) =>
- (e.key === "-" || e.key === "e" || e.key === "E") &&
- e.preventDefault()
- }
- maxLength={3}
- min={0}
- max={100}
- // endAdornment={
- //
- // %
- //
- // }
- />
- handleDeleteGauge(index)}
- >
-
-
-
- ))}
-
-
- { }
- Add Gauge
-
-
- { }
-
-
-
-
-
-
-
-
- Total
-
-
- {totalDistribution}%
-
-
-
-
- Total Distribution: {totalDistribution}%
- {totalDistribution !== 100 && (
- Total must equal 100%
- )}
-
-
-
- );
-};
diff --git a/apps/hub/src/app/validators/components/general-settings.tsx b/apps/hub/src/app/validators/components/general-settings.tsx
new file mode 100644
index 000000000..5150753f8
--- /dev/null
+++ b/apps/hub/src/app/validators/components/general-settings.tsx
@@ -0,0 +1,192 @@
+import { useCallback, useMemo, useState } from "react";
+import {
+ TransactionActionType,
+ beaconDepositAbi,
+ useBeraJs,
+ useValidatorOperatorAddress,
+ useValidatorQueuedOperatorAddress,
+} from "@bera/berajs";
+import { depositContractAddress } from "@bera/config";
+import { useTxn } from "@bera/shared-ui";
+import { Button } from "@bera/ui/button";
+import { Card, CardContent, CardFooter } from "@bera/ui/card";
+import { Checkbox } from "@bera/ui/checkbox";
+import { Icons } from "@bera/ui/icons";
+import { Input } from "@bera/ui/input";
+import { Address, zeroAddress } from "viem";
+
+export const GeneralSettings = ({
+ validatorPublicKey,
+}: {
+ validatorPublicKey: Address;
+}) => {
+ const [confirmed, setConfirmed] = useState(false);
+ const { account } = useBeraJs();
+ const {
+ data: operatorAddress,
+ isLoading: isOperatorAddressLoading,
+ refresh: refreshOperatorAddress,
+ } = useValidatorOperatorAddress(validatorPublicKey);
+ const {
+ data: queuedOperatorAddress,
+ isLoading: isQueuedOperatorAddressLoading,
+ refresh: refreshQueuedOperatorAddress,
+ } = useValidatorQueuedOperatorAddress(validatorPublicKey);
+ const [operatorInput, setOperatorInput] = useState(account || "");
+
+ const isQueuedOperatorAddress = useMemo(() => {
+ if (
+ !queuedOperatorAddress ||
+ !operatorAddress ||
+ isQueuedOperatorAddressLoading ||
+ isOperatorAddressLoading
+ )
+ return true;
+ return (
+ queuedOperatorAddress[1] !== operatorAddress &&
+ queuedOperatorAddress[1] !== zeroAddress
+ );
+ }, [
+ queuedOperatorAddress,
+ operatorAddress,
+ isQueuedOperatorAddressLoading,
+ isOperatorAddressLoading,
+ ]);
+
+ const timeRemaining = useMemo(() => {
+ if (!queuedOperatorAddress) return 0;
+ const currentBlockTimestamp = Number(queuedOperatorAddress[0]) * 1000; // Convert seconds to milliseconds
+ const twentyFourHoursInMs = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
+ return currentBlockTimestamp + twentyFourHoursInMs;
+ }, [queuedOperatorAddress]);
+
+ const canQueueOperatorChange = useMemo(() => {
+ if (!queuedOperatorAddress) return false;
+ return (
+ queuedOperatorAddress[1] !== operatorAddress && Date.now() > timeRemaining
+ );
+ }, [queuedOperatorAddress, operatorAddress, timeRemaining]);
+
+ const {
+ write,
+ isLoading: isApplyingOperatorChange,
+ ModalPortal,
+ } = useTxn({
+ message: "Applying Operator Change",
+ actionType: TransactionActionType.APPLYING_OPERATOR_CHANGE,
+ onSuccess: () => {
+ refreshOperatorAddress();
+ refreshQueuedOperatorAddress();
+ },
+ });
+
+ const handleSaveSettings = useCallback(() => {
+ write({
+ address: depositContractAddress,
+ abi: beaconDepositAbi,
+ functionName: "requestOperatorChange",
+ params: [validatorPublicKey, operatorInput as Address],
+ });
+ }, [operatorInput, validatorPublicKey]);
+
+ const handleConfirmQueuedOperatorChange = useCallback(() => {
+ write({
+ address: depositContractAddress,
+ abi: beaconDepositAbi,
+ functionName: "acceptOperatorChange",
+ params: [validatorPublicKey],
+ });
+ }, [validatorPublicKey]);
+
+ const handleCancelQueuedOperatorChange = useCallback(() => {
+ write({
+ address: depositContractAddress,
+ abi: beaconDepositAbi,
+ functionName: "cancelOperatorChange",
+ params: [validatorPublicKey],
+ });
+ }, [validatorPublicKey]);
+
+ return (
+
+ {isQueuedOperatorAddress && (
+
+
+
+
+
+ {canQueueOperatorChange
+ ? "Confirm Operator Address Change"
+ : "Queued Operator Address Change"}
+
+
+ {`Operator Address is currently queued to change to ${
+ queuedOperatorAddress?.[1]
+ }. You'll be able to apply the change at ${new Date(
+ timeRemaining,
+ ).toLocaleString()}`}
+
+
+
+
+ Confirm
+
+
+ Cancel
+
+
+
+
+ )}
+
+ {ModalPortal}
+
+ General Settings
+
+ Configure your operator address
+
+ Operator Address
+ setOperatorInput(e.target.value)}
+ />
+
+
+
+ setConfirmed(!confirmed)}
+ />
+
+ I understand that changing operator address is equivalent to
+ handing over ownership rights to the validator
+
+
+
+ {"Save"}
+
+
+
+
+ );
+};
diff --git a/apps/hub/src/app/validators/components/queued-reward-allocation-configuration.tsx b/apps/hub/src/app/validators/components/queued-reward-allocation-configuration.tsx
new file mode 100644
index 000000000..de23dbb8f
--- /dev/null
+++ b/apps/hub/src/app/validators/components/queued-reward-allocation-configuration.tsx
@@ -0,0 +1,241 @@
+import { useMemo } from "react";
+import {
+ usePollGaugesData,
+ useValidatorQueuedRewardAllocation,
+ useBlockToTimestamp,
+} from "@bera/berajs";
+import { SimpleTable, useAsyncTable } from "@bera/shared-ui";
+import { BeraChart } from "@bera/ui/bera-chart";
+import { Card, CardContent } from "@bera/ui/card";
+import { Skeleton } from "@bera/ui/skeleton";
+import { type ColumnDef } from "@tanstack/react-table";
+import { v4 as uuidv4 } from "uuid";
+import { useBlockNumber } from "wagmi";
+import { Address } from "viem";
+type VaultData = {
+ vaultAddress: string;
+ stakingTokenAddress: string | undefined;
+ symbol: string;
+ name: string;
+};
+
+type VaultWeight = {
+ address: string;
+ distribution: number;
+ id: string;
+ name: string;
+};
+
+const dateFormatter = new Intl.DateTimeFormat("en-US", {
+ year: "numeric",
+ month: "short",
+ day: "numeric",
+ hour: "numeric",
+ minute: "numeric",
+});
+
+export const QueuedRewardAllocationConfiguration = ({
+ validatorPublicKey,
+}: { validatorPublicKey: Address }) => {
+ const {
+ data: queuedRewardAllocation,
+ isLoading: queuedRewardAllocationLoading,
+ } = useValidatorQueuedRewardAllocation(validatorPublicKey);
+ const { data, isLoading: allVaultsLoading } = usePollGaugesData();
+
+ const vaultsData = useMemo(() => {
+ return data?.vaults?.map((vault) => ({
+ vaultAddress: vault.vaultAddress.toLowerCase(),
+ stakingTokenAddress: vault.stakingToken?.address?.toLowerCase(),
+ symbol: vault.stakingToken.symbol,
+ name: vault.stakingToken.name,
+ }));
+ }, [data]);
+
+ const { data: blockNumber } = useBlockNumber();
+
+ const vaults = useMemo(() => {
+ return queuedRewardAllocation?.weights.map((weight) => ({
+ address: weight.receiver.toLowerCase(),
+ distribution: Number(weight.percentageNumerator) / 100,
+ id: uuidv4(),
+ name: `${
+ vaultsData?.find(
+ (item) => item.vaultAddress === weight.receiver.toLowerCase(),
+ )?.symbol
+ } - ${
+ vaultsData?.find(
+ (item) => item.vaultAddress === weight.receiver.toLowerCase(),
+ )?.name
+ }`,
+ }));
+ }, [queuedRewardAllocation, vaultsData]);
+
+ const startBlockTimestamp = useBlockToTimestamp(
+ queuedRewardAllocation?.startBlock ?? 0,
+ );
+
+ const rgbColorPalette = [
+ "rgb(248 113 113)", // bg-red-400
+ "rgb(96 165 250)", // bg-blue-400
+ "rgb(251 146 60)", // bg-orange-400
+ "rgb(167 139 250)", // bg-violet-400
+ "rgb(250 204 21)", // bg-yellow-400
+ "rgb(74 222 128)", // bg-green-400
+ "rgb(56 189 248)", // bg-sky-400
+ "rgb(45 212 191)", // bg-teal-400
+ "rgb(255 210 204)", // bg-pink-400,
+ "rgb(156 163 175)", // bg-gray-400
+ ];
+
+ const queuedTableColumns = useMemo<
+ ColumnDef[]
+ >(() => {
+ return [
+ {
+ header: "Name",
+ accessorKey: "name",
+ cell: ({ row }) => (
+ {row.original?.name}
+ ),
+ enableSorting: false,
+ },
+ {
+ header: "Vault Address",
+ accessorKey: "address",
+ cell: ({ row }) => (
+ {row.original?.address}
+ ),
+ enableSorting: false,
+ },
+ {
+ header: "Distribution",
+ accessorKey: "distribution",
+ enableSorting: false,
+ cell: ({ row }) => (
+ {row.original?.distribution}%
+ ),
+ minSize: 100,
+ size: 100,
+ },
+ ];
+ }, []);
+
+ const queuedTable = useAsyncTable({
+ fetchData: async () => {},
+ columns: queuedTableColumns,
+ data: vaults || [],
+ });
+
+ const pieChartData = useMemo(() => {
+ if (!vaults || !vaultsData) return { labels: [], datasets: [] };
+ return {
+ labels: vaults?.map(
+ (vault) =>
+ vaultsData?.find((item) => item.vaultAddress === vault.address)
+ ?.name || "Unassigned",
+ ),
+ datasets: [
+ {
+ data: vaults?.map((vault) => vault.distribution),
+ hoverBorderWidth: 5,
+ borderRadius: 8,
+ spacing: 5,
+ borderWidth: 0,
+ backgroundColor: vaults?.map(
+ (vault, index) => rgbColorPalette[index],
+ ),
+ hoverBorderColor: vaults?.map(
+ (vault, index) => rgbColorPalette[index],
+ ),
+ },
+ ],
+ };
+ }, [vaults]);
+
+ const pieChartOptions = {
+ responsive: true,
+ cutout: "70%",
+ radius: "95%",
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ backgroundColor: "rgba(0, 0, 0, 1)",
+ cornerRadius: 6,
+ interaction: {
+ intersect: true,
+ },
+ callbacks: {
+ label: (context: any) => {
+ const label = context.label || "";
+ const value = context.parsed || 0;
+ return `${label}: ${value}%`;
+ },
+ },
+ },
+ },
+ };
+
+ return (
+ <>
+ {queuedRewardAllocationLoading || allVaultsLoading ? (
+
+ ) : vaults && vaults.length > 0 ? (
+
+
+
+ {/* Vaults Weight Chart */}
+
+
+ Queued Distribution
+
+
+
+
+
+
+ {`${
+ Number(queuedRewardAllocation?.startBlock) -
+ Number(blockNumber)
+ }`}{" "}
+ Blocks Remaining
+
+
+ {startBlockTimestamp
+ ? dateFormatter.format(
+ typeof startBlockTimestamp === "number"
+ ? startBlockTimestamp * 1000
+ : startBlockTimestamp,
+ )
+ : "--"}
+
+
+
+
+
+
+
+ ) : null}
+ >
+ );
+};
diff --git a/apps/hub/src/app/validators/components/reward-allocation-configuration.tsx b/apps/hub/src/app/validators/components/reward-allocation-configuration.tsx
new file mode 100644
index 000000000..84b924d56
--- /dev/null
+++ b/apps/hub/src/app/validators/components/reward-allocation-configuration.tsx
@@ -0,0 +1,415 @@
+import { useEffect, useMemo, useState } from "react";
+import {
+ BERA_CHEF_ABI,
+ TransactionActionType,
+ useDefaultRewardAllocation,
+ usePollGaugesData,
+ useRewardAllocationBlockDelay,
+ useValidatorQueuedRewardAllocation,
+ useValidatorRewardAllocation,
+} from "@bera/berajs";
+import { beraChefAddress } from "@bera/config";
+import { Combobox, useTxn } from "@bera/shared-ui";
+import { cn } from "@bera/ui";
+import { BeraChart } from "@bera/ui/bera-chart";
+import { Button } from "@bera/ui/button";
+import { Card, CardContent, CardFooter } from "@bera/ui/card";
+import { Icons } from "@bera/ui/icons";
+import { Input } from "@bera/ui/input";
+import { Skeleton } from "@bera/ui/skeleton";
+import BigNumber from "bignumber.js";
+import { v4 as uuidv4 } from "uuid";
+import { Address } from "viem";
+import { useBlockNumber } from "wagmi";
+
+const USER_BLOCK_DELAY = 100n;
+
+export const RewardAllocationConfiguration = ({
+ validatorPublicKey,
+}: { validatorPublicKey: Address }) => {
+ const [vaults, setVaults] = useState<
+ { address: string; distribution: number; id: string }[]
+ >([{ address: "", distribution: 0, id: uuidv4() }]);
+ const { data: rewardVaults, isLoading } = usePollGaugesData();
+ const { data: blockNumber } = useBlockNumber({
+ query: { refetchInterval: 10000 },
+ });
+ const { data: rewardAllocationBlockDelay } = useRewardAllocationBlockDelay();
+ const { data: defaultRewardAllocation } = useDefaultRewardAllocation();
+
+ const {
+ data: queuedRewardAllocation,
+ isLoading: queuedRewardAllocationLoading,
+ refresh: refreshQueuedRewardAllocation,
+ } = useValidatorQueuedRewardAllocation(validatorPublicKey);
+
+ const isQueuedRewardAllocation = useMemo(
+ () =>
+ queuedRewardAllocation?.weights &&
+ queuedRewardAllocation?.weights.length > 0 &&
+ !queuedRewardAllocationLoading,
+ [queuedRewardAllocation, queuedRewardAllocationLoading],
+ );
+
+ const {
+ write,
+ isLoading: isApplyingQueuedRewardAllocation,
+ ModalPortal,
+ } = useTxn({
+ message: "Applying Reward Allocation",
+ actionType: TransactionActionType.APPLYING_REWARD_ALLOCATION,
+ onSuccess: () => {
+ refreshQueuedRewardAllocation();
+ },
+ });
+
+ const { data: rewardAllocation, isLoading: rewardAllocationLoading } =
+ useValidatorRewardAllocation(validatorPublicKey, {
+ opts: { revalidateOnMount: true },
+ });
+
+ const [error, setError] = useState("");
+ const rgbColorPalette = [
+ "rgb(248 113 113)", // bg-red-400
+ "rgb(96 165 250)", // bg-blue-400
+ "rgb(251 146 60)", // bg-orange-400
+ "rgb(167 139 250)", // bg-violet-400
+ "rgb(250 204 21)", // bg-yellow-400
+ "rgb(74 222 128)", // bg-green-400
+ "rgb(56 189 248)", // bg-sky-400
+ "rgb(45 212 191)", // bg-teal-400
+ "rgb(255 210 204)", // bg-pink-400
+ "rgb(156 163 175)", // bg-gray-400
+ ];
+
+ useEffect(() => {
+ if (rewardAllocation?.weights) {
+ setVaults(
+ rewardAllocation.weights.map((weight) => ({
+ address: weight.receiver.toLowerCase(),
+ distribution: Number(weight.percentageNumerator) / 100,
+ id: uuidv4(),
+ })),
+ );
+ }
+ }, [rewardAllocation]);
+
+ const vaultsData = useMemo(() => {
+ return rewardVaults?.vaults?.map((vault) => ({
+ vaultAddress: vault.vaultAddress.toLowerCase(),
+ stakingTokenAddress: vault.stakingToken?.address?.toLowerCase(),
+ symbol: vault.stakingToken.symbol,
+ name: vault.stakingToken.name,
+ }));
+ }, [rewardVaults]);
+
+ const handleAddVault = () => {
+ setVaults([...vaults, { address: "", distribution: 0, id: uuidv4() }]);
+ };
+
+ const handleDeleteVault = (index: number) => {
+ if (vaults.length === 1) return;
+ setVaults(vaults.filter((_, i) => i !== index));
+ };
+
+ const handleVaultChange = (
+ index: number,
+ field: "address" | "distribution",
+ value: string | number,
+ ) => {
+ const updatedVaults = vaults.map((vault, i) => {
+ if (i === index) {
+ return { ...vault, [field]: value };
+ }
+ return vault;
+ });
+ setVaults(updatedVaults);
+ };
+
+ const totalDistributionBN = vaults.reduce((sum, vault) => {
+ return BigNumber(vault.distribution).plus(sum);
+ }, BigNumber(0));
+ const totalDistribution = totalDistributionBN.isNaN()
+ ? ""
+ : totalDistributionBN.toNumber();
+
+ const handleDistributeVaults = () => {
+ const baseDistribution = Math.floor((100 * 100) / vaults.length) / 100; // Get base with 2 decimal places
+ const remainder = 100 - baseDistribution * vaults.length;
+
+ const updatedVaults = vaults.map((vault, index) => {
+ // Add the remainder to the first vault to ensure total is exactly 100
+ const distribution =
+ index === 0 ? baseDistribution + remainder : baseDistribution;
+ return { ...vault, distribution: parseFloat(distribution.toFixed(2)) };
+ });
+
+ setVaults(updatedVaults);
+ };
+
+ const handleQueue = () => {
+ const formattedVaults = vaults.map((vault) => ({
+ receiver: vault.address as Address,
+ percentageNumerator: BigInt(vault.distribution * 100),
+ }));
+ if (!blockNumber || !rewardAllocationBlockDelay) return;
+ write({
+ address: beraChefAddress,
+ abi: BERA_CHEF_ABI,
+ functionName: "queueNewRewardAllocation",
+ params: [
+ validatorPublicKey,
+ (blockNumber || 0n) +
+ (rewardAllocationBlockDelay || 0n) +
+ USER_BLOCK_DELAY,
+ formattedVaults,
+ ],
+ });
+ };
+
+ const handleResetToDefault = () => {
+ setVaults(
+ defaultRewardAllocation?.weights.map((weight) => ({
+ address: weight.receiver.toLowerCase(),
+ distribution: Number(weight.percentageNumerator) / 100,
+ id: uuidv4(),
+ })) || [],
+ );
+ };
+
+ const pieChartData = useMemo(() => {
+ return {
+ labels: vaults.map(
+ (vault) =>
+ vaultsData?.find((item) => item.vaultAddress === vault.address)
+ ?.name || "Unassigned",
+ ),
+ datasets: [
+ {
+ data: vaults.map((vault) => vault.distribution),
+ hoverBorderWidth: 5,
+ borderRadius: 8,
+ spacing: 5,
+ borderWidth: 0,
+ backgroundColor: vaults.map((vault, index) => rgbColorPalette[index]),
+ hoverBorderColor: vaults.map(
+ (vault, index) => rgbColorPalette[index],
+ ),
+ },
+ ],
+ };
+ }, [vaults, vaultsData]);
+
+ const pieChartOptions = {
+ responsive: true,
+ cutout: "70%",
+ radius: "95%",
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ backgroundColor: "rgba(0, 0, 0, 1)",
+ cornerRadius: 6,
+ interaction: {
+ intersect: true,
+ },
+ callbacks: {
+ label: (context: any) => {
+ const label = context.label || "";
+ const value = context.parsed || 0;
+ return `${label}: ${value}%`;
+ },
+ },
+ },
+ },
+ };
+
+ useEffect(() => {
+ const hasEmptyAddress = vaults.some((vault) => vault.address === "");
+ const hasEmptyDistribution = vaults.some(
+ (vault) => vault.distribution === 0,
+ );
+ if (totalDistribution !== 100) {
+ setError("Total distribution must equal 100%");
+ } else if (hasEmptyAddress) {
+ setError("All vaults must have an address");
+ } else if (hasEmptyDistribution) {
+ setError("All vaults must have a distribution");
+ } else {
+ setError("");
+ }
+ }, [totalDistribution, vaults, setError]);
+
+ return (
+
+ {ModalPortal}
+
+ Berachef Weight
+
+ Configure your reward vaults distribution weighting
+
+
+ {/* Vaults Addresses */}
+
+ {vaults.map((vault, index) => (
+
+
+
+ Reward Vault Address
+
+ {isLoading || rewardAllocationLoading ? (
+
+ ) : (
+
({
+ value: vaultData.vaultAddress,
+ label: `${vaultData.symbol} - ${vaultData.name}`,
+ })) || []
+ }
+ value={vaults[index].address}
+ selectedItems={vaults.map((vault) => vault.address)}
+ disabled={isQueuedRewardAllocation}
+ onSelect={(selectedValue) =>
+ handleVaultChange(index, "address", selectedValue)
+ }
+ />
+ )}
+
+
+
Distribution
+
{
+ let value = e.target.value;
+ if (value.includes(".")) {
+ const [integerPart, decimalPart] = value.split(".");
+ value = `${integerPart}.${decimalPart.slice(0, 2)}`;
+ }
+ handleVaultChange(
+ index,
+ "distribution",
+ parseFloat(value),
+ );
+ }}
+ placeholder="Distribution"
+ outerClassName="w-fit h-[42px]"
+ className={cn(
+ "h-[42px] w-32 text-right xl:w-48",
+ vault.distribution > 100 && "text-destructive-foreground",
+ )}
+ onKeyDown={(e) =>
+ (e.key === "-" || e.key === "e" || e.key === "E") &&
+ e.preventDefault()
+ }
+ maxLength={3}
+ min={0}
+ max={100}
+ endAdornment={
+
+ %
+
+ }
+ />
+
+
handleDeleteVault(index)}
+ disabled={vaults.length === 1 || isQueuedRewardAllocation}
+ >
+
+
+
+ ))}
+
+
+ = 10 || isQueuedRewardAllocation}
+ variant={"outline"}
+ onClick={handleAddVault}
+ >
+ { }
+ Add Reward Vault
+
+
+ { }
+
+
+
+ {/* Vaults Weight Chart */}
+
+
+ Current Vaults Weight
+
+
+
+
+
+
+ Total
+
+
+ {totalDistribution}%
+
+
+
+ Total Distribution: {totalDistribution}%
+ {error && {error} }
+
+
+
+
+
+ {isQueuedRewardAllocation && (
+
+ Unable to be modified when there is a current queued reward
+ allocation
+
+ )}
+
+ Reset to Default
+
+
+ Queue
+
+
+
+ );
+};
diff --git a/apps/hub/src/app/validators/components/validator-banner.tsx b/apps/hub/src/app/validators/components/validator-banner.tsx
index 07a580c68..16b4aa532 100644
--- a/apps/hub/src/app/validators/components/validator-banner.tsx
+++ b/apps/hub/src/app/validators/components/validator-banner.tsx
@@ -1,23 +1,34 @@
import Link from "next/link";
-import { truncateHash, useBeraJs, useSelectedValidator } from "@bera/berajs";
+import { truncateHash, useBeraJs, useValidatorByOperator } from "@bera/berajs";
import { ValidatorIcon } from "@bera/shared-ui";
import { getHubValidatorPath } from "@bera/shared-ui";
import { Icons } from "@bera/ui/icons";
export const ValidatorBanner = () => {
const { account, isReady } = useBeraJs();
- const { data: validator, isLoading } = useSelectedValidator(account ?? "0x");
- if (!isReady || !account || isLoading || !validator) return <>>;
+ const { data: validator, isLoading } = useValidatorByOperator(
+ account ?? "0x",
+ );
+ if (
+ !isReady ||
+ !account ||
+ isLoading ||
+ !validator ||
+ validator?.validators.length === 0
+ )
+ return <>>;
return (
-
+
{" "}
Connected as
{" "}
- {validator?.metadata?.name} ({truncateHash(account)})
+ {"Public Key:"}{" "}
+ {truncateHash(validator?.validators[0]?.publicKey ?? "0x")}{" "}
+ {" | Operator: "} ({truncateHash(account)})
Manage as a validator
diff --git a/apps/hub/src/app/validators/components/validator-configuration.tsx b/apps/hub/src/app/validators/components/validator-configuration.tsx
index e2c7efdc9..ebc6e5e91 100644
--- a/apps/hub/src/app/validators/components/validator-configuration.tsx
+++ b/apps/hub/src/app/validators/components/validator-configuration.tsx
@@ -1,72 +1,32 @@
-import { useCallback, useState } from "react";
-import { cn } from "@bera/ui";
-import { Button } from "@bera/ui/button";
+import { useCallback } from "react";
import { Card } from "@bera/ui/card";
-import { Icons } from "@bera/ui/icons";
-import { Input } from "@bera/ui/input";
import { Address } from "viem";
-import { CuttingBoardConfiguration } from "./cutting-board-configuration";
-
+import { QueuedRewardAllocationConfiguration } from "./queued-reward-allocation-configuration";
+import { RewardAllocationConfiguration } from "./reward-allocation-configuration";
+import { GeneralSettings } from "./general-settings";
export const ValidatorConfiguration = ({
- validatorAddress,
+ validatorPublicKey,
}: {
- validatorAddress: Address;
+ validatorPublicKey: Address;
}) => {
- const [operatorAddress, setOperatorAddress] = useState
("");
- const [commission, setCommission] = useState("0");
-
- const handleSaveSettings = useCallback(() => {
- console.log("changing settings", validatorAddress);
- }, []);
-
const handleUpdateMetadata = useCallback(() => {
- console.log("updating metadata", validatorAddress);
+ console.log("updating metadata", validatorPublicKey);
}, []);
return (
-
- Berachef Weight
-
- Configure your reward vaults distribution weighting
-
-
-
-
- General Settings
-
- Configure your operator address & commission
-
- Operator Address
- setOperatorAddress(e.target.value)}
- />
- Commission
- setCommission(e.target.value)}
- />
-
-
- {"Save"}
-
-
+
+
+
Update your metadata
Configure and modify your validator metadata
{"Coming Soon"}
diff --git a/apps/hub/src/app/validators/components/validator-portal-status.tsx b/apps/hub/src/app/validators/components/validator-portal-status.tsx
index 12990889e..fbb260d50 100644
--- a/apps/hub/src/app/validators/components/validator-portal-status.tsx
+++ b/apps/hub/src/app/validators/components/validator-portal-status.tsx
@@ -1,12 +1,12 @@
import React from "react";
-import { truncateHash, useBeraJs, useSelectedValidator } from "@bera/berajs";
+import { truncateHash, useBeraJs, useValidatorByOperator } from "@bera/berajs";
import { ActionButton } from "@bera/shared-ui";
import { Icons } from "@bera/ui/icons";
export const ValidatorPortalStatus = () => {
const { account, isReady } = useBeraJs();
- const { data: validator } = useSelectedValidator(account ?? "0x");
- if (validator) return <>>;
+ const { data: validator } = useValidatorByOperator(account ?? "0x");
+ if (validator?.validators[0]?.publicKey) return <>>;
return (
diff --git a/apps/hub/src/app/validators/components/validator-tabs.tsx b/apps/hub/src/app/validators/components/validator-tabs.tsx
index 327275a7a..5b5e7c11f 100644
--- a/apps/hub/src/app/validators/components/validator-tabs.tsx
+++ b/apps/hub/src/app/validators/components/validator-tabs.tsx
@@ -1,5 +1,9 @@
-import { useState } from "react";
-import { useBeraJs, type Validator } from "@bera/berajs";
+import { useEffect, useState } from "react";
+import {
+ useBeraJs,
+ useValidatorByOperator,
+ type Validator,
+} from "@bera/berajs";
import {
Select,
SelectContent,
@@ -13,28 +17,48 @@ import { ValidatorOverview } from "../validator/validator-overview";
import { ValidatorPolData } from "../validator/validator-pol-data";
import { ValidatorAnalytics } from "./validator-analytics";
import { ValidatorConfiguration } from "./validator-configuration";
-import { ValidatorEvents } from "./validator-events";
+
+// import { ValidatorEvents } from "./validator-events";
+
+type ValidatorTabValue = "overview" | "configuration" | "analytics" | "events";
export const ValidatorTabs = ({ validator }: { validator: Validator }) => {
const { account } = useBeraJs();
+ const { data } = useValidatorByOperator(account ?? "0x");
const isValidatorWallet =
- account?.toLowerCase() === validator.operator.toLowerCase();
+ data?.validators[0]?.publicKey === validator.coinbase;
+
const [dayRange, setDayRange] = useState("30");
+ const [activeTab, setActiveTab] = useState
("overview");
+
+ useEffect(() => {
+ if (activeTab === "configuration" && !isValidatorWallet) {
+ setActiveTab("overview");
+ }
+ }, [isValidatorWallet, activeTab]);
return (
-
+
+ setActiveTab(value as ValidatorTabValue)
+ }
+ defaultValue="overview"
+ >
Overview
- {/* TODO: Uncomment this when we have a working contract for configuration */}
- {/* {isValidatorWallet && (
+ {isValidatorWallet && (
Configuration
- )} */}
+ )}
Analytics
{/* Events */}
- setDayRange(value)}>
+ setDayRange(value)}
+ >
@@ -67,7 +91,9 @@ export const ValidatorTabs = ({ validator }: { validator: Validator }) => {
-
+
{
const { data: tokenHoneyPrices } = useTokenHoneyPrices({
tokenAddresses: activeIncentivesTokens.map(
- (t: Token) => t.address,
+ (t: Token) => t?.address,
) as Address[],
});
const returnPerBgt: number = activeIncentivesArray?.reduce(
(acc: number, ab: ActiveIncentiveWithVault) => {
const tokenPrice = parseFloat(
- tokenHoneyPrices?.[ab.token.address] ?? "0",
+ tokenHoneyPrices?.[ab?.token.address] ?? "0",
);
- return acc + ab.incentiveRate * tokenPrice;
+ return acc + ab?.incentiveRate * tokenPrice;
},
0,
);
diff --git a/apps/hub/src/app/validators/validator/validator.tsx b/apps/hub/src/app/validators/validator/validator.tsx
index f60de91d5..58c75a858 100755
--- a/apps/hub/src/app/validators/validator/validator.tsx
+++ b/apps/hub/src/app/validators/validator/validator.tsx
@@ -2,7 +2,7 @@
import React from "react";
import { notFound } from "next/navigation";
-import { useSelectedValidator, useValidator } from "@bera/berajs";
+import { useValidator } from "@bera/berajs";
import { type Address } from "viem";
import { ValidatorTabs } from "../components/validator-tabs";
diff --git a/packages/berajs/src/abi/pol/BeaconDeposit.ts b/packages/berajs/src/abi/pol/BeaconDeposit.ts
index 4bf940371..bf97c4764 100644
--- a/packages/berajs/src/abi/pol/BeaconDeposit.ts
+++ b/packages/berajs/src/abi/pol/BeaconDeposit.ts
@@ -1,257 +1,595 @@
export const beaconDepositAbi = [
- { inputs: [], type: "error", name: "AlreadyInitialized" },
- { inputs: [], type: "error", name: "AmountLessThanMinIncentiveRate" },
- { inputs: [], type: "error", name: "CannotRecoverIncentiveToken" },
- { inputs: [], type: "error", name: "CannotRecoverRewardToken" },
- { inputs: [], type: "error", name: "CannotRecoverStakingToken" },
- { inputs: [], type: "error", name: "DepositNotMultipleOfGwei" },
- { inputs: [], type: "error", name: "DepositValueTooHigh" },
- { inputs: [], type: "error", name: "DonateAmountLessThanPayoutAmount" },
- { inputs: [], type: "error", name: "IncentiveRateTooHigh" },
- { inputs: [], type: "error", name: "IndexOutOfRange" },
- { inputs: [], type: "error", name: "InsolventReward" },
- { inputs: [], type: "error", name: "InsufficientDelegateStake" },
- { inputs: [], type: "error", name: "InsufficientDeposit" },
- { inputs: [], type: "error", name: "InsufficientSelfStake" },
- { inputs: [], type: "error", name: "InsufficientStake" },
- { inputs: [], type: "error", name: "InvalidActivateBoostDelay" },
- { inputs: [], type: "error", name: "InvalidBaseRate" },
- { inputs: [], type: "error", name: "InvalidBoostMultiplier" },
- { inputs: [], type: "error", name: "InvalidCredentialsLength" },
- { inputs: [], type: "error", name: "InvalidDropBoostDelay" },
- { inputs: [], type: "error", name: "InvalidMaxIncentiveTokensCount" },
- { inputs: [], type: "error", name: "InvalidMinBoostedRewardRate" },
- { inputs: [], type: "error", name: "InvalidProof" },
- { inputs: [], type: "error", name: "InvalidPubKeyLength" },
- { inputs: [], type: "error", name: "InvalidRewardAllocationWeights" },
- { inputs: [], type: "error", name: "InvalidRewardConvexity" },
- { inputs: [], type: "error", name: "InvalidRewardRate" },
- { inputs: [], type: "error", name: "InvalidRewardVaultAddress" },
- { inputs: [], type: "error", name: "InvalidSignatureLength" },
- { inputs: [], type: "error", name: "InvalidStartBlock" },
{
inputs: [],
+ name: "AlreadyInitialized",
type: "error",
+ },
+ {
+ inputs: [],
+ name: "AmountLessThanMinIncentiveRate",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "CannotRecoverIncentiveToken",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "CannotRecoverRewardToken",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "CannotRecoverStakingToken",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "DepositNotMultipleOfGwei",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "DepositValueTooHigh",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "DonateAmountLessThanPayoutAmount",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "IncentiveRateTooHigh",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "IndexOutOfRange",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InsolventReward",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InsufficientDelegateStake",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InsufficientDeposit",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InsufficientSelfStake",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InsufficientStake",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidActivateBoostDelay",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidBaseRate",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidBoostMultiplier",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidCredentialsLength",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidDropBoostDelay",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidMaxIncentiveTokensCount",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidMinBoostedRewardRate",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidProof",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidPubKeyLength",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidRewardAllocationWeights",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidRewardConvexity",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidRewardRate",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidRewardVaultAddress",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidSignatureLength",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "InvalidStartBlock",
+ type: "error",
+ },
+ {
+ inputs: [],
name: "InvalidateDefaultRewardAllocation",
+ type: "error",
},
- { inputs: [], type: "error", name: "InvariantCheckFailed" },
{
inputs: [],
+ name: "InvariantCheckFailed",
type: "error",
+ },
+ {
+ inputs: [],
name: "MaxNumWeightsPerRewardAllocationIsZero",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "MinIncentiveRateIsZero",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotAContract",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotApprovedSender",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotBGT",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotBlockRewardController",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotDelegate",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotDistributor",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotEnoughBalance",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotEnoughBoostedBalance",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotEnoughTime",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotFactoryVault",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotFeeCollector",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotGovernance",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotIncentiveManager",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotNewOperator",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotOperator",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotRootFollower",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "NotWhitelistedVault",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "OperatorAlreadySet",
+ type: "error",
},
- { inputs: [], type: "error", name: "MaxTokensPerAccountReached" },
- { inputs: [], type: "error", name: "MinIncentiveRateIsZero" },
- { inputs: [], type: "error", name: "NotAContract" },
- { inputs: [], type: "error", name: "NotApprovedSender" },
- { inputs: [], type: "error", name: "NotBGT" },
- { inputs: [], type: "error", name: "NotBlockRewardController" },
- { inputs: [], type: "error", name: "NotDelegate" },
- { inputs: [], type: "error", name: "NotDistributor" },
- { inputs: [], type: "error", name: "NotEnoughBalance" },
- { inputs: [], type: "error", name: "NotEnoughBoostedBalance" },
- { inputs: [], type: "error", name: "NotEnoughTime" },
- { inputs: [], type: "error", name: "NotFactoryVault" },
- { inputs: [], type: "error", name: "NotFeeCollector" },
- { inputs: [], type: "error", name: "NotGovernance" },
- { inputs: [], type: "error", name: "NotIncentiveManager" },
- { inputs: [], type: "error", name: "NotNewOperator" },
- { inputs: [], type: "error", name: "NotOperator" },
- { inputs: [], type: "error", name: "NotRootFollower" },
- { inputs: [], type: "error", name: "NotWhitelistedVault" },
- { inputs: [], type: "error", name: "OperatorAlreadySet" },
- { inputs: [], type: "error", name: "PayoutAmountIsZero" },
- { inputs: [], type: "error", name: "RewardAllocationAlreadyQueued" },
{
inputs: [],
+ name: "PayoutAmountIsZero",
type: "error",
+ },
+ {
+ inputs: [],
+ name: "RewardAllocationAlreadyQueued",
+ type: "error",
+ },
+ {
+ inputs: [],
name: "RewardAllocationBlockDelayTooLarge",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "RewardCycleNotEnded",
+ type: "error",
},
- { inputs: [], type: "error", name: "RewardCycleNotEnded" },
- { inputs: [], type: "error", name: "RewardsDurationIsZero" },
- { inputs: [], type: "error", name: "StakeAmountIsZero" },
- { inputs: [], type: "error", name: "TimestampAlreadyProcessed" },
{
inputs: [],
+ name: "RewardsDurationIsZero",
type: "error",
+ },
+ {
+ inputs: [],
+ name: "StakeAmountIsZero",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "TimestampAlreadyProcessed",
+ type: "error",
+ },
+ {
+ inputs: [],
name: "TokenAlreadyWhitelistedOrLimitReached",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "TokenNotWhitelisted",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "TooManyWeights",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "TotalSupplyOverflow",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "VaultAlreadyExists",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "WithdrawAmountIsZero",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "ZeroAddress",
+ type: "error",
+ },
+ {
+ inputs: [],
+ name: "ZeroOperatorOnFirstDeposit",
+ type: "error",
},
- { inputs: [], type: "error", name: "TokenNotInList" },
- { inputs: [], type: "error", name: "TokenNotWhitelisted" },
- { inputs: [], type: "error", name: "TooManyWeights" },
- { inputs: [], type: "error", name: "TotalSupplyOverflow" },
- { inputs: [], type: "error", name: "VaultAlreadyExists" },
- { inputs: [], type: "error", name: "WithdrawAmountIsZero" },
- { inputs: [], type: "error", name: "ZeroAddress" },
- { inputs: [], type: "error", name: "ZeroOperatorOnFirstDeposit" },
- { inputs: [], type: "error", name: "ZeroPercentageWeight" },
{
+ inputs: [],
+ name: "ZeroPercentageWeight",
+ type: "error",
+ },
+ {
+ anonymous: false,
inputs: [
{
+ indexed: false,
internalType: "bytes",
name: "pubkey",
type: "bytes",
- indexed: false,
},
{
+ indexed: false,
internalType: "bytes",
name: "credentials",
type: "bytes",
- indexed: false,
},
{
+ indexed: false,
internalType: "uint64",
name: "amount",
type: "uint64",
- indexed: false,
},
{
+ indexed: false,
internalType: "bytes",
name: "signature",
type: "bytes",
- indexed: false,
},
{
+ indexed: false,
internalType: "uint64",
name: "index",
type: "uint64",
- indexed: false,
},
],
- type: "event",
name: "Deposit",
- anonymous: false,
+ type: "event",
},
{
+ anonymous: false,
inputs: [
{
+ indexed: true,
internalType: "bytes",
name: "pubkey",
type: "bytes",
- indexed: true,
},
],
- type: "event",
name: "OperatorChangeCancelled",
- anonymous: false,
+ type: "event",
},
{
+ anonymous: false,
inputs: [
{
+ indexed: true,
internalType: "bytes",
name: "pubkey",
type: "bytes",
- indexed: true,
},
{
+ indexed: false,
internalType: "address",
name: "queuedOperator",
type: "address",
- indexed: false,
},
{
+ indexed: false,
internalType: "address",
name: "currentOperator",
type: "address",
- indexed: false,
},
{
+ indexed: false,
internalType: "uint256",
name: "queuedTimestamp",
type: "uint256",
- indexed: false,
},
],
- type: "event",
name: "OperatorChangeQueued",
- anonymous: false,
+ type: "event",
},
{
+ anonymous: false,
inputs: [
{
+ indexed: true,
internalType: "bytes",
name: "pubkey",
type: "bytes",
- indexed: true,
},
{
+ indexed: false,
internalType: "address",
name: "newOperator",
type: "address",
- indexed: false,
},
{
+ indexed: false,
internalType: "address",
name: "previousOperator",
type: "address",
- indexed: false,
},
],
- type: "event",
name: "OperatorUpdated",
- anonymous: false,
+ type: "event",
},
{
- inputs: [{ internalType: "bytes", name: "pubkey", type: "bytes" }],
+ inputs: [
+ {
+ internalType: "bytes",
+ name: "pubkey",
+ type: "bytes",
+ },
+ ],
+ name: "acceptOperatorChange",
+ outputs: [],
stateMutability: "nonpayable",
type: "function",
- name: "acceptOperatorChange",
},
{
- inputs: [{ internalType: "bytes", name: "pubkey", type: "bytes" }],
+ inputs: [
+ {
+ internalType: "bytes",
+ name: "pubkey",
+ type: "bytes",
+ },
+ ],
+ name: "cancelOperatorChange",
+ outputs: [],
stateMutability: "nonpayable",
type: "function",
- name: "cancelOperatorChange",
},
{
inputs: [
- { internalType: "bytes", name: "pubkey", type: "bytes" },
- { internalType: "bytes", name: "credentials", type: "bytes" },
- { internalType: "bytes", name: "signature", type: "bytes" },
- { internalType: "address", name: "operator", type: "address" },
+ {
+ internalType: "bytes",
+ name: "pubkey",
+ type: "bytes",
+ },
+ {
+ internalType: "bytes",
+ name: "credentials",
+ type: "bytes",
+ },
+ {
+ internalType: "bytes",
+ name: "signature",
+ type: "bytes",
+ },
+ {
+ internalType: "address",
+ name: "operator",
+ type: "address",
+ },
],
+ name: "deposit",
+ outputs: [],
stateMutability: "payable",
type: "function",
- name: "deposit",
},
{
inputs: [],
+ name: "depositCount",
+ outputs: [
+ {
+ internalType: "uint64",
+ name: "",
+ type: "uint64",
+ },
+ ],
stateMutability: "view",
type: "function",
- name: "depositCount",
- outputs: [{ internalType: "uint64", name: "", type: "uint64" }],
},
{
- inputs: [{ internalType: "bytes", name: "pubkey", type: "bytes" }],
+ inputs: [
+ {
+ internalType: "bytes",
+ name: "pubkey",
+ type: "bytes",
+ },
+ ],
+ name: "getOperator",
+ outputs: [
+ {
+ internalType: "address",
+ name: "",
+ type: "address",
+ },
+ ],
stateMutability: "view",
type: "function",
- name: "getOperator",
- outputs: [{ internalType: "address", name: "", type: "address" }],
},
{
- inputs: [{ internalType: "bytes", name: "", type: "bytes" }],
- stateMutability: "view",
- type: "function",
+ inputs: [
+ {
+ internalType: "bytes",
+ name: "",
+ type: "bytes",
+ },
+ ],
name: "queuedOperator",
outputs: [
- { internalType: "uint96", name: "queuedTimestamp", type: "uint96" },
- { internalType: "address", name: "newOperator", type: "address" },
+ {
+ internalType: "uint96",
+ name: "queuedTimestamp",
+ type: "uint96",
+ },
+ {
+ internalType: "address",
+ name: "newOperator",
+ type: "address",
+ },
],
+ stateMutability: "view",
+ type: "function",
},
{
inputs: [
- { internalType: "bytes", name: "pubkey", type: "bytes" },
- { internalType: "address", name: "newOperator", type: "address" },
+ {
+ internalType: "bytes",
+ name: "pubkey",
+ type: "bytes",
+ },
+ {
+ internalType: "address",
+ name: "newOperator",
+ type: "address",
+ },
],
+ name: "requestOperatorChange",
+ outputs: [],
stateMutability: "nonpayable",
type: "function",
- name: "requestOperatorChange",
},
{
- inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }],
+ inputs: [
+ {
+ internalType: "bytes4",
+ name: "interfaceId",
+ type: "bytes4",
+ },
+ ],
+ name: "supportsInterface",
+ outputs: [
+ {
+ internalType: "bool",
+ name: "",
+ type: "bool",
+ },
+ ],
stateMutability: "pure",
type: "function",
- name: "supportsInterface",
- outputs: [{ internalType: "bool", name: "", type: "bool" }],
},
] as const;
diff --git a/packages/berajs/src/actions/pol/getDefaultRewardAllocation.ts b/packages/berajs/src/actions/pol/getDefaultRewardAllocation.ts
new file mode 100644
index 000000000..31866c0e3
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getDefaultRewardAllocation.ts
@@ -0,0 +1,34 @@
+import { beraChefAddress } from "@bera/config";
+import { PublicClient } from "viem";
+
+import { BERA_CHEF_ABI } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export interface DefaultRewardAllocation {
+ startBlock: bigint;
+ weights: readonly { receiver: `0x${string}`; percentageNumerator: bigint }[];
+}
+
+export const getDefaultRewardAllocation = async ({
+ client,
+ config,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+}): Promise => {
+ try {
+ if (!beraChefAddress)
+ throw new Error("missing contract address beraChefAddress");
+
+ const result = await client.readContract({
+ address: beraChefAddress,
+ abi: BERA_CHEF_ABI,
+ functionName: "getDefaultRewardAllocation",
+ args: [],
+ });
+ return result;
+ } catch (e) {
+ console.log("getRewardAllocationBlockDelay:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getRewardAllocationBlockDelay.ts b/packages/berajs/src/actions/pol/getRewardAllocationBlockDelay.ts
new file mode 100644
index 000000000..8a93cedb4
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getRewardAllocationBlockDelay.ts
@@ -0,0 +1,28 @@
+import { PublicClient } from "viem";
+import { beraChefAddress } from "@bera/config";
+import { BERA_CHEF_ABI } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export const getRewardAllocationBlockDelay = async ({
+ client,
+ config,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+}): Promise => {
+ try {
+ if (!beraChefAddress)
+ throw new Error("missing contract address beraChefAddress");
+
+ const result = await client.readContract({
+ address: beraChefAddress,
+ abi: BERA_CHEF_ABI,
+ functionName: "rewardAllocationBlockDelay",
+ args: [],
+ });
+ return result;
+ } catch (e) {
+ console.log("getRewardAllocationBlockDelay:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getValidatorByOperator.ts b/packages/berajs/src/actions/pol/getValidatorByOperator.ts
new file mode 100644
index 000000000..40797151f
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getValidatorByOperator.ts
@@ -0,0 +1,30 @@
+import { bgtClient } from "@bera/graphql";
+import {
+ GetValidatorByOperator,
+ type GetValidatorByOperatorQuery,
+} from "@bera/graphql/pol";
+import { Address } from "viem";
+
+import { type BeraConfig } from "~/types";
+
+export const getValidatorByOperator = async ({
+ config,
+ address,
+}: {
+ config: BeraConfig;
+ address: Address;
+}): Promise => {
+ try {
+ if (!config.subgraphs?.polSubgraph) {
+ throw new Error("pol subgraph uri is not found in config");
+ }
+ const result = await bgtClient.query({
+ query: GetValidatorByOperator,
+ variables: { operator: address.toLowerCase() },
+ });
+ return result.data;
+ } catch (e) {
+ console.error("getValidatorByOperator:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getValidatorOperatorAddress.ts b/packages/berajs/src/actions/pol/getValidatorOperatorAddress.ts
new file mode 100644
index 000000000..d3f96357f
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getValidatorOperatorAddress.ts
@@ -0,0 +1,32 @@
+import { Address, PublicClient } from "viem";
+import { depositContractAddress } from "@bera/config";
+import { beaconDepositAbi } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export type ValidatorOperatorAddress = Address;
+
+export const getValidatorOperatorAddress = async ({
+ client,
+ config,
+ pubKey,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+ pubKey: Address;
+}): Promise => {
+ try {
+ if (!depositContractAddress)
+ throw new Error("missing contract address depositContractAddress");
+
+ const result = await client.readContract({
+ address: depositContractAddress,
+ abi: beaconDepositAbi,
+ functionName: "getOperator",
+ args: [pubKey],
+ });
+ return result as ValidatorOperatorAddress;
+ } catch (e) {
+ console.log("getValidatorOperatorAddress:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getValidatorQueuedOperatorAddress.ts b/packages/berajs/src/actions/pol/getValidatorQueuedOperatorAddress.ts
new file mode 100644
index 000000000..d92ad911c
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getValidatorQueuedOperatorAddress.ts
@@ -0,0 +1,32 @@
+import { Address, PublicClient } from "viem";
+import { depositContractAddress } from "@bera/config";
+import { beaconDepositAbi } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export type ValidatorQueuedOperatorAddress = [bigint, string];
+
+export const getValidatorQueuedOperatorAddress = async ({
+ client,
+ config,
+ pubKey,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+ pubKey: Address;
+}): Promise => {
+ try {
+ if (!depositContractAddress)
+ throw new Error("missing contract address depositContractAddress");
+
+ const result = await client.readContract({
+ address: depositContractAddress,
+ abi: beaconDepositAbi,
+ functionName: "queuedOperator",
+ args: [pubKey],
+ });
+ return result as ValidatorQueuedOperatorAddress;
+ } catch (e) {
+ console.log("getValidatorQueuedOperatorAddress:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getValidatorQueuedRewardAllocation.ts b/packages/berajs/src/actions/pol/getValidatorQueuedRewardAllocation.ts
new file mode 100644
index 000000000..40572869d
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getValidatorQueuedRewardAllocation.ts
@@ -0,0 +1,38 @@
+import { Address, PublicClient } from "viem";
+import { beraChefAddress } from "@bera/config";
+import { BERA_CHEF_ABI } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export interface ValidatorQueuedRewardAllocation {
+ startBlock: bigint;
+ weights: readonly {
+ receiver: `0x${string}`;
+ percentageNumerator: bigint;
+ }[];
+}
+
+export const getValidatorQueuedRewardAllocation = async ({
+ client,
+ config,
+ pubKey,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+ pubKey: Address;
+}): Promise => {
+ try {
+ if (!beraChefAddress)
+ throw new Error("missing contract address beraChefAddress");
+
+ const result = await client.readContract({
+ address: beraChefAddress,
+ abi: BERA_CHEF_ABI,
+ functionName: "getQueuedRewardAllocation",
+ args: [pubKey],
+ });
+ return result;
+ } catch (e) {
+ console.log("getValidatorQueuedRewardAllocation:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/getValidatorRewardAllocation.ts b/packages/berajs/src/actions/pol/getValidatorRewardAllocation.ts
new file mode 100644
index 000000000..06394fb7c
--- /dev/null
+++ b/packages/berajs/src/actions/pol/getValidatorRewardAllocation.ts
@@ -0,0 +1,38 @@
+import { Address, PublicClient } from "viem";
+import { beraChefAddress } from "@bera/config";
+import { BERA_CHEF_ABI } from "~/abi";
+import { BeraConfig } from "~/types";
+
+export interface ValidatorRewardAllocation {
+ startBlock: bigint;
+ weights: readonly {
+ receiver: `0x${string}`;
+ percentageNumerator: bigint;
+ }[];
+}
+
+export const getValidatorRewardAllocation = async ({
+ client,
+ config,
+ pubKey,
+}: {
+ client: PublicClient;
+ config: BeraConfig;
+ pubKey: Address;
+}): Promise => {
+ try {
+ if (!beraChefAddress)
+ throw new Error("missing contract address beraChefAddress");
+
+ const result = await client.readContract({
+ address: beraChefAddress,
+ abi: BERA_CHEF_ABI,
+ functionName: "getActiveRewardAllocation",
+ args: [pubKey],
+ });
+ return result;
+ } catch (e) {
+ console.log("getValidatorRewardAllocation:", e);
+ throw e;
+ }
+};
diff --git a/packages/berajs/src/actions/pol/index.ts b/packages/berajs/src/actions/pol/index.ts
index 7345dcdb2..2497d4cb9 100644
--- a/packages/berajs/src/actions/pol/index.ts
+++ b/packages/berajs/src/actions/pol/index.ts
@@ -9,3 +9,11 @@ export * from "./get-validator-block-stats";
export * from "./get-validator-token-rewards";
export * from "./get-all-validators";
export * from "./get-reward-vault";
+
+export * from "./getValidatorRewardAllocation";
+export * from "./getRewardAllocationBlockDelay";
+export * from "./getDefaultRewardAllocation";
+export * from "./getValidatorQueuedRewardAllocation";
+export * from "./getValidatorByOperator";
+export * from "./getValidatorQueuedOperatorAddress";
+export * from "./getValidatorOperatorAddress";
diff --git a/packages/berajs/src/enum/txnEnum.ts b/packages/berajs/src/enum/txnEnum.ts
index 697be4598..ca5a38ddf 100755
--- a/packages/berajs/src/enum/txnEnum.ts
+++ b/packages/berajs/src/enum/txnEnum.ts
@@ -51,4 +51,6 @@ export enum TransactionActionType {
// POL
CREATE_REWARDS_VAULT = "Create Reward Vault",
+ APPLYING_REWARD_ALLOCATION = "Applying Reward Allocation",
+ APPLYING_OPERATOR_CHANGE = "Applying Operator Change",
}
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useDefaultRewardAllocation.ts b/packages/berajs/src/hooks/modules/pol/hooks/useDefaultRewardAllocation.ts
new file mode 100644
index 000000000..97041c008
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useDefaultRewardAllocation.ts
@@ -0,0 +1,39 @@
+import useSWR, { mutate } from "swr";
+import { usePublicClient } from "wagmi";
+
+import {
+ DefaultRewardAllocation,
+ getDefaultRewardAllocation,
+} from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useDefaultRewardAllocation = (
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config ? ["useDefaultRewardAllocation"] : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ if (!publicClient) throw new Error("publicClient is not defined");
+ if (!config) throw new Error("missing beraConfig");
+ return await getDefaultRewardAllocation({
+ config,
+ client: publicClient,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useRewardAllocationBlockDelay.ts b/packages/berajs/src/hooks/modules/pol/hooks/useRewardAllocationBlockDelay.ts
new file mode 100644
index 000000000..727e71fee
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useRewardAllocationBlockDelay.ts
@@ -0,0 +1,35 @@
+import useSWR, { mutate } from "swr";
+import { PublicClient } from "viem";
+import { usePublicClient } from "wagmi";
+
+import { getRewardAllocationBlockDelay } from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useRewardAllocationBlockDelay = (
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config ? ["useRewardAllocationBlockDelay"] : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ return await getRewardAllocationBlockDelay({
+ config,
+ client: publicClient as PublicClient,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useValidatorByOperator.ts b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorByOperator.ts
new file mode 100644
index 000000000..ea12a96bb
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorByOperator.ts
@@ -0,0 +1,33 @@
+import { type GetValidatorByOperatorQuery } from "@bera/graphql/pol";
+import { mutate } from "swr";
+import useSWRImmutable from "swr/immutable";
+import { Address } from "viem";
+
+import { getValidatorByOperator } from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useValidatorByOperator = (
+ address: Address,
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ address && config ? ["useValidatorByOperator", address] : null;
+
+ const swrResponse = useSWRImmutable(
+ QUERY_KEY,
+ async () => {
+ return await getValidatorByOperator({ config, address: address });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useValidatorOperatorAddress.ts b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorOperatorAddress.ts
new file mode 100644
index 000000000..9e82cfdb2
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorOperatorAddress.ts
@@ -0,0 +1,42 @@
+import useSWR, { mutate } from "swr";
+import { Address, PublicClient } from "viem";
+import { usePublicClient } from "wagmi";
+
+import {
+ ValidatorOperatorAddress,
+ getValidatorOperatorAddress,
+} from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useValidatorOperatorAddress = (
+ pubKey: Address,
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config && pubKey
+ ? ["useValidatorOperatorAddress", pubKey]
+ : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ return await getValidatorOperatorAddress({
+ config,
+ client: publicClient as PublicClient,
+ pubKey: pubKey,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedOperatorAddress.ts b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedOperatorAddress.ts
new file mode 100644
index 000000000..d92ec1784
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedOperatorAddress.ts
@@ -0,0 +1,42 @@
+import useSWR, { mutate } from "swr";
+import { Address, PublicClient } from "viem";
+import { usePublicClient } from "wagmi";
+
+import {
+ ValidatorQueuedOperatorAddress,
+ getValidatorQueuedOperatorAddress,
+} from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useValidatorQueuedOperatorAddress = (
+ pubKey: Address,
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config && pubKey
+ ? ["useValidatorQueuedOperatorAddress", pubKey]
+ : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ return await getValidatorQueuedOperatorAddress({
+ config,
+ client: publicClient as PublicClient,
+ pubKey: pubKey,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedRewardAllocation.ts b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedRewardAllocation.ts
new file mode 100644
index 000000000..1317d7caf
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorQueuedRewardAllocation.ts
@@ -0,0 +1,42 @@
+import useSWR, { mutate } from "swr";
+import { Address, PublicClient } from "viem";
+import { usePublicClient } from "wagmi";
+
+import {
+ ValidatorQueuedRewardAllocation,
+ getValidatorQueuedRewardAllocation,
+} from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useValidatorQueuedRewardAllocation = (
+ pubKey: Address,
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config && pubKey
+ ? ["useValidatorQueuedRewardAllocation", pubKey]
+ : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ return await getValidatorQueuedRewardAllocation({
+ config,
+ client: publicClient as PublicClient,
+ pubKey: pubKey,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/hooks/useValidatorRewardAllocation.ts b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorRewardAllocation.ts
new file mode 100644
index 000000000..679224568
--- /dev/null
+++ b/packages/berajs/src/hooks/modules/pol/hooks/useValidatorRewardAllocation.ts
@@ -0,0 +1,42 @@
+import useSWR, { mutate } from "swr";
+import { Address, PublicClient } from "viem";
+import { usePublicClient } from "wagmi";
+
+import {
+ ValidatorRewardAllocation,
+ getValidatorRewardAllocation,
+} from "~/actions/pol";
+import { useBeraJs } from "~/contexts";
+import { DefaultHookOptions, DefaultHookReturnType } from "~/types";
+
+export const useValidatorRewardAllocation = (
+ pubKey: Address,
+ options?: DefaultHookOptions,
+): DefaultHookReturnType => {
+ const { config: beraConfig } = useBeraJs();
+ const publicClient = usePublicClient();
+ const config = options?.beraConfigOverride ?? beraConfig;
+ const QUERY_KEY =
+ publicClient && config && pubKey
+ ? ["useValidatorRewardAllocation", pubKey]
+ : null;
+
+ const swrResponse = useSWR(
+ QUERY_KEY,
+ async () => {
+ return await getValidatorRewardAllocation({
+ config,
+ client: publicClient as PublicClient,
+ pubKey: pubKey,
+ });
+ },
+ {
+ ...options?.opts,
+ },
+ );
+
+ return {
+ ...swrResponse,
+ refresh: () => mutate(QUERY_KEY),
+ };
+};
diff --git a/packages/berajs/src/hooks/modules/pol/index.ts b/packages/berajs/src/hooks/modules/pol/index.ts
index b10b88c74..d72383db4 100644
--- a/packages/berajs/src/hooks/modules/pol/index.ts
+++ b/packages/berajs/src/hooks/modules/pol/index.ts
@@ -14,3 +14,11 @@ export * from "./hooks/useRewardVaultBalanceFromStakingToken";
export { useRewardVaultFromToken } from "./hooks/useRewardVaultFromToken";
export { usePollRewardVault } from "./hooks/poll-reward-vault";
export { useSubgraphUserValidators } from "./hooks/useSubgraphUserValidators";
+
+export { useValidatorRewardAllocation } from "./hooks/useValidatorRewardAllocation";
+export { useRewardAllocationBlockDelay } from "./hooks/useRewardAllocationBlockDelay";
+export { useDefaultRewardAllocation } from "./hooks/useDefaultRewardAllocation";
+export { useValidatorQueuedRewardAllocation } from "./hooks/useValidatorQueuedRewardAllocation";
+export { useValidatorByOperator } from "./hooks/useValidatorByOperator";
+export { useValidatorQueuedOperatorAddress } from "./hooks/useValidatorQueuedOperatorAddress";
+export { useValidatorOperatorAddress } from "./hooks/useValidatorOperatorAddress";
diff --git a/packages/graphql/src/modules/pol/pol.graphql b/packages/graphql/src/modules/pol/pol.graphql
index d8126a4dd..1f8e6cf33 100644
--- a/packages/graphql/src/modules/pol/pol.graphql
+++ b/packages/graphql/src/modules/pol/pol.graphql
@@ -192,7 +192,7 @@ query GetGauges {
globalRewardAllocations(first: 1) {
...GlobalRewardAllocation
}
- vaults(first: 1000, where: { stakingTokenAmount_gt: "0" }) {
+ vaults(first: 1000, where: { isWhitelisted: true }) {
...VaultWithStakingToken
}
}
@@ -219,3 +219,9 @@ query GetRewardVault($stakingToken: String) {
...VaultWithStakingToken
}
}
+
+query GetValidatorByOperator($operator: Bytes = "") {
+ validators(where: {operator: $operator}) {
+ publicKey
+ }
+}
\ No newline at end of file
diff --git a/packages/shared-ui/src/combo-box.tsx b/packages/shared-ui/src/combo-box.tsx
index 1eda98faa..2901f9ad4 100644
--- a/packages/shared-ui/src/combo-box.tsx
+++ b/packages/shared-ui/src/combo-box.tsx
@@ -16,15 +16,20 @@ import { Popover, PopoverContent, PopoverTrigger } from "@bera/ui/popover";
export function Combobox({
items,
+ selectedItems,
onSelect,
className,
+ value,
+ disabled,
}: {
items: { value: string; label: string }[];
+ selectedItems: string[];
onSelect: (value: string) => void;
className?: string;
+ value: string;
+ disabled?: boolean;
}) {
const [open, setOpen] = React.useState(false);
- const [value, setValue] = React.useState("");
const [buttonWidth, setButtonWidth] = React.useState(0);
const buttonRef = React.useRef(null);
@@ -41,6 +46,7 @@ export function Combobox({
}, [updateButtonWidth]);
const handleOpenChange = (newOpen: boolean) => {
+ if (disabled) return;
if (newOpen) {
updateButtonWidth();
}
@@ -56,16 +62,21 @@ export function Combobox({
aria-expanded={open}
size="sm"
ref={buttonRef}
+ disabled={disabled}
className={cn(
- "w-full justify-between rounded-md border border-border p-3 font-semibold text-foreground",
+ "w-full min-w-[100px] justify-between rounded-sm text-sm border border-border p-2 text-foreground font-medium",
className,
)}
>
-
- {value
- ? items.find((item) => item.value === value)?.label
- : "Select item..."}
-
+ {value ? (
+
+ {items.find((item) => item.value === value)?.label}
+
+ ) : (
+
+ Select Item...
+
+ )}
@@ -79,8 +90,10 @@ export function Combobox({
{
- setValue(currentValue === value ? "" : currentValue);
setOpen(false);
onSelect(currentValue); // Call the onSelect function
}}
diff --git a/packages/shared-ui/src/table/v2/lib/components/core/table-row.tsx b/packages/shared-ui/src/table/v2/lib/components/core/table-row.tsx
index 4e44a4dcf..5c2f99b02 100755
--- a/packages/shared-ui/src/table/v2/lib/components/core/table-row.tsx
+++ b/packages/shared-ui/src/table/v2/lib/components/core/table-row.tsx
@@ -10,6 +10,8 @@ export interface TableRowProps {
flexTable?: boolean;
onRowClick?: (row: any) => void;
onRowHover?: (row: any) => void;
+ lastRowBorder?: boolean;
+ lastRow?: boolean;
}
export const TableRow: (
@@ -22,11 +24,16 @@ export const TableRow: (
className,
children,
flexTable,
+ lastRowBorder,
+ lastRow,
}) => {
return (
onRowClick?.(row as any)}
onMouseOver={() => onRowHover?.(row as any)}
data-state={row.getIsSelected() && "selected"}
diff --git a/packages/shared-ui/src/table/v2/lib/simple-table/simple-table.tsx b/packages/shared-ui/src/table/v2/lib/simple-table/simple-table.tsx
index 8f45502be..57102d50d 100755
--- a/packages/shared-ui/src/table/v2/lib/simple-table/simple-table.tsx
+++ b/packages/shared-ui/src/table/v2/lib/simple-table/simple-table.tsx
@@ -26,6 +26,7 @@ export type SimpleTableProps = TableBodyProps & {
mutedBackgroundOnHead?: boolean;
minWidth?: number;
variant?: string;
+ lastRowBorder?: boolean;
};
export function SimpleTable({
@@ -42,6 +43,7 @@ export function SimpleTable({
onRowClick,
onRowHover,
variant = "",
+ lastRowBorder = true,
...props
}: SimpleTableProps) {
const minWidth =
@@ -99,7 +101,7 @@ export function SimpleTable({
tableBodyRef={tableBodyRef}
>
{rows.length > 0 ? (
- rows.map((row) => {
+ rows.map((row, index) => {
return (
({
flexTable={flexTable}
onRowHover={onRowHover}
onRowClick={onRowClick}
+ lastRowBorder={lastRowBorder}
+ lastRow={index === rows.length - 1}
>
{row.getVisibleCells().map((cell) => (
=6'}
- cmdk@0.2.1:
- resolution: {integrity: sha512-U6//9lQ6JvT47+6OF6Gi8BvkxYQ8SCRRSKIJkthIMsFsLZRG0cKvTtuTaefyIKMQb8rvvXy0wGdpTNq/jPtm+g==}
+ cmdk@1.0.4:
+ resolution: {integrity: sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg==}
peerDependencies:
- react: ^18.0.0
- react-dom: ^18.0.0
+ react: ^18 || ^19 || ^19.0.0-rc
+ react-dom: ^18 || ^19 || ^19.0.0-rc
co@4.6.0:
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
@@ -12058,16 +11975,6 @@ packages:
'@types/react':
optional: true
- react-remove-scroll@2.5.4:
- resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
- react: ^16.8.0 || ^17.0.0 || ^18.0.0
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
react-remove-scroll@2.5.5:
resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==}
engines: {node: '>=10'}
@@ -18805,10 +18712,6 @@ snapshots:
dependencies:
'@babel/runtime': 7.24.7
- '@radix-ui/primitive@1.0.0':
- dependencies:
- '@babel/runtime': 7.24.7
-
'@radix-ui/primitive@1.0.1':
dependencies:
'@babel/runtime': 7.24.7
@@ -18984,11 +18887,6 @@ snapshots:
'@types/react': 19.0.1
'@types/react-dom': 18.3.0
- '@radix-ui/react-compose-refs@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- react: 18.2.0
-
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19008,11 +18906,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-context@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- react: 18.2.0
-
'@radix-ui/react-context@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19044,28 +18937,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-dialog@1.0.0(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/primitive': 1.0.0
- '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
- '@radix-ui/react-context': 1.0.0(react@18.2.0)
- '@radix-ui/react-dismissable-layer': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-focus-guards': 1.0.0(react@18.2.0)
- '@radix-ui/react-focus-scope': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-id': 1.0.0(react@18.2.0)
- '@radix-ui/react-portal': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-presence': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-primitive': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-slot': 1.0.0(react@18.2.0)
- '@radix-ui/react-use-controllable-state': 1.0.0(react@18.2.0)
- aria-hidden: 1.2.4
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
- react-remove-scroll: 2.5.4(@types/react@18.3.3)(react@18.2.0)
- transitivePeerDependencies:
- - '@types/react'
-
'@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.6
@@ -19089,6 +18960,28 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
+ '@radix-ui/react-dialog@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-context': 1.1.1(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-portal': 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ aria-hidden: 1.2.4
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ react-remove-scroll: 2.6.0(@types/react@18.3.3)(react@18.2.0)
+ optionalDependencies:
+ '@types/react': 18.3.3
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-dialog@1.1.2(@types/react-dom@18.3.0)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -19130,17 +19023,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-dismissable-layer@1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/primitive': 1.0.0
- '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
- '@radix-ui/react-primitive': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0)
- '@radix-ui/react-use-escape-keydown': 1.0.0(react@18.2.0)
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
-
'@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19169,6 +19051,19 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
+ '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ optionalDependencies:
+ '@types/react': 18.3.3
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@18.3.0)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -19198,14 +19093,15 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
- '@radix-ui/react-focus-guards@1.0.0(react@18.2.0)':
+ '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
react: 18.2.0
+ optionalDependencies:
+ '@types/react': 18.3.3
- '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.3)(react@18.2.0)':
+ '@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
- '@babel/runtime': 7.24.7
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.3
@@ -19216,15 +19112,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-focus-scope@1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
- '@radix-ui/react-primitive': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
- '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0)
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
-
'@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19249,6 +19136,17 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
+ '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ optionalDependencies:
+ '@types/react': 18.3.3
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
@@ -19282,12 +19180,6 @@ snapshots:
dependencies:
react: 19.0.0
- '@radix-ui/react-id@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-use-layout-effect': 1.0.0(react@18.2.0)
- react: 18.2.0
-
'@radix-ui/react-id@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19504,14 +19396,17 @@ snapshots:
'@types/react': 19.0.1
'@types/react-dom': 18.3.0
- '@radix-ui/react-portal@1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ '@radix-ui/react-portal@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
- '@radix-ui/react-primitive': 1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
+ optionalDependencies:
+ '@types/react': 18.3.3
+ '@types/react-dom': 18.3.0
- '@radix-ui/react-portal@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -19521,10 +19416,10 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
- '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ '@radix-ui/react-portal@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
optionalDependencies:
@@ -19541,14 +19436,6 @@ snapshots:
'@types/react': 19.0.1
'@types/react-dom': 18.3.0
- '@radix-ui/react-presence@1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
- '@radix-ui/react-use-layout-effect': 1.0.0(react@18.2.0)
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
-
'@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19580,13 +19467,6 @@ snapshots:
'@types/react': 19.0.1
'@types/react-dom': 18.3.0
- '@radix-ui/react-primitive@1.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-slot': 1.0.0(react@18.2.0)
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
-
'@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19774,12 +19654,6 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
- '@radix-ui/react-slot@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
- react: 18.2.0
-
'@radix-ui/react-slot@1.0.2(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.6
@@ -19937,11 +19811,6 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
- '@radix-ui/react-use-callback-ref@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- react: 18.2.0
-
'@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19961,12 +19830,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-use-controllable-state@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0)
- react: 18.2.0
-
'@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -19989,16 +19852,17 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-use-escape-keydown@1.0.0(react@18.2.0)':
+ '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
- '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0)
react: 18.2.0
+ optionalDependencies:
+ '@types/react': 18.3.3
- '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.3)(react@18.2.0)':
+ '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.3)(react@18.2.0)':
dependencies:
- '@babel/runtime': 7.24.7
- '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0)
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.3
@@ -20010,11 +19874,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- '@radix-ui/react-use-layout-effect@1.0.0(react@18.2.0)':
- dependencies:
- '@babel/runtime': 7.24.7
- react: 18.2.0
-
'@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.3)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.7
@@ -24236,13 +24095,17 @@ snapshots:
clsx@2.1.1: {}
- cmdk@0.2.1(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
+ cmdk@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
- '@radix-ui/react-dialog': 1.0.0(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-dialog': 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.2.0)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
+ use-sync-external-store: 1.2.2(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
+ - '@types/react-dom'
co@4.6.0: {}
@@ -29577,7 +29440,7 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.1
- react-remove-scroll@2.5.4(@types/react@18.3.3)(react@18.2.0):
+ react-remove-scroll@2.5.5(@types/react@18.3.3)(react@18.2.0):
dependencies:
react: 18.2.0
react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.2.0)
@@ -29588,7 +29451,7 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.3
- react-remove-scroll@2.5.5(@types/react@18.3.3)(react@18.2.0):
+ react-remove-scroll@2.6.0(@types/react@18.3.3)(react@18.2.0):
dependencies:
react: 18.2.0
react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.2.0)