Skip to content

refactor: fix crisp app expiration time and checks#1126

Merged
cedoor merged 7 commits into
mainfrom
refactor/crisp-app
Dec 19, 2025
Merged

refactor: fix crisp app expiration time and checks#1126
cedoor merged 7 commits into
mainfrom
refactor/crisp-app

Conversation

@cedoor

@cedoor cedoor commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

• removed dead code
• fixed the calculations related to E3 execution completion and app component updates
• reduced the waiting time of e2e tests by several minutes
• minor changes

Fixes #1125

Summary by CodeRabbit

  • New Features

    • Added network chain switching capability and clearer init error notifications.
  • Bug Fixes

    • Improved poll status detection with real-time blockchain verification.
  • Refactor

    • Replaced WebAssembly flow with a worker-based proof implementation.
    • Simplified proof/signing workflow to a fixed signature message.
    • Removed several unused UI components and helper utilities.
  • Chores

    • Adjusted test and environment timing defaults.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel

vercel Bot commented Dec 18, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Review Updated (UTC)
crisp Skipped Skipped Dec 19, 2025 10:10am
enclave-docs Skipped Skipped Dec 19, 2025 10:10am

@coderabbitai

coderabbitai Bot commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Removed per-call messageHash from proof flows and SDK/types; replaced the WebAssembly worker with an SDK worker; switched poll end detection to on-chain block-timestamp checks; removed several unused UI components and utilities; introduced dynamic chain selection and related wagmi/Web3Provider/App changes.

Changes

Cohort / File(s) Summary
Proof generation & worker
examples/CRISP/client/libs/crispSDKWorker.js, examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx, examples/CRISP/client/src/context/voteManagement/VoteManagement.context.tsx, examples/CRISP/client/src/context/voteManagement/VoteManagement.types.ts, examples/CRISP/client/src/hooks/voting/useVoteCasting.ts, examples/CRISP/packages/crisp-sdk/src/types.ts, examples/CRISP/packages/crisp-sdk/src/utils.ts, examples/CRISP/packages/crisp-sdk/tests/vote.test.ts
Removed messageHash from generateProof call sites and payloads; switched from a WebAssembly worker to an SDK worker (ref-based worker management, new worker script); made messageHash optional in SDK types and updated signature-recovery fallback; updated tests/call sites to omit messageHash.
Polling, chain selection & Web3 config
examples/CRISP/client/src/components/Cards/PollCard.tsx, examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx, examples/CRISP/client/src/utils/methods.ts, examples/CRISP/client/src/providers/Web3Provider.tsx, examples/CRISP/client/src/App.tsx, examples/CRISP/client/src/utils/network.ts
Replaced local poll-end helpers with async on-chain timestamp checks using usePublicClient; added getChain() (hardhat in DEV, sepolia otherwise) and applied it across Web3Provider and App; integrated useSwitchChain in App; removed exported Chain enum.
Removed UI components & hooks
examples/CRISP/client/src/components/CodeTextDisplay.tsx, examples/CRISP/client/src/components/Modal.tsx, examples/CRISP/client/src/hooks/generic/useLocalStorage.tsx
Deleted CodeTextDisplay component, Modal component, and generic useLocalStorage hook files.
Utility, types & assets cleanup
examples/CRISP/client/src/utils/proof-encoding.ts, examples/CRISP/client/src/utils/whitepaper.ts, examples/CRISP/client/src/model/vote.model.ts, examples/CRISP/client/src/utils/handle-generic-error.ts, examples/CRISP/client/src/pages/About/About.tsx, examples/CRISP/client/src/globals.css
Removed encodeCrispInputs, whitepaper markdown export, VotingConfigRequest interface, a commented throw, an unused icon import, and the .close-icon CSS rule.
Configuration & test timing
examples/CRISP/server/.env.example, examples/CRISP/test/crisp.spec.ts
Adjusted E3 window size in .env.example (40 → 30); reduced E3 activation wait and vote-casting wait times in tests (60,000 → 30,000 ms; 150,000 → 80,000 ms).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Pay attention to:
    • Worker message shape and generateProof call chain across hooks, context, worker, and SDK types.
    • useSDKWorker ref-based lifecycle, messaging, and cleanup.
    • PollCard / DailyPoll asynchronous block polling, effect dependencies, and client availability guards.
    • Web3Provider/getChain integration and App's useSwitchChain flow.
    • Test timing changes for stability.

Possibly related PRs

Suggested reviewers

  • hmzakhalid
  • ctrlc03

Poem

🐰 I hopped from wasm to SDK light,
No per-call hashes in my sight,
I check the chain for poll-day ends,
Cleaned up widgets, trimmed old trends,
A nimble hop — the code feels bright!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: fix crisp app expiration time and checks' clearly and specifically describes the main focus of the changes: fixing expiration time calculations and related checks in the CRISP application.
Linked Issues check ✅ Passed The PR addresses the primary objectives from issue #1125: it corrects expiration time calculations by implementing dynamic, client-driven block timestamp checks and removes outdated polling-end utilities; it refactors the application for consistent blockchain synchronization by integrating usePublicClient, wagmi chain switching, and SDK worker updates.
Out of Scope Changes check ✅ Passed All changes are directly aligned with fixing expiration calculations and refactoring for blockchain synchronization: dynamic block checks via usePublicClient, SDK worker integration, messageHash removal, chain switching, and cleanup of unused utilities (hasPollEnded functions, unused imports, dead code). No unrelated refactoring or scope creep detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/crisp-app

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cedoor cedoor requested review from ctrlc03 and hmzakhalid December 18, 2025 16:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (1)

28-68: Race condition: Concurrent generateProof calls will conflict.

Setting workerRef.current!.onmessage inside generateProof creates a critical race condition. If generateProof is called multiple times before the first completes, each new call overwrites the previous onmessage handler, causing earlier promises to hang indefinitely and their loading states to never clear.

Additionally, if the component unmounts during proof generation, the promise never resolves or rejects, causing a memory leak.

🔎 Suggested fix using message IDs to handle concurrent calls:
 export const useSDKWorkerHook = () => {
   const { showToast } = useNotificationAlertContext()
   const [isLoading, setIsLoading] = useState<boolean>(false)
   const workerRef = useRef<Worker | null>(null)
+  const pendingRequests = useRef<Map<string, { resolve: (value: string | undefined) => void; reject: (error: Error) => void }>>(new Map())

   useEffect(() => {
     const newWorker = new Worker(new URL('libs/crispSDKWorker.js', import.meta.url), {
       type: 'module',
     })

     workerRef.current = newWorker
+
+    newWorker.onmessage = (event) => {
+      const { type, success, encodedProof, error, requestId } = event.data
+
+      if (type === 'generate_proof') {
+        const pending = pendingRequests.current.get(requestId)
+        if (pending) {
+          pendingRequests.current.delete(requestId)
+          setIsLoading(pendingRequests.current.size > 0)
+
+          if (success) {
+            pending.resolve(encodedProof)
+          } else {
+            showToast({
+              type: 'danger',
+              message: error,
+            })
+            handleGenericError('generateProof', new Error(error))
+            pending.reject(new Error(error))
+          }
+        }
+      }
+    }

     return () => {
+      pendingRequests.current.clear()
       newWorker.terminate()
     }
   }, [])

   const generateProof = async (
     voteId: bigint,
     publicKey: Uint8Array,
     address: string,
     signature: string,
     previousCiphertext?: Uint8Array,
   ): Promise<string | undefined> => {
     if (!workerRef.current) {
       console.error('Worker not initialized')
       return
     }

     return new Promise<string | undefined>((resolve, reject) => {
+      const requestId = crypto.randomUUID()
+      pendingRequests.current.set(requestId, { resolve, reject })
       setIsLoading(true)

       workerRef.current!.postMessage({
         type: 'generate_proof',
-        data: { voteId, publicKey, address, signature, previousCiphertext },
+        data: { voteId, publicKey, address, signature, previousCiphertext, requestId },
       })
-
-      workerRef.current!.onmessage = async (event) => {
-        const { type, success, encodedProof, error } = event.data
-
-        if (type === 'generate_proof') {
-          if (success) {
-            resolve(encodedProof)
-          } else {
-            showToast({
-              type: 'danger',
-              message: error,
-            })
-
-            handleGenericError('generateProof', new Error(error))
-
-            reject(new Error(error))
-          }
-
-          setIsLoading(false)
-        }
-      }
     })
   }

   return {
     isLoading,
     generateProof,
   }
 }

Note: This also requires updating libs/crispSDKWorker.js to echo back the requestId in responses.

🧹 Nitpick comments (5)
examples/CRISP/server/.env.example (1)

23-26: Verify the timing configuration relationship and document units.

The reduced values align with the PR's goal to fix expiration times. However:

  1. Relationship verification needed: E3_WINDOW_SIZE (30) defines the activation window, while E3_DURATION (40) defines the input submission interval. Please confirm that having the duration exceed the window size is the intended behavior.

  2. Missing unit specification: The comments don't specify units for these values. Based on the test file using milliseconds (30000ms), these appear to be in seconds, but this should be explicitly documented in the comments to prevent confusion.

🔎 Suggested documentation improvement
 # E3 Config
-# Defines the time window during which an e3 can be activated
+# Defines the time window (in seconds) during which an e3 can be activated
 E3_WINDOW_SIZE=30
-# Defines the time interval during which users can submit their inputs
+# Defines the time interval (in seconds) during which users can submit their inputs
 # After this interval, the computation phase starts automatically
 E3_DURATION=40

Note: The static analysis tool suggests reordering these keys, but this is a minor stylistic preference and can be safely ignored.

examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (1)

35-46: Add error handling for blockchain queries.

The async block fetch has no error handling. If client.getBlock() fails (e.g., network issues), the error will be uncaught and could cause issues.

🔎 Apply this diff to add error handling:
   useEffect(() => {
     ;(async () => {
       if (!client) return
       if (!roundState) return
 
-      const block = await client.getBlock()
-
-      if (block.timestamp > roundState.expiration) {
-        setIsEnded(true)
-      }
+      try {
+        const block = await client.getBlock()
+        
+        if (block.timestamp > roundState.expiration) {
+          setIsEnded(true)
+        } else {
+          setIsEnded(false)
+        }
+      } catch (error) {
+        console.error('Failed to fetch block for poll status:', error)
+      }
     })()
   }, [roundState, client])
examples/CRISP/client/src/providers/Web3Provider.tsx (2)

22-26: Consider transport configuration alignment.

The chains array contains only [getChain()] (either hardhat or sepolia), but transports defines mappings for both anvil.id and sepolia.id. While this doesn't cause runtime errors, it means one transport is unused.

🔎 Consider simplifying to match the single-chain approach:
+    const chain = getChain()
     chains: [getChain()],
     transports: {
-      [anvil.id]: http(anvil.rpcUrls.default.http[0]),
-      [sepolia.id]: http(sepolia.rpcUrls.default.http[0]),
+      [chain.id]: http(chain.rpcUrls.default.http[0]),
     },

Alternatively, if multi-chain support is planned, include both chains:

-    chains: [getChain()],
+    chains: [anvil, sepolia],

33-35: Improve chain switcher documentation.

The comment is helpful but could be more actionable. Consider adding a reference to where the switcher should be implemented or a code example.

🔎 Suggested improvement:
-// NOTE: ConnectKit doesn't ship a drop-in chain switcher UI. This just sets the initial chain.
-// For a user-facing switcher, implement a small component that calls wagmi's `useSwitchChain`.
+// NOTE: ConnectKit doesn't provide a built-in chain switcher UI. This sets the initial chain only.
+// For a user-facing switcher, see App.tsx for an example using wagmi's `useSwitchChain` hook.
 const options = { initialChainId: getChain().id }

Based on learnings, the user prefers manual network switching over automatic detection.

examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (1)

43-43: Consider removing non-null assertions for cleaner code.

The non-null assertion operator ! is used on workerRef.current after the guard check at line 35. While technically safe, this pattern could be improved by extracting the worker reference to a local variable.

🔎 Optional refactor to eliminate non-null assertions:
   const generateProof = async (
     voteId: bigint,
     publicKey: Uint8Array,
     address: string,
     signature: string,
     previousCiphertext?: Uint8Array,
   ): Promise<string | undefined> => {
-    if (!workerRef.current) {
+    const worker = workerRef.current
+    if (!worker) {
       console.error('Worker not initialized')
       return
     }

     return new Promise<string | undefined>((resolve, reject) => {
       setIsLoading(true)

-      workerRef.current!.postMessage({
+      worker.postMessage({
         type: 'generate_proof',
         data: { voteId, publicKey, address, signature, previousCiphertext },
       })

-      workerRef.current!.onmessage = async (event) => {
+      worker.onmessage = async (event) => {
         const { type, success, encodedProof, error } = event.data

         if (type === 'generate_proof') {
           if (success) {
             resolve(encodedProof)
           } else {
             showToast({
               type: 'danger',
               message: error,
             })

             handleGenericError('generateProof', new Error(error))

             reject(new Error(error))
           }

           setIsLoading(false)
         }
       }
     })
   }

Also applies to: 48-48

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 122fead and c9d158e.

⛔ Files ignored due to path filters (12)
  • examples/CRISP/client/src/assets/icons/arrowRight.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/calendarCheck.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/caretCircle.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/check.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/close.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/enclaveLogo.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/fingerprint.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/fingerprintWhite.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/logout.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/notebook.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/paper.svg is excluded by !**/*.svg
  • examples/CRISP/client/src/assets/icons/paperPurple.svg is excluded by !**/*.svg
📒 Files selected for processing (25)
  • examples/CRISP/client/libs/crispSDKWorker.js (1 hunks)
  • examples/CRISP/client/src/App.tsx (2 hunks)
  • examples/CRISP/client/src/components/Cards/PollCard.tsx (2 hunks)
  • examples/CRISP/client/src/components/CodeTextDisplay.tsx (0 hunks)
  • examples/CRISP/client/src/components/Modal.tsx (0 hunks)
  • examples/CRISP/client/src/context/voteManagement/VoteManagement.context.tsx (3 hunks)
  • examples/CRISP/client/src/context/voteManagement/VoteManagement.types.ts (0 hunks)
  • examples/CRISP/client/src/globals.css (0 hunks)
  • examples/CRISP/client/src/hooks/generic/useLocalStorage.tsx (0 hunks)
  • examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (3 hunks)
  • examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (4 hunks)
  • examples/CRISP/client/src/model/vote.model.ts (0 hunks)
  • examples/CRISP/client/src/pages/About/About.tsx (0 hunks)
  • examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (3 hunks)
  • examples/CRISP/client/src/providers/Web3Provider.tsx (1 hunks)
  • examples/CRISP/client/src/utils/handle-generic-error.ts (0 hunks)
  • examples/CRISP/client/src/utils/methods.ts (2 hunks)
  • examples/CRISP/client/src/utils/network.ts (0 hunks)
  • examples/CRISP/client/src/utils/proof-encoding.ts (0 hunks)
  • examples/CRISP/client/src/utils/whitepaper.ts (0 hunks)
  • examples/CRISP/packages/crisp-sdk/src/types.ts (1 hunks)
  • examples/CRISP/packages/crisp-sdk/src/utils.ts (1 hunks)
  • examples/CRISP/packages/crisp-sdk/tests/vote.test.ts (0 hunks)
  • examples/CRISP/server/.env.example (1 hunks)
  • examples/CRISP/test/crisp.spec.ts (2 hunks)
💤 Files with no reviewable changes (12)
  • examples/CRISP/client/src/utils/proof-encoding.ts
  • examples/CRISP/client/src/context/voteManagement/VoteManagement.types.ts
  • examples/CRISP/client/src/model/vote.model.ts
  • examples/CRISP/client/src/components/Modal.tsx
  • examples/CRISP/client/src/components/CodeTextDisplay.tsx
  • examples/CRISP/client/src/utils/whitepaper.ts
  • examples/CRISP/packages/crisp-sdk/tests/vote.test.ts
  • examples/CRISP/client/src/hooks/generic/useLocalStorage.tsx
  • examples/CRISP/client/src/globals.css
  • examples/CRISP/client/src/utils/handle-generic-error.ts
  • examples/CRISP/client/src/utils/network.ts
  • examples/CRISP/client/src/pages/About/About.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-10T17:29:41.338Z
Learnt from: cedoor
Repo: gnosisguild/enclave PR: 832
File: templates/default/client/src/pages/components/Navbar.tsx:12-26
Timestamp: 2025-10-10T17:29:41.338Z
Learning: In the Enclave project, the user prefers using ConnectKit's `initialChainId` configuration combined with a manual NetworkSwitchButton for network switching, rather than implementing automatic network detection and switching on wallet connection.

Applied to files:

  • examples/CRISP/client/src/providers/Web3Provider.tsx
🧬 Code graph analysis (6)
examples/CRISP/packages/crisp-sdk/src/utils.ts (2)
examples/CRISP/packages/crisp-sdk/src/index.ts (2)
  • getAddressFromSignature (10-10)
  • SIGNATURE_MESSAGE_HASH (9-9)
examples/CRISP/packages/crisp-sdk/src/constants.ts (1)
  • SIGNATURE_MESSAGE_HASH (32-32)
examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (4)
examples/CRISP/client/src/context/NotificationAlert/NotificationAlert.context.tsx (1)
  • useNotificationAlertContext (88-88)
examples/CRISP/client/libs/crispSDKWorker.js (1)
  • event (10-10)
examples/CRISP/client/src/utils/handle-generic-error.ts (1)
  • handleGenericError (7-9)
crates/events/src/eventbus.rs (1)
  • error (73-77)
examples/CRISP/client/src/components/Cards/PollCard.tsx (2)
examples/CRISP/client/src/model/poll.model.ts (2)
  • PollResult (14-20)
  • PollOption (7-12)
examples/CRISP/client/src/context/voteManagement/VoteManagement.context.tsx (1)
  • useVoteManagementContext (242-242)
examples/CRISP/client/src/context/voteManagement/VoteManagement.context.tsx (1)
examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (1)
  • useSDKWorkerHook (11-75)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (4)
examples/CRISP/client/src/model/poll.model.ts (1)
  • Poll (32-36)
examples/CRISP/packages/crisp-sdk/src/vote.ts (1)
  • generateProof (167-176)
packages/enclave-sdk/src/index.ts (1)
  • generateProof (69-69)
examples/CRISP/packages/crisp-sdk/src/constants.ts (1)
  • SIGNATURE_MESSAGE (31-31)
examples/CRISP/client/src/providers/Web3Provider.tsx (1)
examples/CRISP/client/src/utils/methods.ts (1)
  • getChain (26-28)
🪛 dotenv-linter (4.0.0)
examples/CRISP/server/.env.example

[warning] 26-26: [UnorderedKey] The E3_DURATION key should go before the E3_WINDOW_SIZE key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Build & Push Image
  • GitHub Check: build_sdk
  • GitHub Check: integration_prebuild
  • GitHub Check: build_crisp_sdk
  • GitHub Check: rust_integration
  • GitHub Check: build_enclave_cli
  • GitHub Check: build_ciphernode_image
  • GitHub Check: rust_unit
  • GitHub Check: test_net
🔇 Additional comments (22)
examples/CRISP/test/crisp.spec.ts (2)

47-47: Consider adding buffer time to the activation timeout.

The reduced timeout from 60s to 30s aligns with the E3_WINDOW_SIZE configuration change. However, with a 30-second activation window and exactly 30 seconds of wait time, there's no buffer for processing overhead, network latency, or CI environment slowness. This could lead to flaky test failures.

Consider adding a small buffer (e.g., 35000ms or 40000ms) to account for realistic execution delays while still keeping tests reasonably fast.


113-113: Test wait time reduction looks reasonable.

The reduction from 150s to 60s is appropriate given the E3_DURATION configuration change from 60 to 40 seconds. The 60-second wait provides a 20-second buffer beyond the 40-second duration, which should be sufficient for computation and result processing.

However, monitor for any flakiness in CI environments where execution may be slower than local development.

examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (4)

7-7: LGTM!

The new imports are correctly added to support the blockchain-based poll end detection.

Also applies to: 18-18


28-29: LGTM with a note on state management.

The hook and state initialization look correct. Note that isEnded persists across roundState changes, which appears intentional since the useEffect will recalculate it when roundState updates.


95-95: LGTM!

The conditional rendering logic based on isEnded state is correctly implemented throughout the component for displaying poll status, countdown timer, and voting buttons.

Also applies to: 113-113, 131-131, 138-138


42-42: No changes needed. The comparison is correct.

Both block.timestamp (from Ethereum) and roundState.expiration are in seconds. The convertVoteStateLite utility function confirms this by multiplying expiration by 1000 when converting to a JavaScript Date, which is the standard conversion from seconds to milliseconds.

Likely an incorrect or invalid review comment.

examples/CRISP/client/src/components/Cards/PollCard.tsx (3)

12-14: LGTM: Clean transition to blockchain-based timestamp checking.

The import changes appropriately reflect the shift from a synchronous utility function to wagmi's public client for blockchain timestamp verification.


41-41: LGTM: Dependency array properly manages interval cleanup.

Including isActive in the dependency array ensures the interval is cleaned up when the poll ends. When isActive becomes false, the effect re-runs, the cleanup function clears the old interval, and the guard at line 27 prevents a new interval from being set.


27-35: Verify type compatibility between block.timestamp and endTime.

The comparison at line 32 mixes types: block.timestamp is bigint (from viem's getBlock()), while endTime is number (from the PollResult interface). Consider converting to a consistent type:

if (Number(block.timestamp) >= endTime) {
  setIsActive(false)
}

Or alternatively:

if (block.timestamp >= BigInt(endTime)) {
  setIsActive(false)
}
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (3)

16-16: LGTM: Centralized signature message.

The import of SIGNATURE_MESSAGE from the SDK centralizes the signing message, improving consistency across the codebase.


113-113: Fixed signature message replaces dynamic approach.

Using the constant SIGNATURE_MESSAGE replaces the previous per-round dynamic message hash. This change simplifies the signing flow and ensures consistency.


70-73: Simplified proof generation signature with smart message defaults.

The messageHash parameter is made optional and defaults to SIGNATURE_MESSAGE_HASH, simplifying the public API. The function now relies on the SDK's fixed SIGNATURE_MESSAGE constant for address recovery, eliminating the need for callers to manage the signature message separately.

Verification confirmed:

  • Backend signature verification correctly uses fixed SIGNATURE_MESSAGE_HASH for address recovery (verified in contract tests)
  • Client code correctly relies on the SDK's default by signing with SIGNATURE_MESSAGE and omitting messageHash
  • Type definition shows messageHash?: 0x${string} with fallback to SIGNATURE_MESSAGE_HASH in getAddressFromSignature
examples/CRISP/client/libs/crispSDKWorker.js (1)

14-35: LGTM: Worker aligned with messageHash removal.

The worker correctly omits messageHash from the data payload and the generateVoteProof call, consistent with the SDK refactor that makes messageHash optional and defaults to SIGNATURE_MESSAGE_HASH.

examples/CRISP/packages/crisp-sdk/src/types.ts (1)

198-198: LGTM: Type reflects optional messageHash.

Making messageHash optional in VoteProofInputs aligns with the runtime behavior where the SDK now defaults to SIGNATURE_MESSAGE_HASH when not provided. This change is backward-compatible.

examples/CRISP/client/src/utils/methods.ts (2)

26-28: LGTM: Clean chain selection helper.

The getChain() function provides a clear DEV vs. production chain selection. The implementation is straightforward and leverages Viem's chain definitions.


9-10: Poll-end utilities successfully removed.

Verification confirms hasPollEnded and hasPollEndedByTimestamp are not referenced anywhere in the codebase. The removal is complete with no remaining dependencies.

examples/CRISP/client/src/context/voteManagement/VoteManagement.context.tsx (2)

9-9: LGTM: SDK worker replaces WebAssembly hook.

The refactor from useWebAssemblyHook to useSDKWorkerHook modernizes the proof generation flow while maintaining the same API surface (generateProof, loading state).


62-62: Consistent loading state renaming.

The rename from wasmLoading to workerLoading accurately reflects the underlying implementation change and is applied consistently across all references.

Also applies to: 170-174

examples/CRISP/packages/crisp-sdk/src/utils.ts (1)

120-124: LGTM: Optional messageHash with sensible fallback.

Making messageHash optional and defaulting to SIGNATURE_MESSAGE_HASH supports both the new fixed-message flow and any legacy code that might still pass explicit message hashes. This is a backward-compatible change.

examples/CRISP/client/src/hooks/voting/useSDKWorker.tsx (3)

7-7: LGTM! Appropriate use of useRef for Worker instance.

Using useRef instead of useState for the Worker instance is the correct approach, as Worker mutations shouldn't trigger component re-renders.

Also applies to: 14-14


11-11: LGTM! Hook renamed to reflect SDK worker integration.

The rename from useWebAssemblyHook to useSDKWorkerHook accurately reflects the refactoring to SDK-based worker integration.


17-26: LGTM! Worker initialization and cleanup properly implemented.

The worker script path has been updated to crispSDKWorker.js, and the cleanup logic properly terminates the worker on component unmount.

Comment thread examples/CRISP/client/src/App.tsx
Comment thread examples/CRISP/client/src/components/Cards/PollCard.tsx
Comment thread examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx Outdated
Comment thread examples/CRISP/client/src/utils/methods.ts
@vercel vercel Bot temporarily deployed to Preview – enclave-docs December 18, 2025 16:32 Inactive
@vercel vercel Bot temporarily deployed to Preview – crisp December 18, 2025 16:32 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9d158e and c388d3d.

📒 Files selected for processing (2)
  • examples/CRISP/server/.env.example (1 hunks)
  • examples/CRISP/test/crisp.spec.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/CRISP/server/.env.example
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: build_sdk
  • GitHub Check: build_e3_support_dev
  • GitHub Check: integration_prebuild
  • GitHub Check: build_enclave_cli
  • GitHub Check: build_crisp_sdk
  • GitHub Check: rust_unit
  • GitHub Check: rust_integration
  • GitHub Check: test_net
  • GitHub Check: build_ciphernode_image
  • GitHub Check: Build & Push Image
🔇 Additional comments (1)
examples/CRISP/test/crisp.spec.ts (1)

47-47: Verify the reduced timeout is sufficient across environments.

The maxWaitMs has been halved from 60s to 30s. While this aligns with the server-side E3_WINDOW_SIZE reduction (40→30), ensure this timeout is adequate for all test environments (local, CI, different hardware configurations) to avoid introducing flakiness.

Consider running the test suite multiple times across different environments to confirm the 30s timeout remains reliable. If timing varies significantly, you may want to add a small buffer to the timeout.

Comment thread examples/CRISP/test/crisp.spec.ts
@ctrlc03 ctrlc03 self-requested a review December 18, 2025 17:05
ctrlc03
ctrlc03 previously approved these changes Dec 18, 2025
@vercel vercel Bot temporarily deployed to Preview – enclave-docs December 19, 2025 10:10 Inactive
@vercel vercel Bot temporarily deployed to Preview – crisp December 19, 2025 10:10 Inactive
@cedoor cedoor requested a review from ctrlc03 December 19, 2025 10:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
examples/CRISP/client/src/App.tsx (1)

31-48: Fix the incomplete dependency array (still unresolved from previous review).

The previous review identified that this useEffect uses initialLoad and switchChain but has an empty dependency array. This issue remains unresolved. The effect now also uses showToast and handleGenericError, which should be included in the dependencies or properly memoized.

🔎 Apply this diff to fix the dependency array:
     })()
-  }, [])
+  }, [initialLoad, switchChain, showToast])

Note: Ensure initialLoad, switchChain, and showToast are stable (memoized with useCallback in their respective contexts) to prevent infinite re-renders.

🧹 Nitpick comments (1)
examples/CRISP/client/src/App.tsx (1)

38-46: Consider more granular error handling for different failure scenarios.

The current error handling treats all failures equally with a persistent error toast. However, switchChain can fail for benign reasons (e.g., user rejection), which shouldn't display a persistent "Failed to initialize" message. Consider distinguishing between critical failures (initialLoad) and optional failures (switchChain).

🔎 Suggested approach for more nuanced error handling:
       try {
         await initialLoad()
-
+      } catch (error) {
+        const errorMessage = error instanceof Error ? error.message : String(error)
+        handleGenericError('App initial load', error instanceof Error ? error : new Error(errorMessage))
+        showToast({
+          type: 'danger',
+          message: 'Failed to initialize application. Please refresh the page.',
+          persistent: true,
+        })
+        return
+      }
+
+      try {
         const chain = getChain()
         switchChain({ chainId: chain.id })
       } catch (error) {
-        const errorMessage = error instanceof Error ? error.message : String(error)
-        handleGenericError('App initial load', error instanceof Error ? error : new Error(errorMessage))
+        // Chain switch failure is less critical (e.g., user rejection)
+        console.warn('Chain switch failed:', error)
         showToast({
-          type: 'danger',
-          message: 'Failed to initialize application. Please refresh the page.',
-          persistent: true,
+          type: 'warning',
+          message: 'Failed to switch network. You may need to switch manually.',
+          persistent: false,
         })
       }

This separates critical initialization failures from optional chain-switching failures.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c388d3d and 6a92f62.

📒 Files selected for processing (2)
  • examples/CRISP/client/src/App.tsx (2 hunks)
  • examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (1)
examples/CRISP/client/src/model/poll.model.ts (1)
  • Poll (32-36)
🔇 Additional comments (1)
examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (1)

92-99: Great fix for the Tailwind dynamic class generation issue!

The previous review correctly flagged that template literal interpolation (e.g., `border-${color}-600`) doesn't work with Tailwind's JIT compiler. You've properly addressed this by using complete conditional class names with a ternary operator, ensuring all required classes are generated in the final CSS bundle.

Comment thread examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx
Comment thread examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx
@cedoor cedoor enabled auto-merge (squash) December 19, 2025 10:18
@cedoor cedoor merged commit 9987505 into main Dec 19, 2025
27 checks passed
@ctrlc03 ctrlc03 deleted the refactor/crisp-app branch December 19, 2025 10:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix expiration time calculation in CRISP client app

2 participants