22
33import { useState } from "react" ;
44import { parseEther } from "viem" ;
5+ import { usePublicClient } from "wagmi" ;
56import TooltipInfo from "~~/components/TooltipInfo" ;
67import { IntegerInput } from "~~/components/scaffold-eth" ;
78import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth" ;
89import { useGlobalState } from "~~/services/store/store" ;
910import { 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
1129interface SubmitAssertionModalProps {
1230 isOpen : boolean ;
@@ -16,11 +34,12 @@ interface SubmitAssertionModalProps {
1634const 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 >
0 commit comments