-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testnets #128
Testnets #128
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
"use client"; | ||
|
||
import { useEffectOnce } from "@legendapp/state/react"; | ||
import Accordion from "components/Accordion"; | ||
import Arrow from "components/Arrow"; | ||
import BulletedNumber from "components/BulletedNumber"; | ||
import ExternalLink from "components/ExternalLink"; | ||
import Field from "components/Field"; | ||
import Identicon from "components/Identicon"; | ||
import Modal from "components/Modal"; | ||
|
@@ -18,8 +20,10 @@ import { APIPoH, StakeMultipliers } from "contracts/apis/APIPoH"; | |
import usePoHWrite from "contracts/hooks/usePoHWrite"; | ||
import { RequestQuery } from "generated/graphql"; | ||
import { useLoading } from "hooks/useLoading"; | ||
import Image from "next/image"; | ||
import { useMemo, useRef, useState } from "react"; | ||
import { toast } from "react-toastify"; | ||
import { camelToTitle } from "utils/case"; | ||
import { eth2Wei, formatEth } from "utils/misc"; | ||
import { Address } from "viem"; | ||
|
||
|
@@ -47,6 +51,8 @@ const SideFunding: React.FC<SideFundingProps> = ({ | |
loosingSideHasEnd, | ||
}) => { | ||
const title = side === SideEnum.claimer ? "Claimer" : "Challenger"; | ||
const shrunkAddress: string = | ||
requester.substring(0, 6) + " ... " + requester.slice(-4); | ||
const [requesterInput, setRequesterInput] = useState(0n); | ||
const loading = useLoading(); | ||
const errorRef = useRef(false); | ||
|
@@ -78,43 +84,41 @@ const SideFunding: React.FC<SideFundingProps> = ({ | |
); | ||
|
||
return ( | ||
<Accordion className="mb-4" title={title}> | ||
<div className="w-full border p-4"> | ||
<div className="mb-2 flex gap-2"> | ||
<Identicon diameter={32} address={requester} /> | ||
<div className="flex flex-col"> | ||
<span className="text-sm">{requester}</span> | ||
<span className="text-xs">{title}</span> | ||
</div> | ||
</div> | ||
<div className="flex gap-1"> | ||
<Field | ||
type="number" | ||
onChange={(v) => setRequesterInput(eth2Wei(+v.target.value))} | ||
/> | ||
<button | ||
className={`gradient rounded px-4 text-white ${ | ||
!contributor || errorRef.current || loosingSideHasEnd | ||
? "cursor-not-allowed opacity-50" | ||
: "" | ||
}`} | ||
disabled={!contributor || errorRef.current || loosingSideHasEnd} | ||
onClick={async () => { | ||
prepareFundAppeal({ | ||
args: [arbitrator as Address, BigInt(disputeId), side], | ||
value: requesterInput, | ||
}); | ||
}} | ||
> | ||
Fund | ||
</button> | ||
<div className="w-full border p-4"> | ||
<div className="mb-2 flex gap-2"> | ||
<Identicon diameter={32} address={requester} /> | ||
<div className="flex flex-col"> | ||
<span>{title}</span> | ||
<span className="text-sm">{shrunkAddress}</span> | ||
</div> | ||
<Progress | ||
value={valueProgress} | ||
label={`${formatEth(requesterFunds)} ${unit} of ${formatEth(appealCost)} ${unit}`} | ||
</div> | ||
<div className="flex gap-1"> | ||
<Field | ||
type="number" | ||
onChange={(v) => setRequesterInput(eth2Wei(+v.target.value))} | ||
/> | ||
<button | ||
className={`gradient rounded px-4 text-white ${ | ||
!contributor || errorRef.current || loosingSideHasEnd | ||
? "cursor-not-allowed opacity-50" | ||
: "" | ||
}`} | ||
disabled={!contributor || errorRef.current || loosingSideHasEnd} | ||
onClick={async () => { | ||
prepareFundAppeal({ | ||
args: [arbitrator as Address, BigInt(disputeId), side], | ||
value: requesterInput, | ||
}); | ||
}} | ||
> | ||
Fund | ||
</button> | ||
</div> | ||
</Accordion> | ||
<Progress | ||
value={valueProgress} | ||
label={`${formatEth(requesterFunds)} ${unit} out of ${formatEth(appealCost)} ${unit}`} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
|
@@ -131,6 +135,8 @@ interface AppealProps { | |
currentChallenge: ArrayElement< | ||
NonNullable<NonNullable<RequestQuery>["request"]>["challenges"] | ||
>; | ||
revocation: boolean; | ||
expired: boolean; | ||
} | ||
|
||
const Appeal: React.FC<AppealProps> = ({ | ||
|
@@ -144,6 +150,8 @@ const Appeal: React.FC<AppealProps> = ({ | |
claimer, | ||
challenger, | ||
currentChallenge, | ||
revocation, | ||
expired, | ||
}) => { | ||
const [totalClaimerCost, setTotalClaimerCost] = useState(0n); | ||
const [totalChallengerCost, setTotalChallengerCost] = useState(0n); | ||
|
@@ -297,62 +305,132 @@ const Appeal: React.FC<AppealProps> = ({ | |
<h1 className="mb-4 text-xl"> | ||
Appeal the decision: {formatedCurrentRuling} | ||
</h1> | ||
<p className="txt"> | ||
In order to appeal the decision, you need to fully fund the | ||
crowdfunding deposit. The dispute will be sent to the jurors when the | ||
full deposit is reached. Note that if the previous round loser funds | ||
its side, the previous round winner should also fully fund its side, | ||
in order not to lose the case. | ||
</p> | ||
<br /> | ||
<h1 className="mb-4 text-xl">Appeal timeframes</h1> | ||
<p className="txt"> | ||
Appeal timeframe ends | ||
<TimeAgo time={parseInt(String(period[1]))} /> | ||
</p> | ||
{loosingSideHasEnd ? ( | ||
<p className="txt"> | ||
Loosing side ended | ||
<TimeAgo time={loosingSideDeadline} /> | ||
</p> | ||
) : ( | ||
<p className="txt"> | ||
Loosing side ends | ||
<TimeAgo time={loosingSideDeadline} /> | ||
</p> | ||
)} | ||
<br /> | ||
<SideFunding | ||
side={SideEnum.claimer} | ||
disputeId={disputeId} | ||
arbitrator={arbitrator!} | ||
contributor={contributor} | ||
requester={claimer} | ||
requesterFunds={claimerFunds} | ||
appealCost={totalClaimerCost} | ||
chainId={chainId} | ||
loosingSideHasEnd={ | ||
currentRulingFormatted === SideEnum.challenger | ||
? loosingSideHasEnd | ||
: false | ||
} | ||
/> | ||
<div className="gradient-border relative overflow-hidden"> | ||
<div className="absolute inset-0 bg-gradient-to-r from-[#FF9966] to-[#FF8CA9]"></div> | ||
<div className="absolute inset-0 border-2 border-solid border-transparent"></div> | ||
<div className="mb-1"></div> | ||
</div> | ||
<div className="container mt-4"> | ||
<div className="flex items-center"> | ||
<BulletedNumber number={1} /> | ||
{!revocation ? ( | ||
<span className="mx-2 mt-2 text-sm"> | ||
The profile was challenged for{" "} | ||
<strong className="text-status-challenged"> | ||
{camelToTitle( | ||
currentChallenge.reason.id, | ||
revocation, | ||
expired, | ||
)} | ||
</strong> | ||
. | ||
</span> | ||
) : ( | ||
<span className="mx-2 mt-2 text-sm"> | ||
The profile was challenged. | ||
</span> | ||
)} | ||
</div> | ||
<div className="flex items-center"> | ||
<BulletedNumber number={2} /> | ||
|
||
<span className="mx-2 mt-2 text-sm"> | ||
Independent jurors evaluated the evidence, policy compliance, and | ||
voted in favor of:{" "} | ||
{currentRulingFormatted === SideEnum.challenger | ||
? "Challenger" | ||
: currentRulingFormatted === SideEnum.claimer | ||
? "Claimer" | ||
: "Shared"} | ||
. | ||
<div className="mt-[-1.4rem]"> | ||
<ExternalLink | ||
className="text-orange mx-2 flex flex-row flex-wrap justify-end gap-x-[8px] text-sm font-semibold leading-none hover:text-orange-500 md:gap-2 lg:gap-3" | ||
href={`https://resolve.kleros.io/cases/${currentChallenge.disputeId}`} | ||
> | ||
<span className="mt-1 text-right text-sm font-semibold leading-none"> | ||
Check how the jury voted | ||
</span> | ||
<Arrow /> | ||
</ExternalLink> | ||
</div> | ||
</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<BulletedNumber number={3} current={!loosingSideHasEnd} /> | ||
{loosingSideHasEnd ? ( | ||
<span className="mx-2 mt-2 text-sm"> | ||
The losing party's appeal time ended | ||
<TimeAgo time={loosingSideDeadline} />. | ||
</span> | ||
) : ( | ||
<span className="mx-2 mt-2 text-sm"> | ||
The losing party's appeal time ends | ||
<TimeAgo time={loosingSideDeadline} />. | ||
</span> | ||
)} | ||
</div> | ||
<div className="flex items-center"> | ||
<BulletedNumber number={4} current /> | ||
<span className="mx-2 mt-2 text-sm"> | ||
Appeal timeframe ends | ||
<TimeAgo time={parseInt(String(period[1]))} />. | ||
</span> | ||
</div> | ||
<div className="mb-4 mt-4"> | ||
<span className="text-sm"> | ||
In order to appeal the decision, you need to fully fund the | ||
crowdfunding deposit. The dispute will be sent to the jurors when | ||
the full deposit is reached. Note that if the previous round loser | ||
funds its side, the previous round winner should also fully fund | ||
its side, in order not to lose the case. | ||
</span> | ||
<div className="mt-4 flex items-center opacity-75"> | ||
<Image | ||
alt="warning" | ||
src="/logo/exclamation.svg" | ||
height={24} | ||
width={24} | ||
/> | ||
<span className="mx-2 text-sm opacity-75"> | ||
External contributors can also crowdfund the appeal. | ||
</span> | ||
</div> | ||
</div> | ||
</div> | ||
<br /> | ||
<SideFunding | ||
side={SideEnum.challenger} | ||
disputeId={disputeId} | ||
arbitrator={arbitrator!} | ||
contributor={contributor} | ||
requester={challenger} | ||
requesterFunds={challengerFunds} | ||
appealCost={totalChallengerCost} | ||
chainId={chainId} | ||
loosingSideHasEnd={ | ||
currentRulingFormatted === SideEnum.claimer | ||
? loosingSideHasEnd | ||
: false | ||
} | ||
/> | ||
<div className="flex items-center"> | ||
<SideFunding | ||
side={SideEnum.claimer} | ||
disputeId={disputeId} | ||
arbitrator={arbitrator!} | ||
contributor={contributor} | ||
requester={claimer} | ||
requesterFunds={claimerFunds} | ||
appealCost={totalClaimerCost} | ||
chainId={chainId} | ||
loosingSideHasEnd={ | ||
currentRulingFormatted === SideEnum.challenger | ||
? loosingSideHasEnd | ||
: false | ||
} | ||
/> | ||
<SideFunding | ||
side={SideEnum.challenger} | ||
disputeId={disputeId} | ||
arbitrator={arbitrator!} | ||
contributor={contributor} | ||
requester={challenger} | ||
requesterFunds={challengerFunds} | ||
appealCost={totalChallengerCost} | ||
chainId={chainId} | ||
loosingSideHasEnd={ | ||
currentRulingFormatted === SideEnum.claimer | ||
? loosingSideHasEnd | ||
: false | ||
} | ||
/> | ||
</div> | ||
Comment on lines
+402
to
+433
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify funding section conditional logic The nested ternary operators for +const isLoosingSide = (side: SideEnum, currentRuling: SideEnum) => {
+ return (side === SideEnum.claimer && currentRuling === SideEnum.challenger) ||
+ (side === SideEnum.challenger && currentRuling === SideEnum.claimer);
+};
<SideFunding
// ... other props
- loosingSideHasEnd={
- currentRulingFormatted === SideEnum.challenger
- ? loosingSideHasEnd
- : false
- }
+ loosingSideHasEnd={isLoosingSide(SideEnum.claimer, currentRulingFormatted) && loosingSideHasEnd}
/>
|
||
</div> | ||
</Modal> | ||
) : null; | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,21 +1,23 @@ | ||||||||||||||||||||||||||
"use client"; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import Modal from "components/Modal"; | ||||||||||||||||||||||||||
import InfoIcon from "icons/info.svg"; | ||||||||||||||||||||||||||
import Image from "next/image"; | ||||||||||||||||||||||||||
import Modal from "components/Modal"; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
interface InfoProps { | ||||||||||||||||||||||||||
nbRequests: number; | ||||||||||||||||||||||||||
label: string; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export default function Info({ nbRequests }: InfoProps) { | ||||||||||||||||||||||||||
export default function Info({ nbRequests, label }: InfoProps) { | ||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||
<Modal | ||||||||||||||||||||||||||
formal | ||||||||||||||||||||||||||
className="flex flex-col p-8" | ||||||||||||||||||||||||||
trigger={ | ||||||||||||||||||||||||||
<span className="flex cursor-pointer gap-x-[4px] text-slate-500"> | ||||||||||||||||||||||||||
<InfoIcon className="h-6 w-6 stroke-slate-500 stroke-2" /> | ||||||||||||||||||||||||||
<span className="flex cursor-pointer gap-x-[4px] text-slate-500 hover:text-slate-700"> | ||||||||||||||||||||||||||
{label} | ||||||||||||||||||||||||||
<InfoIcon className="h-6 w-6 stroke-slate-500 stroke-2 hover:stroke-slate-700" /> | ||||||||||||||||||||||||||
</span> | ||||||||||||||||||||||||||
Comment on lines
+18
to
21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider improving accessibility of the modal trigger. The current implementation has accessibility limitations:
Consider applying these improvements: - <span className="flex cursor-pointer gap-x-[4px] text-slate-500 hover:text-slate-700">
+ <button
+ type="button"
+ className="flex items-center gap-x-[4px] text-slate-500 hover:text-slate-700"
+ aria-label={`Information about ${label}`}
+ >
{label}
<InfoIcon className="h-6 w-6 stroke-slate-500 stroke-2 hover:stroke-slate-700" />
- </span>
+ </button> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -361,17 +361,13 @@ export default async function Request({ params }: PageProps) { | |
</div> | ||
<div className="mb-4 h-1 w-full border-b"></div> | ||
<div className="mb-2 flex flex-col-reverse justify-between md:flex-row"> | ||
<div className="flex items-center"> | ||
<span className="flex items-center text-slate-400">POH ID</span> | ||
<div className="mx-[10px]"> | ||
<Info | ||
nbRequests={ | ||
+request.humanity.nbRequests + | ||
+request.humanity.nbLegacyRequests | ||
} | ||
/> | ||
</div> | ||
</div> | ||
<Info | ||
label="POH ID" | ||
nbRequests={ | ||
+request.humanity.nbRequests + | ||
+request.humanity.nbLegacyRequests | ||
} | ||
/> | ||
</div> | ||
<div className="text-orange mb-8 flex flex-wrap gap-x-[8px] gap-y-[8px] font-medium"> | ||
<Link | ||
|
@@ -432,10 +428,15 @@ export default async function Request({ params }: PageProps) { | |
className="text-primaryText ml-2" | ||
> | ||
<div className="text-primaryText group relative flex py-[8px]"> | ||
Policy in force at submission | ||
<div className="\\ \\ \\ \\ \\ \\ \\ \\ outline-color: #E5E5E5 \\ bg-whiteBackground text-secondaryText invisible absolute left-1/2 z-10 m-4 mx-auto w-[260px] flex-shrink-0 -translate-x-1/2 transform place-content-center content-between rounded-[3px] border-[1px] border-[solid] bg-[var(--Light-Mode-White-background,_#FFF)] p-[8px] text-justify text-[14px] font-normal not-italic leading-[normal] outline-black transition-opacity ease-in-out [box-shadow:0px_2px_3px_0px_rgba(0,_0,_0,_0.06)] group-hover:visible md:w-[400px]"> | ||
<Image | ||
alt="warning" | ||
src="/logo/exclamation.svg" | ||
height={24} | ||
width={24} | ||
/> | ||
Policy in force at submission | ||
<div className="outline-color: #E5E5E5 bg-whiteBackground text-secondaryText invisible absolute left-1/2 z-10 m-4 mx-auto w-[260px] flex-shrink-0 -translate-x-1/2 transform place-content-center content-between rounded-[3px] border-[1px] border-[solid] bg-[var(--Light-Mode-White-background,_#FFF)] p-[8px] text-justify text-[14px] font-normal not-italic leading-[normal] outline-black transition-opacity ease-in-out [box-shadow:0px_2px_3px_0px_rgba(0,_0,_0,_0.06)] group-hover:visible md:w-[400px]"> | ||
Comment on lines
+431
to
+438
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider improving tooltip accessibility and readability. While the warning icon and tooltip provide valuable context about policy versioning, consider these improvements:
Consider these enhancements: -<div className="text-primaryText group relative flex py-[8px]">
+<div className="text-primaryText group relative flex py-[8px]"
+ role="button"
+ tabIndex={0}
+ onClick={() => setTooltipVisible(!tooltipVisible)}
+ onKeyPress={(e) => e.key === 'Enter' && setTooltipVisible(!tooltipVisible)}>
<Image
alt="warning"
src="/logo/exclamation.svg"
height={24}
width={24}
/>
Policy in force at submission
- <div className="outline-color: #E5E5E5 bg-whiteBackground text-secondaryText invisible absolute left-1/2 z-10 m-4 mx-auto w-[260px] flex-shrink-0 -translate-x-1/2 transform place-content-center content-between rounded-[3px] border-[1px] border-[solid] bg-[var(--Light-Mode-White-background,_#FFF)] p-[8px] text-justify text-[14px] font-normal not-italic leading-[normal] outline-black transition-opacity ease-in-out [box-shadow:0px_2px_3px_0px_rgba(0,_0,_0,_0.06)] group-hover:visible md:w-[400px]">
+ <div className={`outline-color: #E5E5E5 bg-whiteBackground text-secondaryText absolute left-1/2 z-10 m-4 mx-auto w-[260px] flex-shrink-0 -translate-x-1/2 transform place-content-center content-between rounded-[3px] border-[1px] border-[solid] bg-[var(--Light-Mode-White-background,_#FFF)] p-[8px] text-[14px] font-normal not-italic leading-[normal] outline-black transition-opacity ease-in-out [box-shadow:0px_2px_3px_0px_rgba(0,_0,_0,_0.06)] md:w-[400px] ${tooltipVisible ? 'visible' : 'invisible'}`}
+ role="tooltip">
<span>
- This is the policy that was in effect when this submission was made. Why is this important? Policies may change over time, and it's crucial to know the policy that was in force at the time of a submission before challenging or removing a profile. If you challenge this submission, this version of the policy will be enforced by Kleros jurors if the case goes to arbitration. Also, if you revoke this profile citing "incorrect submission," but the submission complied with this policy, your revocation request may be rejected, and you may lose your deposit.
+ <p className="mb-2"><strong>Why is this important?</strong></p>
+ <p className="mb-2">This is the policy that was in effect when this submission was made. Policies may change over time, and it's crucial to know the applicable policy before challenging or removing a profile.</p>
+ <p className="mb-2">If you challenge this submission, this version of the policy will be enforced by Kleros jurors during arbitration.</p>
+ <p>Note: Revoking this profile for "incorrect submission" when it complied with this policy may result in rejection and deposit loss.</p>
</span>
</div>
</div> You'll need to add state management at the component level: const [tooltipVisible, setTooltipVisible] = useState(false); |
||
<span> | ||
{/* (Policy in force since {new Date(policyUpdate * 1000).toDateString()}) */} | ||
This is the policy that was in effect when this | ||
submission was made. Why is this important? Policies | ||
may change over time, and it's crucial to know the | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider simplifying gradient border implementation
The gradient border implementation could be simplified using a single div with border-image.
📝 Committable suggestion