Skip to content

feat: fetch token data data from crisp server#804

Merged
ctrlc03 merged 4 commits into
devfrom
feat/fetch-crisp-token-data
Oct 9, 2025
Merged

feat: fetch token data data from crisp server#804
ctrlc03 merged 4 commits into
devfrom
feat/fetch-crisp-token-data

Conversation

@ctrlc03

@ctrlc03 ctrlc03 commented Oct 8, 2025

Copy link
Copy Markdown
Collaborator

fix #685 and fix #806

Summary by CodeRabbit

  • New Features

    • Added a CRISP SDK package exposing token-related APIs to fetch token-holder tree data.
    • Added a server route to retrieve token-holder hashes with improved error responses and logging.
  • Changes

    • Deployment script now preserves previous local deployments instead of wiping them.
  • Tests

    • Added a unit test validating token data fetching against a local server.
  • Chores

    • Added formatting configuration and ignore rules for the SDK.
    • Included the SDK in the workspace configuration.

@vercel

vercel Bot commented Oct 8, 2025

Copy link
Copy Markdown

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
crisp Skipped Skipped Oct 8, 2025 1:43pm
enclave-docs Skipped Skipped Oct 8, 2025 1:43pm

@ctrlc03 ctrlc03 self-assigned this Oct 8, 2025
@github-actions

github-actions Bot commented Oct 8, 2025

Copy link
Copy Markdown
Contributor

License Header Check Failed

Some files are missing the required SPDX license header. Please add the following header to the beginning of all .js, .jsx, .nr, .rs, .sol, .ts, and .tsx files:

// SPDX-License-Identifier: LGPL-3.0-only
//
// This file is provided WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.

You can run ./scripts/check-license-headers.sh --fix locally to automatically add missing headers, then commit the changes.

Or run ./scripts/check-license-headers.sh to see which files need headers.

@coderabbitai

coderabbitai Bot commented Oct 8, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a new TypeScript CRISP SDK (package, formatting, build, tests) exposing token-tree fetch APIs; adds a server route to return token-holder hashes; changes server round lifecycle to initialize on Requested and start on Activated; updates deploy script to skip deleting previous deployments; includes SDK in pnpm workspace.

Changes

Cohort / File(s) Summary
Deploy script
examples/CRISP/scripts/evm_deploy.sh
Removed the step that deletes deployments/localhost before running pnpm deploy:mocks --network localhost.
Workspace
pnpm-workspace.yaml
Added examples/CRISP/sdk to workspace packages.
SDK package & config
examples/CRISP/sdk/.prettierignore, examples/CRISP/sdk/.prettierrc, examples/CRISP/sdk/package.json, examples/CRISP/sdk/tsconfig.json
New SDK project files: Prettier ignore/config, package metadata (scripts, devDeps, publishConfig), and TypeScript configuration for building declarations to dist.
SDK source & tests
examples/CRISP/sdk/src/constants.ts, examples/CRISP/sdk/src/index.ts, examples/CRISP/sdk/src/token.ts, examples/CRISP/sdk/tests/token.test.ts
New SDK exports: CRISP_SERVER_TOKEN_TREE_ENDPOINT, re-export ./token, getTreeData(serverUrl, e3Id) that POSTs { round_id } to server and returns JSON; placeholders generateMerkleProof, getBalanceAt, getRoundDetails, IRoundDetails interface; Vitest test asserting getTreeData(http://localhost:4000, 0) returns a non-empty array.
Server: indexer and repository
examples/CRISP/server/src/server/indexer.rs, examples/CRISP/server/src/server/repo.rs
On Requested event call repo.initialize_round().await?; on Activated event call new repo.start_round().await?. Added start_round in repository to set start_time and set status to "Active"; initialize_round now sets start_time to 0 and status to "Requested".
Server: routes/state
examples/CRISP/server/src/server/routes/state.rs
Added /state/token-holders route and handler to fetch token-holder hashes via store.e3(...).get_token_holder_hashes().await; improved contract creation error handling and logging; minor import/reformatting changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client as SDK Consumer
  participant SDK as CRISP SDK
  participant Server as CRISP Server
  participant Repo as CrispE3Repository

  Client->>SDK: getTreeData(serverUrl, e3Id)
  SDK->>Server: POST /state/token-holders { round_id: e3Id }
  Server->>Repo: get_token_holder_hashes(round_id)
  Repo-->>Server: tokenHolderHashes
  Server-->>SDK: 200 OK JSON (hashes)
  SDK-->>Client: Parsed JSON
  note right of Server: Errors return HTTP 500 with JSON message
Loading
sequenceDiagram
  autonumber
  actor Chain as E3 Events
  participant Indexer as indexer.rs
  participant Repo as CrispE3Repository

  rect rgba(200,235,255,0.3)
    note right of Chain: Requested Event
    Chain->>Indexer: register_e3_requested
    Indexer->>Repo: initialize_round()
    Repo-->>Indexer: Ok
  end

  rect rgba(200,255,200,0.3)
    note right of Chain: Activated Event
    Chain->>Indexer: register_e3_activated
    Indexer->>Repo: start_round()
    Repo-->>Indexer: Ok
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • cedoor
  • hmzakhalid

Poem

A twitch of whiskers, taps of keys,
I fetched the tree with nimble ease.
New routes burrow where data hides,
Rounds awaken on gentle tides.
Hippity hop — hashes out the gate! 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR introduces numerous unrelated tooling and configuration updates—including Prettier settings, TypeScript SDK scaffolding, package.json, pnpm-workspace entries, tsconfig, and deployment script edits—that fall outside the goals of exposing merkle tree data (#685) and fixing the round override (#806). To keep the PR focused on the linked issues, split out the formatting and SDK setup into a separate commit or PR and retain only the server route, indexer, and minimal SDK logic required for data exposure and round persistence fixes.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the addition of token data fetching from the CRISP server, aligning with the main feature of the PR despite a minor duplicated word.
Linked Issues Check ✅ Passed The PR implements a server route and SDK function to fetch merkle tree siblings data satisfying issue #685 and modifies the indexer to call initialize_round on request and start_round on activation to prevent the data reset described in issue #806.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/fetch-crisp-token-data

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fe8d6f and 2f466db.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • examples/CRISP/sdk/package.json (1 hunks)
⏰ 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). (6)
  • GitHub Check: test_contracts
  • GitHub Check: build_enclave_cli
  • GitHub Check: integration_prebuild
  • GitHub Check: build_sdk
  • GitHub Check: test_net
  • GitHub Check: rust_unit

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.

@ctrlc03 ctrlc03 force-pushed the feat/fetch-crisp-token-data branch from 7f4dbfa to 0afefdf Compare October 8, 2025 11:32
@github-actions

github-actions Bot commented Oct 8, 2025

Copy link
Copy Markdown
Contributor

License Header Check Failed

Some files are missing the required SPDX license header. Please add the following header to the beginning of all .js, .jsx, .nr, .rs, .sol, .ts, and .tsx files:

// SPDX-License-Identifier: LGPL-3.0-only
//
// This file is provided WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.

You can run ./scripts/check-license-headers.sh --fix locally to automatically add missing headers, then commit the changes.

Or run ./scripts/check-license-headers.sh to see which files need headers.

@ctrlc03 ctrlc03 force-pushed the feat/fetch-crisp-token-data branch from 1f91006 to 5fe8d6f Compare October 8, 2025 11:36
@vercel vercel Bot temporarily deployed to Preview – crisp October 8, 2025 11:36 Inactive
@vercel vercel Bot temporarily deployed to Preview – enclave-docs October 8, 2025 11:36 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: 4

🧹 Nitpick comments (8)
examples/CRISP/server/src/server/repo.rs (1)

87-112: Collapse the double modify into a single call

We mutate the same record twice in succession to bump start_time and status. Folding both field writes into one modify keeps the operation atomic, trims a store roundtrip, and narrows the window for racing updates.

Apply this diff to combine the updates:

-        self.store
-            .modify(&key, |e3_obj: Option<E3Crisp>| {
-                e3_obj.map(|mut e| {
-                    e.start_time = start_time;
-                    e
-                })
-            })
-            .await
-            .map_err(|_| eyre::eyre!("Could not update start_time for '{key}'"))?;
-
-        self.store
-            .modify(&key, |e3_obj: Option<E3Crisp>| {
-                e3_obj.map(|mut e| {
-                    e.status = "Active".to_string();
-                    e
-                })
-            })
+        self.store
+            .modify(&key, |e3_obj: Option<E3Crisp>| {
+                e3_obj.map(|mut e| {
+                    e.start_time = start_time;
+                    e.status = "Active".to_string();
+                    e
+                })
+            })
             .await
-            .map_err(|_| eyre::eyre!("Could not update status for '{key}'"))?;
+            .map_err(|_| eyre::eyre!("Could not update start_time/status for '{key}'"))?;
examples/CRISP/sdk/tsconfig.json (1)

2-11: Harden SDK tsconfig for consumers (target/lib/rootDir/maps).

Recommend adding explicit target/libs, rootDir, and declaration maps for better DX and browser typings.

Apply this diff:

   "compilerOptions": {
     "composite": true,
     "skipLibCheck": true,
     "module": "ESNext",
     "moduleResolution": "bundler",
     "allowSyntheticDefaultImports": true,
     "strict": true,
     "outDir": "dist",
-    "declaration": true
+    "declaration": true,
+    "declarationMap": true,
+    "rootDir": "src",
+    "target": "ES2022",
+    "lib": ["ES2022", "DOM"]
   },
examples/CRISP/server/src/server/indexer.rs (1)

80-92: External call resiliency to Bitquery (timeouts/backoff/pagination).

The "10000" limit and TODO are noted. Please ensure the Bitquery client enforces reasonable timeouts, retries with jitter on 429/5xx, and supports pagination/chunking to avoid blocking the handler and OOM on large holder sets.

If not already present in BitqueryClient, consider:

  • Request timeout (e.g., 15–30s) and retry with exponential backoff on retriable errors.
  • Paginated fetch merging with streaming/chunked processing to bound memory.
examples/CRISP/server/src/server/routes/state.rs (2)

49-55: Avoid leaking internal errors in HTTP responses.

Returning raw error strings exposes internals. Prefer generic messages, keep details in logs.

Apply this diff:

-        Err(e) => {
-            info!("Failed to create contract: {:?}", e);
-            return HttpResponse::InternalServerError()
-                .json(format!("Failed to create contract: {}", e));
-        }
+        Err(e) => {
+            info!("Failed to create contract: {:?}", e);
+            return HttpResponse::InternalServerError().body("Failed to create contract");
+        }

And similarly for the send transaction branch:

-        Err(e) => {
-            error!("Failed to send transaction: {:?}", e);
-            return HttpResponse::InternalServerError()
-                .json(format!("Failed to send transaction: {}", e));
-        }
+        Err(e) => {
+            error!("Failed to send transaction: {:?}", e);
+            return HttpResponse::InternalServerError().body("Failed to send transaction");
+        }

Also applies to: 58-61


171-183: Map not-found to 404 and consider GET for caching.

All errors return 500. If the round or hashes are missing, return 404. Also consider making this a GET with round_id as a query param to enable HTTP caching.

Example:

-    match store.e3(incoming.round_id).get_token_holder_hashes().await {
-        Ok(hashes) => HttpResponse::Ok().json(hashes),
-        Err(e) => {
-            error!("Error getting token holders hashes: {:?}", e);
-            HttpResponse::InternalServerError().body("Failed to get token holders hashes")
-        }
-    }
+    match store.e3(incoming.round_id).get_token_holder_hashes().await {
+        Ok(hashes) => HttpResponse::Ok().json(hashes),
+        Err(e) => {
+            error!("Error getting token holders hashes: {:?}", e);
+            // Pseudocode: adjust to your error types
+            if e.to_string().contains("not found") {
+                HttpResponse::NotFound().body("Token holder hashes not found")
+            } else {
+                HttpResponse::InternalServerError().body("Failed to get token holder hashes")
+            }
+        }
+    }

If you stick to POST for consistency, still apply the error mapping.

examples/CRISP/sdk/src/token.ts (3)

32-35: Implement the Merkle proof generation.

This function is a placeholder but directly addresses PR objective #685 (expose merkle tree data for inclusion proofs).

Would you like me to help generate an implementation for this function, or should this be tracked as a follow-up task?


37-40: Placeholder function without implementation.

This function is currently a placeholder. Consider adding a TODO comment or tracking as a follow-up task if not needed for the current PR scope.


51-54: Placeholder function without implementation.

Since the IRoundDetails interface is already defined (lines 45-49), consider implementing this function or documenting when it will be added.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b4b7dc and 5fe8d6f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • examples/CRISP/scripts/evm_deploy.sh (0 hunks)
  • examples/CRISP/sdk/.prettierignore (1 hunks)
  • examples/CRISP/sdk/.prettierrc (1 hunks)
  • examples/CRISP/sdk/package.json (1 hunks)
  • examples/CRISP/sdk/src/constants.ts (1 hunks)
  • examples/CRISP/sdk/src/index.ts (1 hunks)
  • examples/CRISP/sdk/src/token.ts (1 hunks)
  • examples/CRISP/sdk/tests/token.test.ts (1 hunks)
  • examples/CRISP/sdk/tsconfig.json (1 hunks)
  • examples/CRISP/server/src/server/indexer.rs (2 hunks)
  • examples/CRISP/server/src/server/repo.rs (3 hunks)
  • examples/CRISP/server/src/server/routes/state.rs (3 hunks)
  • pnpm-workspace.yaml (1 hunks)
💤 Files with no reviewable changes (1)
  • examples/CRISP/scripts/evm_deploy.sh
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T10:28:56.174Z
Learnt from: ctrlc03
PR: gnosisguild/enclave#657
File: Cargo.toml:32-34
Timestamp: 2025-08-25T10:28:56.174Z
Learning: The examples/CRISP directory has its own Cargo.toml workspace configuration with members like "server", "wasm-crypto", "program/core", "program/client", etc. The root workspace intentionally excludes "examples/CRISP/server", "examples/CRISP/program", and "examples/CRISP/wasm-crypto" to prevent double workspace membership, which is the correct approach for self-contained example workspaces.

Applied to files:

  • pnpm-workspace.yaml
🧬 Code graph analysis (3)
examples/CRISP/sdk/src/token.ts (1)
examples/CRISP/sdk/src/constants.ts (1)
  • CRISP_SERVER_TOKEN_TREE_ENDPOINT (7-7)
examples/CRISP/server/src/server/routes/state.rs (2)
crates/evm-helpers/src/contracts.rs (1)
  • create_write (251-271)
examples/CRISP/server/src/server/repo.rs (2)
  • store (35-37)
  • store (78-80)
examples/CRISP/sdk/tests/token.test.ts (1)
examples/CRISP/sdk/src/token.ts (1)
  • getTreeData (14-30)
⏰ 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). (8)
  • GitHub Check: crisp_e2e
  • GitHub Check: test_enclave_init
  • GitHub Check: build_sdk
  • GitHub Check: rust_unit
  • GitHub Check: integration_prebuild
  • GitHub Check: test_net
  • GitHub Check: test_contracts
  • GitHub Check: Build & Push Image
🔇 Additional comments (7)
pnpm-workspace.yaml (1)

6-6: SDK inclusion in workspace looks good

Adding examples/CRISP/sdk ensures the new package participates in the pnpm workspace. 👍

examples/CRISP/sdk/.prettierrc (1)

1-10: Prettier config is consistent

Settings line up with the rest of the repo conventions for the SDK. No concerns.

examples/CRISP/sdk/src/constants.ts (1)

1-7: Endpoint constant matches the new route

state/token-holders aligns with the server’s token-holder hash endpoint. Looks good.

examples/CRISP/server/src/server/indexer.rs (2)

139-140: Good: start round on Activated instead of re-initializing.

This should prevent overwriting state written during Requested.

Please confirm start_round does not reset fields like token_holder_hashes or e3_params set earlier. If needed, add an integration test covering Requested→Activated preserving those fields.


49-52: Right move: initialize on E3Requested to fix round reset. Please verify idempotence.

This aligns lifecycle with #806. Ensure initialize_round only sets baseline state and does not overwrite any fields already set later in the same handler (e.g., custom params, token-holder hashes).

Run to confirm call sites and guard against regressions:

examples/CRISP/sdk/src/index.ts (1)

7-7: LGTM: clean barrel export.

examples/CRISP/sdk/src/token.ts (1)

45-49: Interface definition looks reasonable.

The IRoundDetails interface is well-defined. Using string types for snapshotBlock and threshold is appropriate for handling large numbers without precision loss.

Comment thread examples/CRISP/sdk/package.json
Comment thread examples/CRISP/sdk/src/token.ts
Comment thread examples/CRISP/sdk/tests/token.test.ts
Comment thread examples/CRISP/server/src/server/routes/state.rs
cedoor
cedoor previously approved these changes Oct 8, 2025

@cedoor cedoor 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.

utACK 👍🏽

Comment thread examples/CRISP/sdk/package.json Outdated
@ctrlc03 ctrlc03 changed the title feat: fetch token data from crisp server feat: fetch round data data from crisp server Oct 8, 2025
@ctrlc03 ctrlc03 changed the title feat: fetch round data data from crisp server feat: fetch token data data from crisp server Oct 8, 2025
@vercel vercel Bot temporarily deployed to Preview – enclave-docs October 8, 2025 13:43 Inactive
@vercel vercel Bot temporarily deployed to Preview – crisp October 8, 2025 13:43 Inactive
@ctrlc03 ctrlc03 requested a review from cedoor October 8, 2025 13:43
@ctrlc03 ctrlc03 deleted the branch dev October 8, 2025 15:11
@ctrlc03 ctrlc03 closed this Oct 8, 2025
@cedoor cedoor reopened this Oct 8, 2025
@cedoor cedoor changed the base branch from main to dev October 8, 2025 15:26
@ctrlc03 ctrlc03 merged commit 4bac0c4 into dev Oct 9, 2025
23 checks passed
@ctrlc03 ctrlc03 deleted the feat/fetch-crisp-token-data branch October 9, 2025 10:26
ctrlc03 added a commit that referenced this pull request Oct 11, 2025
* feat: fetch token data from crisp server

* fix: server resetting data

* chore: add license

* chore: update package.json
ctrlc03 added a commit that referenced this pull request Oct 11, 2025
* feat: fetch token data from crisp server

* fix: server resetting data

* chore: add license

* chore: update package.json
cedoor pushed a commit that referenced this pull request Oct 14, 2025
* feat: fetch token data from crisp server

* fix: server resetting data

* chore: add license

* chore: update package.json
cedoor pushed a commit that referenced this pull request Oct 14, 2025
* feat: fetch token data from crisp server

* fix: server resetting data

* chore: add license

* chore: update package.json
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.

CRISP Server overrides round data on activate event Expose merkle tree data for users that want to generate an inclusion proof

2 participants