-
- {!isUndefined(chartData) ? (
-
- ) : (
-
-
-
- )}
-
-
-
-
-
- {markets.map((market, i) => (
-
-
-
- ))}
+
+ {experiments.map((experiment, index) => (
+
+
- {predictionMarkets.length > 0 ? (
-
-
-
-
- ) : null}
-
-
-
-
+ ))}
-
-
{
- setOnboardingDone(true);
- toggleGuide(false);
- }}
- />
+
);
diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png
index 5be3a9a..d8a92b5 100644
Binary files a/src/app/apple-icon.png and b/src/app/apple-icon.png differ
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
index 64aac39..ccda0c1 100644
Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ
diff --git a/src/app/globals.css b/src/app/globals.css
index 05f199b..5c6230f 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -81,6 +81,7 @@
--foreground: #171717;
--red-2: #f75c7b;
--green-2: #3fec65;
+ --klerosUIComponentsPrimaryBlue: #4872ff;
}
:root.dark {
@@ -88,6 +89,7 @@
--foreground: #ededed;
--red-2: #ffd2db;
--green-2: #d2ffdc;
+ --klerosUIComponentsPrimaryBlue: #4872ff;
}
body {
diff --git a/src/app/icon0.svg b/src/app/icon0.svg
index 2e9f294..ccdb56b 100644
--- a/src/app/icon0.svg
+++ b/src/app/icon0.svg
@@ -1,3 +1,11 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/app/icon1.png b/src/app/icon1.png
index d63709d..fffad8e 100644
Binary files a/src/app/icon1.png and b/src/app/icon1.png differ
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index c340be2..a8d076d 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -2,13 +2,6 @@ import { ThemeProvider } from "next-themes";
import clsx from "clsx";
import localFont from "next/font/local";
-import { headers } from "next/headers";
-import { ToastContainer } from "react-toastify";
-
-import Web3Context from "@/context/Web3Context";
-
-import Footer from "@/components/layout/Footer";
-import Header from "@/components/layout/Header";
import "@kleros/ui-components-library/style.css";
import "./globals.css";
@@ -31,8 +24,6 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
- const cookies = headers().get("cookie");
-
return (
@@ -44,14 +35,9 @@ export default function RootLayout({
"flex size-full flex-col",
)}
>
-
-
-
-
- {children}
-
-
-
+
+ {children}
+
);
diff --git a/src/app/settings/email-confirmation/page.tsx b/src/app/settings/email-confirmation/page.tsx
index 412f3a8..d241ac9 100644
--- a/src/app/settings/email-confirmation/page.tsx
+++ b/src/app/settings/email-confirmation/page.tsx
@@ -1,20 +1,21 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
+import { useAtlasProvider } from "@kleros/kleros-app";
+import { Button } from "@kleros/ui-components-library";
+import clsx from "clsx";
+import Link from "next/link";
+import { useSearchParams } from "next/navigation";
import { isAddress } from "viem";
-import { Button } from "@kleros/ui-components-library";
+import Loader from "@/components/Loader";
import CheckIcon from "@/assets/svg/check-circle.svg";
-import WarningIcon from "@/assets/svg/warning-outline.svg";
import InvalidIcon from "@/assets/svg/minus-outline.svg";
+import WarningIcon from "@/assets/svg/warning-outline.svg";
-import { useAtlasProvider } from "@kleros/kleros-app";
-import clsx from "clsx";
import { cn } from "@/utils";
-import { useSearchParams } from "next/navigation";
-import Loader from "@/components/Loader";
-import Link from "next/link";
+
import { tgLink } from "@/consts/markets";
enum TextColor {
diff --git a/src/app/settings/layout.tsx b/src/app/settings/layout.tsx
new file mode 100644
index 0000000..b5a6575
--- /dev/null
+++ b/src/app/settings/layout.tsx
@@ -0,0 +1,24 @@
+import { headers } from "next/headers";
+import { ToastContainer } from "react-toastify";
+
+import Web3Context from "@/context/Web3Context";
+
+import Footer from "@/components/layout/Footer";
+import Header from "@/components/layout/Header";
+
+export default function SettingsLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const cookies = headers().get("cookie");
+
+ return (
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/src/app/settings/unsubscribe/page.tsx b/src/app/settings/unsubscribe/page.tsx
new file mode 100644
index 0000000..8821856
--- /dev/null
+++ b/src/app/settings/unsubscribe/page.tsx
@@ -0,0 +1,181 @@
+"use client";
+import React, { useCallback, useEffect, useState } from "react";
+
+import { useAtlasProvider } from "@kleros/kleros-app";
+import { AlertMessage, Button } from "@kleros/ui-components-library";
+import clsx from "clsx";
+import Link from "next/link";
+import { usePrevious } from "react-use";
+import { useAccount } from "wagmi";
+
+import EnsureChain from "@/components/EnsureChain";
+import Loader from "@/components/Loader";
+
+import CheckIcon from "@/assets/svg/check-circle.svg";
+
+import { cn } from "@/utils";
+import { errorToast, infoToast, successToast } from "@/utils/wrapWithToast";
+
+const pageLayoutClassName = clsx(
+ "flex flex-col gap-x-4 gap-y-12 px-4 py-12 md:px-8 lg:px-32",
+ "size-full items-center justify-center",
+ "md:justify-between lg:flex-row",
+);
+
+const Unsubscribe: React.FC = () => {
+ const { address } = useAccount();
+ const [IsUnsubscribed, setIsUnsubscribed] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+ const {
+ isFetchingUser,
+ isVerified,
+ isSigningIn,
+ isDeletingUser,
+ authoriseUser,
+ deleteUser,
+ userExists,
+ } = useAtlasProvider();
+ const prevIsFetchingUser = usePrevious(isFetchingUser);
+
+ useEffect(() => {
+ if (!address || !isVerified) {
+ setIsLoading(false);
+ return;
+ }
+
+ if (isFetchingUser) {
+ setIsLoading(true);
+ return;
+ }
+
+ if (prevIsFetchingUser) {
+ setIsLoading(false);
+ return;
+ }
+
+ const timeoutId = window.setTimeout(() => setIsLoading(false), 50);
+ return () => window.clearTimeout(timeoutId);
+ }, [address, isVerified, isFetchingUser, prevIsFetchingUser]);
+
+ const isAlreadyUnsubscribed =
+ !isLoading && Boolean(address) && isVerified && !userExists;
+ const showSuccess = IsUnsubscribed || isAlreadyUnsubscribed;
+
+ const handleUnsubscribe = useCallback(async () => {
+ if (!address) return;
+
+ if (!isVerified) {
+ infoToast("Signing in User...");
+ try {
+ await authoriseUser();
+ successToast("Signed In successfully!");
+ } catch (error) {
+ console.error(error);
+ if (error instanceof Error) {
+ errorToast(`Sign-In failed: ${error.message}`);
+ }
+ return;
+ }
+ }
+
+ infoToast("Unsubscribing ...");
+ try {
+ const res = await deleteUser();
+ if (!res) {
+ errorToast("Unsubscribe failed: Unknown error");
+ return;
+ }
+ setIsUnsubscribed(true);
+ successToast("You have been unsubscribed from notifications.");
+ } catch (error) {
+ console.error("Unsubscribe failed:", error);
+ if (error instanceof Error) {
+ errorToast(`Unsubscribe failed: ${error.message}`);
+ }
+ }
+ }, [address, isVerified, authoriseUser, deleteUser]);
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ {showSuccess ? (
+ <>
+
+
+
+ You have been unsubscribed
+
+
+ You will no longer receive notification emails from Kleros
+ products.
+
+
+
+
+
+
+ >
+ ) : (
+ <>
+
+
+ Unsubscribe from Notifications
+
+
+
+
+
+ >
+ )}
+
+ );
+};
+
+export default Unsubscribe;
diff --git a/src/assets/experiments/movies-dark.svg b/src/assets/experiments/movies-dark.svg
new file mode 100644
index 0000000..940d754
--- /dev/null
+++ b/src/assets/experiments/movies-dark.svg
@@ -0,0 +1,15 @@
+
diff --git a/src/assets/experiments/movies-light.svg b/src/assets/experiments/movies-light.svg
new file mode 100644
index 0000000..b5eb505
--- /dev/null
+++ b/src/assets/experiments/movies-light.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/src/assets/experiments/realt-dark.svg b/src/assets/experiments/realt-dark.svg
new file mode 100644
index 0000000..e491836
--- /dev/null
+++ b/src/assets/experiments/realt-dark.svg
@@ -0,0 +1,28 @@
+
\ No newline at end of file
diff --git a/src/assets/experiments/realt-light.svg b/src/assets/experiments/realt-light.svg
new file mode 100644
index 0000000..71513e7
--- /dev/null
+++ b/src/assets/experiments/realt-light.svg
@@ -0,0 +1,28 @@
+
\ No newline at end of file
diff --git a/src/assets/png/movies-banner.png b/src/assets/png/movies-banner.png
new file mode 100644
index 0000000..30a6c54
Binary files /dev/null and b/src/assets/png/movies-banner.png differ
diff --git a/src/assets/png/movies-r2-banner.png b/src/assets/png/movies-r2-banner.png
new file mode 100644
index 0000000..9493b75
Binary files /dev/null and b/src/assets/png/movies-r2-banner.png differ
diff --git a/src/assets/png/properties-banner.png b/src/assets/png/properties-banner.png
new file mode 100644
index 0000000..de5157d
Binary files /dev/null and b/src/assets/png/properties-banner.png differ
diff --git a/src/assets/svg/arrow-right.svg b/src/assets/svg/arrow-right.svg
new file mode 100644
index 0000000..8740832
--- /dev/null
+++ b/src/assets/svg/arrow-right.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/src/assets/svg/built-by-kleros.svg b/src/assets/svg/built-by-kleros.svg
new file mode 100644
index 0000000..9ef677a
--- /dev/null
+++ b/src/assets/svg/built-by-kleros.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/assets/svg/eye.svg b/src/assets/svg/eye.svg
new file mode 100644
index 0000000..da227c0
--- /dev/null
+++ b/src/assets/svg/eye.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/assets/svg/foresight-logo-navbar.svg b/src/assets/svg/foresight-logo-navbar.svg
new file mode 100644
index 0000000..283ecd0
--- /dev/null
+++ b/src/assets/svg/foresight-logo-navbar.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/assets/svg/homepage-overlay.svg b/src/assets/svg/homepage-overlay.svg
new file mode 100644
index 0000000..4b8cc70
--- /dev/null
+++ b/src/assets/svg/homepage-overlay.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/assets/svg/tag-category.svg b/src/assets/svg/tag-category.svg
new file mode 100644
index 0000000..4f2e277
--- /dev/null
+++ b/src/assets/svg/tag-category.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/src/components/ExperimentCard/index.tsx b/src/components/ExperimentCard/index.tsx
new file mode 100644
index 0000000..4b6cebf
--- /dev/null
+++ b/src/components/ExperimentCard/index.tsx
@@ -0,0 +1,267 @@
+"use client";
+
+import { useState } from "react";
+
+import clsx from "clsx";
+import { AnimatePresence, motion } from "framer-motion";
+import Image from "next/image";
+import Link from "next/link";
+import Countdown, { type CountdownRenderProps } from "react-countdown";
+
+import RealtDarkIcon from "@/assets/experiments/realt-dark.svg";
+import RealtLightIcon from "@/assets/experiments/realt-light.svg";
+import ArrowIcon from "@/assets/svg/arrow-right.svg";
+import TradingIcon from "@/assets/svg/chart-bar.svg";
+import CountdownIcon from "@/assets/svg/cronometer.svg";
+import TagIcon from "@/assets/svg/tag-category.svg";
+
+import { type ExperimentStatus, type IExperiment } from "@/consts/experiments";
+
+const IMAGE_HEIGHT_DEFAULT = 180;
+const IMAGE_HEIGHT_HOVERED = 80;
+
+const statusStyles: Record<
+ ExperimentStatus,
+ { label: string; className: string }
+> = {
+ live: {
+ label: "Live",
+ className: "bg-[#00c853] text-white",
+ },
+ ended: {
+ label: "Ended",
+ className:
+ "bg-white/80 text-gray-700 backdrop-blur-sm dark:bg-black/60 dark:text-gray-300",
+ },
+ "coming soon": {
+ label: "Coming Soon",
+ className: "bg-klerosUIComponentsPrimaryBlue text-white",
+ },
+};
+
+const iconMap: Record<
+ string,
+ | {
+ type: "image";
+ light: string;
+ dark: string;
+ width: number;
+ height: number;
+ }
+ | {
+ type: "svg";
+ light: React.FC
>;
+ dark: React.FC>;
+ }
+> = {
+ movie: {
+ type: "image",
+ light: "/experiment-icons/movie-light.png",
+ dark: "/experiment-icons/movie-dark.png",
+ width: 46,
+ height: 40,
+ },
+ realt: { type: "svg", light: RealtLightIcon, dark: RealtDarkIcon },
+};
+
+const countdownRenderer = ({
+ days,
+ hours,
+ minutes,
+ completed,
+}: CountdownRenderProps) => {
+ if (completed) {
+ return (
+
+ Ended
+
+ );
+ }
+ return (
+
+ {days > 0 && `${days}d `}
+ {hours > 0 && `${hours}h:`}
+ {minutes > 0 && `${minutes}m `}
+
+ );
+};
+
+export interface ExperimentCardProps extends IExperiment {
+ priority?: boolean;
+}
+
+const ExperimentCard: React.FC = ({
+ name,
+ question,
+ url,
+ icon,
+ banner,
+ countLabel,
+ tradingPeriod,
+ endTime,
+ status,
+ priority = false,
+}) => {
+ const [hovered, setHovered] = useState(false);
+ const icons = iconMap[icon];
+
+ return (
+ setHovered(true)}
+ onMouseLeave={() => setHovered(false)}
+ >
+
+
+
+
+
+
+
+ {statusStyles[status].label}
+
+
+
+
+
+
+
+ {name}
+
+
+ {question}
+
+
+
+
+
+ {countLabel}
+
+
+
+ {hovered ? (
+
+
+
+
+ Trading Period:
+
+
+ {tradingPeriod}
+
+
+
+
+
+ Countdown:
+
+
+
+
+ ) : null}
+
+
+
+
+ {icons?.type === "image" ? (
+ <>
+
+
+ >
+ ) : icons?.type === "svg" ? (
+ (() => {
+ const LightIcon = icons.light;
+ const DarkIcon = icons.dark;
+ return (
+ <>
+
+
+ >
+ );
+ })()
+ ) : null}
+
+
+
+
+
+ );
+};
+
+export default ExperimentCard;
diff --git a/src/components/layout/Header/Logo.tsx b/src/components/layout/Header/Logo.tsx
index 199e4db..4cf417c 100644
--- a/src/components/layout/Header/Logo.tsx
+++ b/src/components/layout/Header/Logo.tsx
@@ -1,45 +1,18 @@
"use client";
-import React, { useEffect, useState } from "react";
+import React from "react";
-import { useTheme } from "next-themes";
-
-import Image from "next/image";
import Link from "next/link";
-import _LogoDark from "@/assets/png/movies-logo-dark.png";
-import _Logo from "@/assets/png/movies-logo.png";
+import BuiltByKlerosLogo from "@/assets/svg/built-by-kleros.svg";
+import ForesightLogo from "@/assets/svg/foresight-logo-navbar.svg";
const Logo: React.FC = () => {
- const { resolvedTheme } = useTheme();
- const [mounted, setMounted] = useState(false);
-
- useEffect(() => {
- setMounted(true);
- }, []);
-
- if (!mounted) {
- return (
-
-
-
-
-
- );
- }
-
return (
-
-
-
+
+
+
+
);
};
diff --git a/src/components/layout/Header/Menu/Settings/Notifications/FormContactDetails/index.tsx b/src/components/layout/Header/Menu/Settings/Notifications/FormContactDetails/index.tsx
index 029a664..f8d74a6 100644
--- a/src/components/layout/Header/Menu/Settings/Notifications/FormContactDetails/index.tsx
+++ b/src/components/layout/Header/Menu/Settings/Notifications/FormContactDetails/index.tsx
@@ -1,7 +1,13 @@
import React, { useCallback, useEffect, useState } from "react";
import { useAtlasProvider } from "@kleros/kleros-app";
-import { Button, Form, TextField } from "@kleros/ui-components-library";
+import {
+ AlertMessage,
+ Button,
+ Form,
+ TextField,
+} from "@kleros/ui-components-library";
+import clsx from "clsx";
import { useAccount } from "wagmi";
import InfoCard from "@/components/InfoCard";
@@ -11,13 +17,17 @@ import { timeLeftUntil } from "@/utils/date";
import { errorToast, infoToast, successToast } from "@/utils/wrapWithToast";
import EmailVerificationInfo from "./EmailVerificationInfo";
-import clsx from "clsx";
// https://www.w3.org/TR/2012/WD-html-markup-20120329/input.email.html#input.email.attrs.value.single
export const EMAIL_REGEX =
// eslint-disable-next-line max-len
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+const unsubscribeButtonClassName = clsx(
+ "bg-klerosUIComponentsError! hover:bg-klerosUIComponentsError! hover:opacity-75",
+ "border-klerosUIComponentsError! [&_.button-text]:text-wrap! [&_.button-text]:text-white!",
+);
+
type FormDetailsParams = {
togglePopup: () => void;
isPostPrediction?: boolean;
@@ -29,6 +39,7 @@ const FormContactDetails: React.FC
= ({
infoText,
}) => {
const [emailInput, setEmailInput] = useState("");
+ const [isConfirmingUnsubscribe, setIsConfirmingUnsubscribe] = useState(false);
const { address } = useAccount();
const {
user,
@@ -37,6 +48,8 @@ const FormContactDetails: React.FC = ({
addUser,
updateEmail,
isUpdatingUser,
+ isDeletingUser,
+ deleteUser,
userExists,
isVerified,
authoriseUser,
@@ -72,6 +85,27 @@ const FormContactDetails: React.FC = ({
}
}, [authoriseUser]);
+ const handleConfirmUnsubscribe = useCallback(async () => {
+ if (isUndefined(address)) return;
+
+ infoToast("Unsubscribing ...");
+ deleteUser()
+ .then((res) => {
+ if (!res) {
+ errorToast("Unsubscribe failed: Unknown error");
+ return;
+ }
+ setEmailInput("");
+ setIsConfirmingUnsubscribe(false);
+ successToast("You have been unsubscribed from notifications.");
+ togglePopup();
+ })
+ .catch((err) => {
+ console.error("Unsubscribe failed:", err);
+ errorToast(`Unsubscribe failed: ${err?.message || "Unknown error"}`);
+ });
+ }, [address, deleteUser, togglePopup]);
+
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!address || isFetchingUser) {
@@ -122,6 +156,7 @@ const FormContactDetails: React.FC = ({
isAddingUser ||
isFetchingUser ||
isUpdatingUser ||
+ isDeletingUser ||
!isEmailUpdateable ||
isSigningIn
}
@@ -174,13 +209,51 @@ const FormContactDetails: React.FC = ({
}
/>
) : null}
+ {!isPostPrediction && isConfirmingUnsubscribe ? (
+
+ ) : null}
{isPostPrediction ? (
{SubscribeButton}
) : (
- {SubscribeButton}
+
+ {isConfirmingUnsubscribe ? (
+ <>
+
+
)}
diff --git a/src/components/layout/HomepageHeader.tsx b/src/components/layout/HomepageHeader.tsx
new file mode 100644
index 0000000..f600750
--- /dev/null
+++ b/src/components/layout/HomepageHeader.tsx
@@ -0,0 +1,52 @@
+"use client";
+
+import clsx from "clsx";
+import dynamic from "next/dynamic";
+import { useToggle } from "react-use";
+
+import LightButton from "@/components/LightButton";
+import ThemeToggle from "@/components/ThemeToggle";
+
+import HelpIcon from "@/assets/menu-icons/help.svg";
+
+import Logo from "./Header/Logo";
+
+const Help = dynamic(() => import("./Header/Menu/Help"), { ssr: false });
+
+const HomepageHeader: React.FC = () => {
+ const [isHelpOpen, toggleIsHelpOpen] = useToggle(false);
+
+ return (
+
+
+
+
+
+ }
+ onPress={toggleIsHelpOpen}
+ />
+
+
+
+
+ {isHelpOpen ? (
+
+ ) : null}
+
+ );
+};
+
+export default HomepageHeader;
diff --git a/src/consts/experiments.ts b/src/consts/experiments.ts
new file mode 100644
index 0000000..ffe9825
--- /dev/null
+++ b/src/consts/experiments.ts
@@ -0,0 +1,43 @@
+export type ExperimentStatus = "live" | "ended" | "coming soon";
+
+export interface IExperiment {
+ slug: string;
+ name: string;
+ question: string;
+ url: string;
+ icon: string;
+ banner: string;
+ countLabel: string;
+ tradingPeriod: string;
+ endTime: number;
+ status: ExperimentStatus;
+}
+
+export const experiments: IExperiment[] = [
+ {
+ slug: "movies-s2",
+ name: "Movies Experiment - Session 2",
+ question:
+ "If watched, what percentile score would Clément give to the movie?",
+ url: "https://movies-r2.foresight.kleros.io",
+ icon: "movie",
+ banner: "/experiment-banners/movies-r2-banner.webp",
+ countLabel: "20 Movies",
+ tradingPeriod: "Until July 5th 00:00 UTC",
+ endTime: 1783209600,
+ status: "live",
+ },
+ {
+ slug: "movies",
+ name: "Movies Experiment",
+ question:
+ "If watched, what percentile score would Clément give to the movie?",
+ url: "https://movies.foresight.kleros.io",
+ icon: "movie",
+ banner: "/experiment-banners/movies-banner.webp",
+ countLabel: "16 Movies",
+ tradingPeriod: "Until Friday 3rd 18:00 UTC",
+ endTime: 1775239200,
+ status: "ended",
+ },
+];
diff --git a/src/context/Web3Context.tsx b/src/context/Web3Context.tsx
index 6807ac2..888881e 100644
--- a/src/context/Web3Context.tsx
+++ b/src/context/Web3Context.tsx
@@ -2,7 +2,7 @@
import React, { type ReactNode } from "react";
-import { AtlasProvider, Products } from "@kleros/kleros-app";
+import { AtlasProvider, SignupProduct } from "@kleros/kleros-app";
import { gnosis } from "@reown/appkit/networks";
import { createAppKit } from "@reown/appkit/react";
import { configureRpcProviders } from "@swapr/sdk";
@@ -50,10 +50,10 @@ createAppKit({
interface IWeb3Context {
children: ReactNode;
- cookies: string | null;
+ cookies?: string | null;
}
-const Web3Context: React.FC = ({ children, cookies }) => {
+const Web3Context: React.FC = ({ children, cookies = null }) => {
const initialState = cookieToInitialState(
wagmiAdapter.wagmiConfig as Config,
cookies,
@@ -72,7 +72,7 @@ const Web3Context: React.FC = ({ children, cookies }) => {
diff --git a/yarn.lock b/yarn.lock
index 0db5c2a..33abdcf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3444,9 +3444,9 @@ __metadata:
languageName: node
linkType: hard
-"@kleros/kleros-app@npm:^2.2.2":
- version: 2.2.2
- resolution: "@kleros/kleros-app@npm:2.2.2"
+"@kleros/kleros-app@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "@kleros/kleros-app@npm:3.0.1"
dependencies:
jose: "npm:^5.9.6"
peerDependencies:
@@ -3457,7 +3457,7 @@ __metadata:
react-dom: ^18.3.1
viem: ^2.24.1
wagmi: ^2.14.15
- checksum: 10c0/96712b793b761127354ed967d0b88b3d14f880c4d00019af8d3d234d66ae9714ee51a505cd619724b348a4e66ef30e0faffcb062e83a8ebd8115ec47f591fe1b
+ checksum: 10c0/0b3f3f1ca5b0f495e45c33265025ce9bfbca285b72eea5d98e73c6ab9db12b460de0667213db53db8e3bf296988af0a1276ec919da0458c40f79052c5a013035
languageName: node
linkType: hard
@@ -11110,7 +11110,7 @@ __metadata:
"@graphql-codegen/typescript": "npm:^5.0.2"
"@graphql-codegen/typescript-graphql-request": "npm:^6.3.0"
"@graphql-codegen/typescript-operations": "npm:^5.0.2"
- "@kleros/kleros-app": "npm:^2.2.2"
+ "@kleros/kleros-app": "npm:^3.0.1"
"@kleros/ui-components-library": "npm:^3.7.0"
"@reown/appkit": "npm:^1.7.11"
"@reown/appkit-adapter-wagmi": "npm:^1.7.11"