Skip to content

Commit b18236e

Browse files
Merge pull request #52 from BuidlGuidl/fix/minor-fe
Fix/minor fe fixes
2 parents bbd9049 + 19bbfc9 commit b18236e

File tree

5 files changed

+76
-33
lines changed

5 files changed

+76
-33
lines changed

packages/hardhat/deploy/00_deploy_whitelist.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ const deployWhitelistOracleContracts: DeployFunction = async function (hre: Hard
1111
const { deployer } = await hre.getNamedAccounts();
1212
const { deploy } = hre.deployments;
1313
const { viem } = hre;
14+
// Set your own address here
15+
const whitelistContractNewOwner = deployer;
1416

1517
const publicClient = await viem.getPublicClient();
1618

1719
console.log("Deploying WhitelistOracle contracts...");
18-
const whitelistContractOwner = deployer;
1920

2021
// Get 10 wallet clients (accounts)
2122
const accounts = await viem.getWalletClients();
@@ -106,13 +107,13 @@ const deployWhitelistOracleContracts: DeployFunction = async function (hre: Hard
106107
});
107108
console.log(`Initial median price: ${medianPrice.toString()}`);
108109

109-
if (deployer !== whitelistContractOwner) {
110+
if (deployer !== whitelistContractNewOwner) {
110111
console.log("Transferring ownership of WhitelistOracle");
111112
await deployerAccount.writeContract({
112113
address: whitelistOracleAddress,
113114
abi: whitelistOracleAbi,
114115
functionName: "transferOwnership",
115-
args: [whitelistContractOwner],
116+
args: [whitelistContractNewOwner],
116117
});
117118
console.log("Ownership transferred successfully!");
118119
}

packages/nextjs/components/oracle/NodesTable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@ export const NodesTable = () => {
4343
functionName: "getNodeAddresses",
4444
});
4545

46+
const tooltipText =
47+
"This table displays registered oracle nodes that provide price data to the system. Nodes are displayed as inactive if they don't have enough ETH staked. You can edit the skip probability and price variance of an oracle node with the slider.";
48+
4649
return (
4750
<div className="flex flex-col gap-2">
4851
<h2 className="text-xl font-bold">Oracle Nodes</h2>
4952
<div className="bg-base-100 rounded-lg p-4 relative">
50-
<TooltipInfo top={0} right={0} infoText="TODO: Update this tooltip" />
53+
<TooltipInfo top={0} right={0} infoText={tooltipText} />
5154
<div className="overflow-x-auto">
5255
<table className="table w-full">
5356
<thead>

packages/nextjs/components/oracle/PriceWidget.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,18 @@ export const PriceWidget = ({ contractName }: PriceWidgetProps) => {
5151
<TooltipInfo
5252
top={0}
5353
right={0}
54-
infoText="Displays the median price. If an error occurs, it means that no oracle nodes have reported prices in the last 10 seconds."
54+
infoText="Displays the median price. If no oracle nodes have reported prices in the last 10 seconds, it will display 'No fresh price'."
5555
/>
5656
<div className={`rounded-lg transition-colors duration-1000 ${highlight ? highlightColor : ""}`}>
57-
<div className="text-4xl font-bold">
57+
<div className="font-bold h-10 text-4xl flex items-center justify-center">
5858
{isError ? (
59-
<div className="text-error">Error</div>
60-
) : currentPrice !== undefined ? (
61-
`$${parseFloat(formatEther(currentPrice)).toFixed(2)}`
59+
<div className="text-error text-xl">No fresh price</div>
6260
) : isLoading || currentPrice === undefined ? (
6361
<div className="animate-pulse">
6462
<div className="h-10 bg-secondary rounded-md w-32"></div>
6563
</div>
6664
) : (
67-
<div className="text-error">Error</div>
65+
`$${parseFloat(formatEther(currentPrice)).toFixed(2)}`
6866
)}
6967
</div>
7068
</div>

packages/nextjs/components/oracle/optimistic/SubmitAssertionButton.tsx

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,29 @@
22

33
import { useState } from "react";
44
import { parseEther } from "viem";
5+
import { usePublicClient } from "wagmi";
56
import TooltipInfo from "~~/components/TooltipInfo";
67
import { IntegerInput } from "~~/components/scaffold-eth";
78
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
89
import { useGlobalState } from "~~/services/store/store";
910
import { getRandomQuestion } from "~~/utils/helpers";
11+
import { notification } from "~~/utils/scaffold-eth";
12+
13+
const MINIMUM_REWARD = 0.21;
14+
const MINIMUM_ASSERTION_WINDOW = 3;
15+
16+
const getStartTimestamp = (timestamp: bigint, startInMinutes: string) => {
17+
if (startInMinutes.length === 0) return 0n;
18+
if (Number(startInMinutes) === 0) return 0n;
19+
return timestamp + BigInt(startInMinutes) * 60n;
20+
};
21+
22+
const getEndTimestamp = (timestamp: bigint, startTimestamp: bigint, durationInMinutes: string) => {
23+
if (durationInMinutes.length === 0) return 0n;
24+
if (Number(durationInMinutes) === MINIMUM_ASSERTION_WINDOW) return 0n;
25+
if (startTimestamp === 0n) return timestamp + BigInt(durationInMinutes) * 60n;
26+
return startTimestamp + BigInt(durationInMinutes) * 60n;
27+
};
1028

1129
interface SubmitAssertionModalProps {
1230
isOpen: boolean;
@@ -16,11 +34,12 @@ interface SubmitAssertionModalProps {
1634
const SubmitAssertionModal = ({ isOpen, onClose }: SubmitAssertionModalProps) => {
1735
const { timestamp } = useGlobalState();
1836
const [isLoading, setIsLoading] = useState(false);
37+
const publicClient = usePublicClient();
1938

2039
const [description, setDescription] = useState("");
2140
const [reward, setReward] = useState<string>("");
22-
const [startTime, setStartTime] = useState<string>("");
23-
const [endTime, setEndTime] = useState<string>("");
41+
const [startInMinutes, setStartInMinutes] = useState<string>("");
42+
const [durationInMinutes, setDurationInMinutes] = useState<string>("");
2443

2544
const { writeContractAsync } = useScaffoldWriteContract({ contractName: "OptimisticOracle" });
2645

@@ -30,21 +49,44 @@ const SubmitAssertionModal = ({ isOpen, onClose }: SubmitAssertionModalProps) =>
3049

3150
const handleSubmit = async (e: React.FormEvent) => {
3251
e.preventDefault();
52+
if (durationInMinutes.length > 0 && Number(durationInMinutes) < MINIMUM_ASSERTION_WINDOW) {
53+
notification.error(
54+
`Duration must be at least ${MINIMUM_ASSERTION_WINDOW} minutes or leave blank to use default value`,
55+
);
56+
return;
57+
}
58+
59+
if (Number(reward) < MINIMUM_REWARD) {
60+
notification.error(`Reward must be at least ${MINIMUM_REWARD} ETH`);
61+
return;
62+
}
63+
64+
if (!publicClient) {
65+
notification.error("Public client not found");
66+
return;
67+
}
68+
3369
try {
3470
setIsLoading(true);
35-
const startTimeFormatted = startTime.length === 0 ? 0n : BigInt(startTime);
36-
const endTimeFormatted = endTime.length === 0 ? 0n : BigInt(endTime);
71+
let recentTimestamp = timestamp;
72+
if (!recentTimestamp) {
73+
const block = await publicClient.getBlock();
74+
recentTimestamp = block.timestamp;
75+
}
76+
77+
const startTimestamp = getStartTimestamp(recentTimestamp, startInMinutes);
78+
const endTimestamp = getEndTimestamp(recentTimestamp, startTimestamp, durationInMinutes);
3779

3880
await writeContractAsync({
3981
functionName: "assertEvent",
40-
args: [description.trim(), startTimeFormatted, endTimeFormatted],
82+
args: [description.trim(), startTimestamp, endTimestamp],
4183
value: parseEther(reward),
4284
});
4385
// Reset form after successful submission
4486
setDescription("");
4587
setReward("");
46-
setStartTime("");
47-
setEndTime("");
88+
setStartInMinutes("");
89+
setDurationInMinutes("");
4890
onClose();
4991
} catch (error) {
5092
console.log("Error with submission", error);
@@ -58,8 +100,8 @@ const SubmitAssertionModal = ({ isOpen, onClose }: SubmitAssertionModalProps) =>
58100
// Reset form when closing
59101
setDescription("");
60102
setReward("");
61-
setStartTime("");
62-
setEndTime("");
103+
setStartInMinutes("");
104+
setDurationInMinutes("");
63105
};
64106

65107
if (!isOpen) return null;
@@ -82,7 +124,7 @@ const SubmitAssertionModal = ({ isOpen, onClose }: SubmitAssertionModalProps) =>
82124
<TooltipInfo
83125
top={-2}
84126
right={5}
85-
infoText="Create a new assertion with your reward stake. Leave timestamps blank to use default values."
127+
infoText="Create a new assertion with your reward stake. Leave time inputs blank to use default values."
86128
/>
87129
</div>
88130

@@ -133,36 +175,35 @@ const SubmitAssertionModal = ({ isOpen, onClose }: SubmitAssertionModalProps) =>
133175
</label>
134176
<IntegerInput
135177
name="reward"
136-
placeholder="0.22"
178+
placeholder={`Minimum ${MINIMUM_REWARD} ETH`}
137179
value={reward}
138180
onChange={newValue => setReward(newValue)}
139181
disableMultiplyBy1e18
140182
/>
141183
</div>
142184
{/* Start Time and End Time Inputs */}
143-
{timestamp && <div className="!mt-6 px-1 text-sm">Current Timestamp: {timestamp}</div>}
144-
<div className="grid grid-cols-2 gap-4 !mt-0">
185+
<div className="grid grid-cols-2 gap-4">
145186
<div>
146187
<label className="label">
147-
<span className="label-text font-medium">Start Time</span>
188+
<span className="label-text font-medium">Start in (minutes)</span>
148189
</label>
149190
<IntegerInput
150191
name="startTime"
151-
placeholder="0"
152-
value={startTime}
153-
onChange={newValue => setStartTime(newValue)}
192+
placeholder="blank = now"
193+
value={startInMinutes}
194+
onChange={newValue => setStartInMinutes(newValue)}
154195
disableMultiplyBy1e18
155196
/>
156197
</div>
157198
<div>
158199
<label className="label">
159-
<span className="label-text font-medium">End Time</span>
200+
<span className="label-text font-medium">Duration (minutes)</span>
160201
</label>
161202
<IntegerInput
162203
name="endTime"
163-
placeholder="0"
164-
value={endTime}
165-
onChange={newValue => setEndTime(newValue)}
204+
placeholder={`minimum ${MINIMUM_ASSERTION_WINDOW} minutes`}
205+
value={durationInMinutes}
206+
onChange={newValue => setDurationInMinutes(newValue)}
166207
disableMultiplyBy1e18
167208
/>
168209
</div>

packages/nextjs/components/oracle/whitelist/WhitelistTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const LoadingRow = () => {
2222
const NoNodesRow = () => {
2323
return (
2424
<tr>
25-
<td colSpan={6} className="text-center">
25+
<td colSpan={3} className="text-center">
2626
No nodes found
2727
</td>
2828
</tr>
@@ -58,7 +58,7 @@ export const WhitelistTable = () => {
5858
}))
5959
?.filter(item => !oraclesRemoved?.some(removedOracle => removedOracle?.args?.oracleAddress === item.address));
6060

61-
const tooltipText = `This table displays authorized oracle nodes that provide price data to the system. Nodes are considered active if they've reported within the last 10 seconds. You can edit the price of an oracle node by clicking on the price cell.`;
61+
const tooltipText = `This table displays registered oracle nodes that provide price data to the system. Nodes are considered active if they've reported within the last 10 seconds. You can add a new oracle node by clicking the "Add Oracle Node" button or edit the price of an oracle node.`;
6262

6363
return (
6464
<div className="flex flex-col gap-2">

0 commit comments

Comments
 (0)