import React, { useEffect } from 'react'
import Markdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import FormWrapper from '@/components/FormWrapper'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { ScrollArea } from '@/components/ui/scroll-area'
import { SimulationConfig } from '@/lib/types/types'
import { AllCheckResults } from '@/simulation/types'
import { useQueryState } from 'next-usequerystate'
import ApiCaller from '../providers/api-caller'
const STATUS_ITEMS = [
{ key: 'checkStateChanges', text: 'Report State Changes' },
{
key: 'checkDecodeCalldata',
text: 'Decoded Target Calldata',
},
{
key: 'checkLogs',
text: 'Report Events Emitted',
},
{
key: 'checkTargetsVerifiedEtherscan',
text: 'Report Target Contracts are Verified',
},
]
const countDoneLabels = (labels: string[]) => labels.filter((label) => label === 'Done').length
const AccordionStatusItem = ({ label, text, content }: any): JSX.Element => {
let labelClass
switch (label) {
case PENDING_LABEL:
labelClass = 'bg-orange-800 text-white animate-pulse' // Orange background, white text
break
case DONE_LABEL:
labelClass = 'bg-green-800 text-white' // Dark green background, white text
break
case ERROR_LABEL:
labelClass = 'bg-red-500 text-white' // Red background, white text
break
case DONE_BLACK_LABEL:
labelClass = 'bg-black text-white' // Black background, white text
break
default:
labelClass = 'bg-orange-800 text-whiten animate-pulse' // Default to orange background, white text
}
return (
{label}
{text}
{content}
)
}
const PENDING_LABEL = 'Pending'
const DONE_LABEL = 'Done'
const DONE_BLACK_LABEL = 'None'
const ERROR_LABEL = 'Error'
const getStatusAndContent = (resultItem: {
errors: string[]
warnings: string[]
info: string[]
}): {
status: string
content: string
} => {
if (resultItem.errors && resultItem.errors.length > 0) {
return {
status: ERROR_LABEL,
content: resultItem.errors.join('
'),
}
} else if (resultItem.warnings && resultItem.warnings.length > 0) {
return {
status: DONE_LABEL,
content: resultItem.warnings.join('
'),
} // Keeping the label as Done but showing warnings
} else if (resultItem.info && resultItem.info.length > 0) {
return { status: DONE_LABEL, content: resultItem.info.join('
') } // Keeping the label as Done but showing info
} else {
return { status: DONE_BLACK_LABEL, content: '' }
}
}
const ContractSimulationStatus = ({ simConfig }: { simConfig: SimulationConfig }) => {
const [simulationResults, setSimulationResults] = React.useState({
checkStateChanges: {
name: '',
result: { info: [], errors: [], warnings: [] },
},
checkDecodeCalldata: {
name: '',
result: { info: [], errors: [], warnings: [] },
},
checkTargetsVerifiedEtherscan: {
name: '',
result: { info: [], errors: [], warnings: [] },
},
checkLogs: {
name: '',
result: { info: [], errors: [], warnings: [] },
},
})
const [status, setStatus] = useQueryState('status', {
defaultValue: 'pending',
})
const [pendingAPI, setPendingAPI] = React.useState(true)
const [pendingState, setPendingState] = React.useState({
label: PENDING_LABEL,
text: ['Simulation in Progress'],
info: ['Please wait while we simulate your proposal.'],
})
React.useEffect(() => {
ApiCaller(simConfig).then(
(results) => {
setSimulationResults(results)
setPendingAPI(false)
},
(err) => {
setPendingState({
label: ERROR_LABEL,
text: ['Simulation Failed'],
info: ['Please try again later. \n Error Message: ', err],
})
}
)
}, [simConfig])
React.useEffect(() => {
// count if any of the labels is Errors
const countErrors = Object.values(simulationResults)
.map((item) => item.result)
.map((result) => getStatusAndContent(result).status)
.filter((status: any) => status === ERROR_LABEL).length
const countWarnings = Object.values(simulationResults)
.map((item) => item.result)
.map((result) => getStatusAndContent(result).status)
.filter((status: any) => status === DONE_LABEL).length
if (countErrors === 0 && pendingAPI === false) {
setStatus('done')
}
}, [simulationResults])
return (
Proposal Simulation Status{' '}
{countDoneLabels(
Object.values(simulationResults)
.map((item) => item.result)
.map((result) => getStatusAndContent(result).status)
)}{' '}
of {Object.values(simulationResults).length}{' '}
{' '}
{pendingAPI ? (
) : (
<>
{STATUS_ITEMS.map((item, index) => {
const { status, content } = getStatusAndContent(simulationResults[item.key].result)
return
})}
>
)}
{' '}
)
}
export default ContractSimulationStatus