Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/evm contract verified code #1210

Merged
merged 10 commits into from
Jan 30, 2025
Merged

Conversation

Poafs1
Copy link
Collaborator

@Poafs1 Poafs1 commented Jan 28, 2025

Summary by CodeRabbit

  • New Features

    • Added a comprehensive code editor with file tree navigation.
    • Introduced EVM contract details code preview.
    • Implemented mobile-friendly editor sidebar.
    • Added a new component for displaying contract source code and constructor arguments.
  • Improvements

    • Enhanced source code display for contracts.
    • Added new icons for file representation.
    • Improved file path and source tree generation.
  • Bug Fixes

    • Fixed Monaco editor positioning during window resize.

Copy link

vercel bot commented Jan 28, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
celatone-frontend-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 30, 2025 7:14am
6 Skipped Deployments
Name Status Preview Comments Updated (UTC)
celatone-frontend-main ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am
initia-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am
neutron-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am
osmosis-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am
sei-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am
terra-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 30, 2025 7:14am

Copy link

coderabbitai bot commented Jan 28, 2025

Walkthrough

This pull request introduces a comprehensive set of components and utilities for an advanced code editor system, specifically tailored for EVM contract interactions. The changes include creating a modular editor infrastructure with components like Editor, EditorFileBody, EditorSidebar, EditorTop, and FullEditor, which work together to provide a flexible and interactive code viewing and editing experience. The implementation supports file tree navigation, mobile responsiveness, and integration with EVM contract details, enhancing the overall code exploration and verification workflow.

Changes

File Change Summary
src/lib/components/editor/* Added multiple components: Editor, EditorFileBody, EditorSidebar, EditorTop, FullEditor, FullEditorSidebarMobile with supporting types and helpers.
src/lib/components/icon/SvgIcon.tsx Added new "code-file" icon.
src/lib/pages/evm-contract-details/components/... Introduced ContractCode component for displaying contract source code.
src/lib/styles/globals.css Added Monaco editor positioning rule.
CHANGELOG.md Added feature entry for EVM contract details code preview.

Sequence Diagram

sequenceDiagram
    participant User
    participant FullEditor
    participant EditorSidebar
    participant EditorTop
    participant Editor

    User->>FullEditor: Select/Navigate Files
    FullEditor->>EditorSidebar: Render File Tree
    EditorSidebar-->>User: Display Clickable File Structure
    User->>EditorSidebar: Click File
    EditorSidebar->>FullEditor: Update Selected File
    FullEditor->>EditorTop: Show Selected File Path
    FullEditor->>Editor: Load File Content
    Editor-->>User: Display Code
Loading

Suggested reviewers

  • songwongtp
  • evilpeach

Poem

🐰 Code editor hopping, files in sight,
Monaco dancing with rabbit's delight!
Sidebars unfurl, trees bloom with glee,
EVM contracts, now easy to see!
A coding adventure, pure and bright! 🌟


📜 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 81914ec and e850bcc.

📒 Files selected for processing (1)
  • CHANGELOG.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: CodeQL
  • GitHub Check: Analyze (javascript)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (11)
src/lib/pages/evm-contract-details/components/EvmContractDetailsContract/ContractCode.tsx (2)

37-44: Consider adding aria-label for accessibility.

The button for opening the file tree should have an aria-label for better accessibility.

 <Button
   display={{
     base: "block",
     md: "none",
   }}
   onClick={onOpen}
   size="sm"
   variant="outline-primary"
+  aria-label="Open contract file tree"
 >

62-62: Consider adding validation for constructor arguments format.

The constructor arguments are displayed as-is without any validation or formatting. Consider adding validation to ensure they are in the correct hexadecimal format.

-<TextReadOnly text={constructorArguments} canCopy />
+<TextReadOnly 
+  text={constructorArguments.startsWith('0x') ? constructorArguments : `0x${constructorArguments}`}
+  canCopy 
+/>
src/lib/components/editor/types.ts (1)

1-1: Consider supporting additional EVM-related file extensions.

The EXTENSION_LIB array only includes "sol" (Solidity). Consider adding support for other EVM-related file extensions like "yul" (Yul/inline assembly) and "vy" (Vyper).

-export const EXTENSION_LIB = ["sol"];
+export const EXTENSION_LIB = ["sol", "yul", "vy"];
src/lib/components/editor/FullEditorSidebarMobile.tsx (1)

23-38: Add aria-label for better accessibility.

The drawer implementation looks good, but could benefit from improved accessibility.

-  <Drawer isOpen={isOpen} onClose={onClose} placement="bottom">
+  <Drawer 
+    isOpen={isOpen} 
+    onClose={onClose} 
+    placement="bottom"
+    aria-label="File tree navigation"
+  >
src/lib/components/editor/helpers.ts (1)

14-36: Optimize tree generation performance.

The current implementation uses array operations that could be inefficient for large file trees:

  1. find operation in a loop
  2. slice and join for each path segment
    Consider using a Map for O(1) lookups and maintaining the full path during traversal.
+    let currentPath = '';
     parts.forEach((part, index) => {
-      let existingNode = currentLevel.find((node) => node.name === part);
+      currentPath = index === 0 ? part : `${currentPath}/${part}`;
+      let existingNode = nodeMap.get(currentPath);

       if (!existingNode) {
         const extension = last(split(part, "."));
-        const isFolder = extension ? !EXTENSION_LIB.includes(extension) : false;
+        const isFolder = !extension;
         const isInitializeNodePath = initialFilePath === path;
         const isOpen = index === 0 || isInitializeNodePath;

         existingNode = {
           name: part,
           isOpen,
           children: [],
           isFolder,
           treeLevel: index,
           code,
-          path: parts.slice(0, index + 1).join("/"),
+          path: currentPath,
         };
+        nodeMap.set(currentPath, existingNode);
         currentLevel.push(existingNode);
       }
src/lib/components/editor/EditorFileBody.tsx (2)

5-9: Consider adding validation for the node prop.

The node prop is crucial for rendering, but there's no validation to ensure required properties exist.

Consider adding prop validation:

interface EditorFileBodyProps extends FlexProps {
  node: {
    isFolder: boolean;
    path: string;
    name: string;
    isOpen?: boolean;
  } & SourceTreeNode;
  initialFilePath: string;
  isNoWrap?: boolean;
}

37-43: Add aria-label for better accessibility.

The text component displaying the node name should have an aria-label for screen readers.

 <Text
   variant="body2"
   noOfLines={!isNoWrap ? 1 : undefined}
   whiteSpace={!isNoWrap ? "normal" : "nowrap"}
+  aria-label={`${node.isFolder ? 'Folder' : 'File'}: ${node.name}`}
 >
   {node.name}
 </Text>
src/lib/components/editor/EditorSidebar.tsx (1)

33-33: Consider using useCallback for performance optimization.

The state update logic could benefit from memoization to prevent unnecessary re-renders.

- const [tree, setTree] = useState(sourceTreeNode);
+ const [tree, setTree] = useState(sourceTreeNode);
+ const handleUpdateIsOpen = useCallback(
+   (node: SourceTreeNode, currentTree: SourceTreeNode[]): SourceTreeNode[] =>
+     currentTree.map((n) => ({
+       ...n,
+       isOpen: n.path === node.path ? !n.isOpen : n.isOpen,
+       children: handleUpdateIsOpen(node, n.children),
+     })),
+   []
+ );
src/lib/components/editor/EditorTop.tsx (1)

15-15: Move color constant to theme configuration.

Hardcoded color values should be managed in a theme configuration.

- const vsCodeDarkColor = "#1E1E1E";

Add to your theme configuration file:

export const theme = {
  colors: {
    editor: {
      background: "#1E1E1E"
    }
  }
}
src/lib/components/icon/SvgIcon.tsx (2)

Line range hint 4-10: Consider grouping viewBox constants into an object.

The viewBox constants could be organized into a single object for better maintainability and cleaner code structure.

-const viewboxDefault = "0 0 16 16";
-const viewBox221616 = "-2 -2 16 16";
-const viewBox101616 = "-1 0 16 16";
-const viewBox021616 = "0 -2 16 16";
-const viewBox011616 = "0 -1 16 16";
-const viewBox121616 = "-1 -2 16 16";
+const VIEW_BOX = {
+  default: "0 0 16 16",
+  "221616": "-2 -2 16 16",
+  "101616": "-1 0 16 16",
+  "021616": "0 -2 16 16",
+  "011616": "0 -1 16 16",
+  "121616": "-1 -2 16 16"
+} as const;

Line range hint 1017-1023: Consider using currentColor instead of hardcoded colors.

Some icons like "pin" and "pin-solid" use hardcoded colors. Consider using currentColor for better theme support and consistency.

-        fill="#707E94"
+        fill="currentColor"

Also applies to: 1029-1035

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b61fd52 and 6ec8546.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • src/lib/components/editor/Editor.tsx (1 hunks)
  • src/lib/components/editor/EditorFileBody.tsx (1 hunks)
  • src/lib/components/editor/EditorSidebar.tsx (1 hunks)
  • src/lib/components/editor/EditorTop.tsx (1 hunks)
  • src/lib/components/editor/FullEditor.tsx (1 hunks)
  • src/lib/components/editor/FullEditorSidebarMobile.tsx (1 hunks)
  • src/lib/components/editor/helpers.ts (1 hunks)
  • src/lib/components/editor/types.ts (1 hunks)
  • src/lib/components/icon/SvgIcon.tsx (1 hunks)
  • src/lib/components/module/ModuleSourceCode.tsx (2 hunks)
  • src/lib/pages/evm-contract-details/components/EvmContractDetailsContract/ContractCode.tsx (1 hunks)
  • src/lib/pages/evm-contract-details/components/EvmContractDetailsContract/index.tsx (2 hunks)
  • src/lib/pages/evm-contract-details/index.tsx (1 hunks)
  • src/lib/pages/interact/index.tsx (1 hunks)
  • src/lib/services/types/verification/evm.ts (1 hunks)
  • src/lib/styles/globals.css (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/lib/styles/globals.css
  • src/lib/pages/evm-contract-details/index.tsx
  • src/lib/pages/interact/index.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/lib/components/editor/EditorTop.tsx

[error] 96-96: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (10)
src/lib/pages/evm-contract-details/components/EvmContractDetailsContract/ContractCode.tsx (2)

13-17: LGTM! Well-defined interface with proper typing.

The ContractCodeProps interface is clear and properly typed using the EvmVerifyInfoSourceFile type.


48-56: Verify error handling for invalid file paths.

The FullEditor component receives file paths and content, but there's no visible error handling if the initialFilePath doesn't match any of the provided files.

src/lib/services/types/verification/evm.ts (1)

47-47: LGTM! Well-structured type definition.

The EvmVerifyInfoSourceFile type is properly inferred from the Zod schema, maintaining type safety throughout the application.

src/lib/pages/evm-contract-details/components/EvmContractDetailsContract/index.tsx (1)

51-53: Verify data properties before passing to ContractCode.

The code assumes that data object always has the required properties. Consider adding validation.

src/lib/components/editor/types.ts (1)

3-14: LGTM! Well-structured interfaces.

The FilePath and SourceTreeNode interfaces are well-designed for representing a hierarchical file structure. The SourceTreeNode appropriately extends FilePath with all necessary properties for tree visualization.

src/lib/components/editor/FullEditorSidebarMobile.tsx (1)

13-16: LGTM! Well-defined props interface.

The interface properly extends EditorSidebarProps with the necessary drawer control props.

src/lib/components/module/ModuleSourceCode.tsx (1)

23-23: Verify the Editor component implementation.

The Editor component is imported correctly. However, let's verify its implementation to ensure it properly handles the Monaco Editor initialization and Move syntax highlighting.

✅ Verification successful

The Editor component is properly implemented with Move syntax support

The Editor component correctly wraps MonacoEditor with Move language support, including syntax highlighting and language configuration. All required dependencies are properly installed and configured.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the Editor component implementation and its dependencies

# Check the Editor component implementation
ast-grep --pattern 'export const Editor = ({ $$ }) => { $$ }'

# Check for Monaco Editor and Move syntax configuration
rg -A 10 'loadMoveSyntax|monaco-editor'

Length of output: 7948

src/lib/components/icon/SvgIcon.tsx (3)

354-384: LGTM! New icon implementation follows established patterns.

The new "code-file" icon is well-implemented with proper SVG path definitions and follows the component's icon structure.


Line range hint 1048-1060: LGTM! Component implementation is clean and type-safe.

The SvgIcon component is well-implemented with proper typing and follows React best practices.


Line range hint 1042-1047: LGTM! Type definitions ensure type safety.

The type system is well-designed with proper constraints on icon names and props.

src/lib/components/editor/Editor.tsx Show resolved Hide resolved
src/lib/components/editor/Editor.tsx Show resolved Hide resolved
src/lib/components/editor/helpers.ts Show resolved Hide resolved
src/lib/components/editor/EditorSidebar.tsx Show resolved Hide resolved
src/lib/components/editor/EditorTop.tsx Outdated Show resolved Hide resolved
src/lib/components/editor/FullEditor.tsx Show resolved Hide resolved
src/lib/components/editor/FullEditor.tsx Show resolved Hide resolved
src/lib/components/editor/FullEditor.tsx Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractCode.tsx (1)

26-64: Consider extracting the mobile button styles into a theme constant.

The mobile-specific display styles could be moved to a theme constant for better maintainability and reuse:

-            display={{
-              base: "block",
-              md: "none",
-            }}
+            display={MOBILE_ONLY_DISPLAY}
src/lib/components/editor/EditorTop.tsx (3)

16-24: Consider moving the color value to theme configuration.

Hard-coded color values should be defined in a theme configuration file for better maintainability and consistency across the application.

Consider moving vsCodeDarkColor to your theme configuration:

-const vsCodeDarkColor = "#1E1E1E";

And update the theme configuration (typically in a file like theme.ts):

export const theme = {
  colors: {
    editor: {
      dark: "#1E1E1E"
    }
    // ... other theme values
  }
}

67-77: Enhance accessibility for the close icon.

The close icon button needs proper ARIA attributes for better accessibility.

 <CustomIcon
   name="close"
   boxSize={3}
   color="gray.600"
   cursor="pointer"
+  aria-label="Close file"
+  role="button"
   onClick={(e) => {
     e.stopPropagation();
     onRemove(node, index);
   }}
 />

95-96: Enhance accessibility for the chevron icon.

The chevron icon needs proper ARIA attributes.

-<CustomIcon name="chevron-right" boxSize={3} color="gray.600" />
+<CustomIcon
+  name="chevron-right"
+  boxSize={3}
+  color="gray.600"
+  aria-hidden="true"
+  role="presentation"
+/>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ec8546 and b51d06e.

📒 Files selected for processing (5)
  • CHANGELOG.md (1 hunks)
  • src/lib/components/editor/EditorTop.tsx (1 hunks)
  • src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractCode.tsx (1 hunks)
  • src/lib/pages/evm-contract-details/components/evm-contract-details-contract/index.tsx (2 hunks)
  • src/lib/services/types/verification/evm.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/services/types/verification/evm.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractCode.tsx (1)

1-17: LGTM! Clean imports and well-defined interface.

The component has a clear interface with three required props: sourceFiles, contractPath, and constructorArguments. The imports are well-organized and use proper named imports.

src/lib/pages/evm-contract-details/components/evm-contract-details-contract/index.tsx (1)

43-49: LGTM! Clean conditional rendering.

The ContractCode component is properly rendered based on the currentTab state, with all required props passed correctly.

CHANGELOG.md (1)

42-42: LGTM! Well-formatted changelog entry.

The changelog entry follows the Keep a Changelog format and is placed in the correct section.

src/lib/components/editor/EditorTop.tsx (2)

1-14: LGTM! Well-structured imports and interface definition.

The imports are clean and properly scoped, and the interface follows TypeScript best practices with clear prop types.


26-34: Verify mobile responsiveness of the file list.

The file list's overflow behavior might need adjustments for better mobile experience.

✅ Verification successful

Mobile responsiveness is properly implemented

The file list's overflow behavior is correctly handled with horizontal scrolling, and the component is part of a fully responsive layout system that includes:

  • Horizontal scrolling for file tabs
  • Mobile-optimized sidebar
  • Responsive grid layout
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for responsive design tests or related components
rg -l 'useBreakpointValue|sm:|md:|lg:|xl:|base:' src/

Length of output: 12661


Script:

#!/bin/bash
# Get the complete implementation of EditorTop.tsx and FullEditor.tsx
echo "=== EditorTop.tsx ==="
cat src/lib/components/editor/EditorTop.tsx
echo -e "\n=== FullEditor.tsx ==="
cat src/lib/components/editor/FullEditor.tsx

Length of output: 6477

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractByteCode.tsx (1)

19-25: LGTM! Consider adding aria-label for better accessibility.

The conditional rendering is well-implemented, providing clear feedback when no byte code is available.

Consider adding an aria-label to improve accessibility:

-        <Text variant="body2" color="text.disabled">
+        <Text variant="body2" color="text.disabled" aria-label="No byte code available">
           -
         </Text>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b51d06e and 81914ec.

📒 Files selected for processing (2)
  • src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractByteCode.tsx (2 hunks)
  • src/lib/pages/evm-contract-details/index.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/lib/pages/evm-contract-details/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
src/lib/pages/evm-contract-details/components/evm-contract-details-contract/ContractByteCode.tsx (1)

Line range hint 5-8: Verify the intended type for byteCode prop.

The interface shows byteCode: Option<string> which aligns with the null case handling in the component, but the summary suggests it was changed to string. Please confirm if this was intentional.

Let's verify the type usage across the codebase:

@Poafs1 Poafs1 merged commit f65e52e into develop Jan 30, 2025
13 checks passed
@Poafs1 Poafs1 deleted the feature/evm-contract-verified-code branch January 30, 2025 07:20
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.

2 participants