Initial commit with 🏗️ create-eth @ 2.0.4
This commit is contained in:
260
packages/nextjs/components/oracle/optimistic/AssertionModal.tsx
Normal file
260
packages/nextjs/components/oracle/optimistic/AssertionModal.tsx
Normal file
@@ -0,0 +1,260 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { AssertionWithIdAndState } from "../types";
|
||||
import { Address } from "@scaffold-ui/components";
|
||||
import { formatEther } from "viem";
|
||||
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
|
||||
import { useChallengeState } from "~~/services/store/challengeStore";
|
||||
import { ZERO_ADDRESS } from "~~/utils/scaffold-eth/common";
|
||||
|
||||
const getStateName = (state: number) => {
|
||||
switch (state) {
|
||||
case 0:
|
||||
return "Invalid";
|
||||
case 1:
|
||||
return "Asserted";
|
||||
case 2:
|
||||
return "Proposed";
|
||||
case 3:
|
||||
return "Disputed";
|
||||
case 4:
|
||||
return "Settled";
|
||||
case 5:
|
||||
return "Expired";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to format timestamp to UTC
|
||||
const formatTimestamp = (timestamp: bigint | string | number) => {
|
||||
const timestampNumber = Number(timestamp);
|
||||
const date = new Date(timestampNumber * 1000); // Convert from seconds to milliseconds
|
||||
return date.toLocaleString();
|
||||
};
|
||||
|
||||
const Description = ({ assertion }: { assertion: AssertionWithIdAndState }) => {
|
||||
return (
|
||||
<div className="bg-base-200 p-4 rounded-lg space-y-2 mb-4">
|
||||
<div>
|
||||
<span className="font-bold">AssertionId:</span> {assertion.assertionId}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-bold">Description:</span> {assertion.description}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-bold">Bond:</span> {formatEther(assertion.bond)} ETH
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-bold">Reward:</span> {formatEther(assertion.reward)} ETH
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-bold">Start Time:</span>
|
||||
<span className="text-sm"> UTC: {formatTimestamp(assertion.startTime)}</span>
|
||||
<span className="text-sm"> Timestamp: {assertion.startTime}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-bold">End Time:</span>
|
||||
<span className="text-sm"> UTC: {formatTimestamp(assertion.endTime)}</span>
|
||||
<span className="text-sm"> Timestamp: {assertion.endTime}</span>
|
||||
</div>
|
||||
|
||||
{assertion.proposer !== ZERO_ADDRESS && (
|
||||
<div>
|
||||
<span className="font-bold">Proposed Outcome:</span> {assertion.proposedOutcome ? "True" : "False"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{assertion.proposer !== ZERO_ADDRESS && (
|
||||
<div>
|
||||
<span className="font-bold">Proposer:</span>{" "}
|
||||
<Address address={assertion.proposer} format="short" onlyEnsOrAddress disableAddressLink size="sm" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{assertion.disputer !== ZERO_ADDRESS && (
|
||||
<div>
|
||||
<span className="font-bold">Disputer:</span>{" "}
|
||||
<Address address={assertion.disputer} format="short" onlyEnsOrAddress disableAddressLink size="sm" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const AssertionModal = () => {
|
||||
const [isActionPending, setIsActionPending] = useState(false);
|
||||
const { refetchAssertionStates, openAssertion, closeAssertionModal } = useChallengeState();
|
||||
|
||||
const isOpen = !!openAssertion;
|
||||
|
||||
const { writeContractAsync: writeOOContractAsync } = useScaffoldWriteContract({
|
||||
contractName: "OptimisticOracle",
|
||||
});
|
||||
|
||||
const { writeContractAsync: writeDeciderContractAsync } = useScaffoldWriteContract({
|
||||
contractName: "Decider",
|
||||
});
|
||||
|
||||
const handleAction = async (args: any) => {
|
||||
if (!openAssertion) return;
|
||||
|
||||
try {
|
||||
setIsActionPending(true);
|
||||
if (args.functionName === "settleDispute") {
|
||||
await writeDeciderContractAsync(args);
|
||||
} else {
|
||||
await writeOOContractAsync(args);
|
||||
}
|
||||
refetchAssertionStates();
|
||||
closeAssertionModal();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setIsActionPending(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!openAssertion) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<input type="checkbox" id="challenge-modal" className="modal-toggle" checked={isOpen} readOnly />
|
||||
<label htmlFor="challenge-modal" className="modal cursor-pointer" onClick={closeAssertionModal}>
|
||||
<label
|
||||
className="modal-box relative max-w-2xl w-full bg-base-100"
|
||||
htmlFor=""
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
{/* dummy input to capture event onclick on modal box */}
|
||||
<input className="h-0 w-0 absolute top-0 left-0" />
|
||||
|
||||
{/* Close button */}
|
||||
<button onClick={closeAssertionModal} className="btn btn-ghost btn-sm btn-circle absolute right-3 top-3">
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Modal Content */}
|
||||
<div className="">
|
||||
{/* Header with Current State */}
|
||||
<div className="text-center mb-6">
|
||||
<h2 className="text-lg">
|
||||
Current State: <span className="font-bold">{getStateName(openAssertion.state)}</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<Description assertion={openAssertion} />
|
||||
|
||||
{openAssertion.state === 1 && (
|
||||
<>
|
||||
{/* Proposed Outcome Section */}
|
||||
<div className="rounded-lg p-4">
|
||||
<div className="flex justify-center mb-4">
|
||||
<span className="font-medium">Propose Outcome</span>
|
||||
</div>
|
||||
{isActionPending && <span className="loading loading-spinner loading-xs"></span>}
|
||||
|
||||
<div className="flex justify-center gap-4">
|
||||
<button
|
||||
className="btn btn-primary flex-1"
|
||||
onClick={() =>
|
||||
handleAction({
|
||||
functionName: "proposeOutcome",
|
||||
args: [BigInt(openAssertion.assertionId), true],
|
||||
value: openAssertion.bond,
|
||||
})
|
||||
}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
True
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary flex-1"
|
||||
onClick={() =>
|
||||
handleAction({
|
||||
functionName: "proposeOutcome",
|
||||
args: [BigInt(openAssertion.assertionId), false],
|
||||
value: openAssertion.bond,
|
||||
})
|
||||
}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
False
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{openAssertion.state === 2 && (
|
||||
<div className="rounded-lg p-4">
|
||||
<div className="flex justify-center mb-4">
|
||||
<span className="font-medium">Submit Dispute</span>
|
||||
</div>
|
||||
|
||||
{isActionPending && <span className="loading loading-spinner loading-xs"></span>}
|
||||
|
||||
<div className="flex justify-center gap-4">
|
||||
<button
|
||||
className="btn btn-primary flex-1"
|
||||
onClick={() =>
|
||||
handleAction({
|
||||
functionName: "disputeOutcome",
|
||||
args: [BigInt(openAssertion.assertionId)],
|
||||
value: openAssertion.bond,
|
||||
})
|
||||
}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
{!openAssertion.proposedOutcome ? "True" : "False"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{openAssertion.state === 3 && (
|
||||
<div className="rounded-lg p-4">
|
||||
<div className="flex flex-col items-center gap-2 mb-4">
|
||||
<span className="text-2xl font-medium">Impersonate Decider</span>
|
||||
<span className="font-medium">Resolve Answer to</span>
|
||||
</div>
|
||||
{isActionPending && <span className="loading loading-spinner loading-xs"></span>}
|
||||
|
||||
<div className="flex justify-center gap-4">
|
||||
<button
|
||||
className="btn btn-primary flex-1"
|
||||
onClick={() =>
|
||||
handleAction({
|
||||
functionName: "settleDispute",
|
||||
args: [BigInt(openAssertion.assertionId), true],
|
||||
})
|
||||
}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
True
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary flex-1"
|
||||
onClick={() =>
|
||||
handleAction({
|
||||
functionName: "settleDispute",
|
||||
args: [BigInt(openAssertion.assertionId), false],
|
||||
})
|
||||
}
|
||||
disabled={isActionPending}
|
||||
>
|
||||
False
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</label>
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user