├── web ├── src │ ├── vite-env.d.ts │ ├── App.css │ ├── components │ │ ├── ColorModeSwitch.tsx │ │ ├── Login.tsx │ │ ├── Avatars.tsx │ │ ├── SearchResults.tsx │ │ ├── Contribution.tsx │ │ └── ProjectCard.tsx │ ├── pages │ │ └── LandingPage │ │ │ ├── LandingPage.tsx │ │ │ ├── Banner.tsx │ │ │ └── HeroComponent.tsx │ ├── main.tsx │ ├── App.tsx │ ├── index.css │ ├── assets │ │ └── LogoIcon.tsx │ ├── types │ │ └── snarkjs.d.ts │ ├── Layout.tsx │ ├── context │ │ ├── ProjectPageContext.tsx │ │ └── StateContext.tsx │ └── helpers │ │ ├── constants.ts │ │ ├── functions.ts │ │ ├── firebase.ts │ │ └── interfaces.ts ├── .firebaserc ├── vite.config.ts ├── tsconfig.node.json ├── firebase.json ├── .gitignore ├── .eslintrc.cjs ├── index.html ├── tsconfig.json ├── public │ └── vite.svg ├── package.json ├── .default.env └── README.md ├── .github ├── .lighthouserc.json ├── workflows │ ├── check-ceremonies.yml │ ├── validate-ceremony-setup.yml │ ├── check-pr-files.yml │ ├── validate-directory-and-prefix.yml │ ├── deploy-hosting.yml │ ├── lighthouse-pr-audit.yml │ └── setup-ceremony.yml ├── actions │ └── check-ceremonies.js ├── ISSUE_TEMPLATE │ └── bug_report.md ├── pull_request_template.md └── PULL_REQUEST_TEMPLATE │ └── pull_request_template.md ├── LICENSE ├── SECURITY.md ├── README.md ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md └── ceremonies ├── README.md ├── setup_ceremony_config.sh └── rln-trusted-setup-ceremony └── p0tionConfig.json /web/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /web/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 100vw; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /.github/.lighthouserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "ci": { 3 | "collect": { 4 | "settings": { 5 | "preset": "desktop" 6 | } 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /web/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "dev": "p0tion-ci-environment", 4 | "staging": "pse-p0tion-staging", 5 | "prod": "pse-p0tion-production" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /web/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /web/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /web/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # Environment 27 | .env 28 | 29 | # Firebase 30 | .firebase 31 | -------------------------------------------------------------------------------- /web/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { browser: true, es2020: true }, 3 | extends: [ 4 | 'eslint:recommended', 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:react-hooks/recommended', 7 | ], 8 | parser: '@typescript-eslint/parser', 9 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 10 | plugins: ['react-refresh'], 11 | rules: { 12 | 'react-refresh/only-export-components': 'warn', 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Definitely Setup 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/src/components/ColorModeSwitch.tsx: -------------------------------------------------------------------------------- 1 | import { IconButton, useColorMode } from "@chakra-ui/react"; 2 | import { FaSun, FaMoon } from "react-icons/fa"; 3 | 4 | export const ColorModeSwitch: React.FC = () => { 5 | const { colorMode, toggleColorMode } = useColorMode(); 6 | return ( 7 | : } 12 | onClick={toggleColorMode} 13 | /> 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /.github/workflows/check-ceremonies.yml: -------------------------------------------------------------------------------- 1 | name: Check Ceremonies 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | check-ceremonies: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repo 13 | uses: actions/checkout@v2 14 | 15 | - name: Install Node.js 16 | uses: actions/setup-node@v2 17 | with: 18 | node-version: '14' 19 | 20 | - name: Install Dependencies 21 | run: npm ci 22 | 23 | - name: Check ceremonies 24 | run: node .github/actions/check-ceremonies.js 25 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2022", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /.github/actions/check-ceremonies.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const ceremoniesPath = path.join(__dirname, '..', '..', 'ceremonies'); 5 | 6 | fs.readdir(ceremoniesPath, (err, folders) => { 7 | if (err) { 8 | console.error('Failed to list ceremonies:', err); 9 | process.exit(1); 10 | } 11 | 12 | folders.forEach(folder => { 13 | const configPath = path.join(ceremoniesPath, folder, 'p0tionConfig.json'); 14 | 15 | fs.readFile(configPath, 'utf-8', (err, data) => { 16 | if (err) { 17 | console.error(`Failed to read p0tionConfig.json for ceremony "${folder}":`, err); 18 | return; 19 | } 20 | 21 | console.log(`p0tionConfig.json for ceremony "${folder}":\n`, data); 22 | //TODO: call CLI or page devs 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /web/src/components/Login.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { signInWithGitHub, signOutWithGitHub } from "../helpers/p0tion" 3 | import { StateContext } from "../context/StateContext"; 4 | 5 | /** 6 | * Component for GitHub login 7 | */ 8 | export const Login = () => { 9 | 10 | const { user, setUser } = useContext(StateContext); 11 | 12 | const login = async () => { 13 | const user = await signInWithGitHub() 14 | if (setUser) setUser(user) 15 | } 16 | 17 | const handleSignOut = async () => { 18 | await signOutWithGitHub() 19 | if (setUser) setUser(undefined) 20 | } 21 | 22 | return ( 23 | <> 24 | 27 | 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /web/src/pages/LandingPage/LandingPage.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { StateContext } from "../../context/StateContext"; 3 | import { HeroComponent } from "./HeroComponent"; 4 | import SearchResults from "../../components/SearchResults"; 5 | import { CircularProgress } from "@chakra-ui/react"; 6 | 7 | const LandingPage: React.FC = () => { 8 | const { projects, waitingQueue, search, loading } = useContext(StateContext); 9 | 10 | if (loading) { 11 | return ( 12 | Fetching ceremonies... 13 | ) 14 | } 15 | 16 | const render = search ? ( 17 | 18 | ) : ( 19 | 23 | ); 24 | return render; 25 | }; 26 | 27 | export default LandingPage; 28 | -------------------------------------------------------------------------------- /web/src/components/Avatars.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Avatar, Box } from "@chakra-ui/react" 3 | 4 | interface ScrollingAvatarsProps { 5 | images?: string[] 6 | } 7 | 8 | /** 9 | * Display the participants Avatars in a scrolling list 10 | * @param {ScrollingAvatarsProps} - the images to show 11 | */ 12 | const ScrollingAvatars: React.FC = ({ images }) => { 13 | return ( 14 | 23 | {images && images.length > 0 && images.map((image: string, index: any) => ( 24 | 29 | ))} 30 | 31 | ) 32 | } 33 | 34 | export default ScrollingAvatars -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /web/src/main.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from "react-dom/client"; 2 | import App from "./App.tsx"; 3 | import "./index.css"; 4 | import { ChakraProvider, extendTheme,ColorModeScript } from "@chakra-ui/react"; 5 | 6 | import '@fontsource/poppins/700.css' 7 | import '@fontsource/poppins/600.css' 8 | import '@fontsource/poppins/400.css' 9 | import '@fontsource/poppins/200.css' 10 | 11 | //@ts-ignore 12 | if (typeof global === 'undefined') { 13 | //@ts-ignore 14 | window.global = window; 15 | } 16 | 17 | 18 | const colors = { 19 | brand: { 20 | 900: "#000000", 21 | 800: "#000000", 22 | 700: "#000000" 23 | } 24 | }; 25 | 26 | const theme = extendTheme({ 27 | fonts: { 28 | body: "Poppins", 29 | heading: "Sofia Sans" 30 | }, 31 | colors, 32 | config: { 33 | initialColorMode: "dark", 34 | useSystemColorMode: false, 35 | }, 36 | }); 37 | 38 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( 39 | <> 40 | 41 | 42 | 43 | 44 | 45 | ); 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ethereum Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /web/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 2 | import Layout from "./Layout"; 3 | import { StateProvider } from "./context/StateContext"; 4 | import { ProjectPageProvider } from "./context/ProjectPageContext"; 5 | import ProjectPage from "./pages/ProjectPage"; 6 | import LandingPage from "./pages/LandingPage/LandingPage"; 7 | 8 | function App() { 9 | return ( 10 | 11 | 12 | 13 | }> 14 | {/* Render the SearchResults component for the index route */} 15 | } /> 16 | {/* Render the ProjectPage component for the "projects/:title" route */} 17 | 21 | 22 | 23 | } 24 | /> 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /.github/workflows/validate-ceremony-setup.yml: -------------------------------------------------------------------------------- 1 | # Run for each PR that changes files in the ceremonies directory 2 | name: Check PR with new ceremony files 3 | 4 | on: 5 | pull_request: 6 | paths: 7 | - 'ceremonies/**' 8 | 9 | jobs: 10 | check: 11 | runs-on: ubuntu-latest 12 | if: endsWith(github.head_ref, '-ceremony') 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | 18 | - name: Setup Node.js 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: '16' 22 | 23 | - name: Install p0tion 24 | run: npm install -g @p0tion/phase2cli 25 | 26 | # we want to validate that the p0tionConfig.json file is valid 27 | - name: Run npm script and check output 28 | run: | 29 | echo $GITHUB_HEAD_REF 30 | result=$(phase2cli validate --template ./ceremonies/$(echo $GITHUB_HEAD_REF | tr '[:upper:]' '[:lower:]')/p0tionConfig.json) 31 | if [[ "$result" != "true" ]]; then 32 | echo "NPM script returned false." 33 | exit 1 34 | fi 35 | echo "The ceremony files are valid and the circuits have < 1M constraints" 36 | env: 37 | # read only token when the PR originates from a fork 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/check-pr-files.yml: -------------------------------------------------------------------------------- 1 | # check that a PR modified the correct files and nothing more 2 | name: Check PR Files 3 | 4 | on: 5 | pull_request: 6 | paths: 7 | - 'ceremonies/**' 8 | 9 | jobs: 10 | check-files: 11 | runs-on: ubuntu-latest 12 | if: endsWith(github.head_ref, '-ceremony') 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | 18 | - name: Get changed files 19 | id: get-changed-files 20 | uses: jitterbit/get-changed-files@v1 21 | with: 22 | format: 'csv' 23 | 24 | - name: Validate files 25 | run: | 26 | changed_files="${{ steps.get-changed-files.outputs.all }}" 27 | IFS=', ' read -r -a files <<< "$changed_files" 28 | config_found=false 29 | for file in "${files[@]}"; do 30 | if [[ $file == ceremonies/$(echo $GITHUB_HEAD_REF | tr '[:upper:]' '[:lower:]')/p0tionConfig.json ]]; then 31 | config_found=true 32 | else 33 | echo "Invalid file detected: $file" 34 | exit 1 35 | fi 36 | done 37 | 38 | if [[ $config_found = false ]]; then 39 | echo "No p0tionConfig.json file found in PR." 40 | exit 1 41 | fi 42 | 43 | echo "p0tionConfig.json file is present and no other files were changed." 44 | -------------------------------------------------------------------------------- /.github/workflows/validate-directory-and-prefix.yml: -------------------------------------------------------------------------------- 1 | # We need the directory of the ceremony to match the prefix of the ceremony. 2 | name: Validate Directory name and prefix 3 | 4 | on: 5 | pull_request: 6 | paths: 7 | - 'ceremonies/**' 8 | 9 | jobs: 10 | verify: 11 | runs-on: ubuntu-latest 12 | if: endsWith(github.head_ref, '-ceremony') 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Set up Node.js 18 | uses: actions/setup-node@v2 19 | with: 20 | node-version: '16' 21 | 22 | - name: Install jq 23 | run: sudo apt-get install jq -y 24 | 25 | - name: Read JSON and get title 26 | run: | 27 | title=$(jq -r '.title' ./ceremonies/$(echo $GITHUB_HEAD_REF | tr '[:upper:]' '[:lower:]')/p0tionConfig.json) 28 | echo "Title: $title" 29 | echo "TITLE=$title" >> $GITHUB_ENV 30 | 31 | - name: Transform and compare 32 | run: | 33 | prefix=$(echo "${TITLE}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -dc '[:alnum:]-\n\r') 34 | echo "Converted Prefix: $prefix" 35 | DIR_NAME="$(echo $GITHUB_HEAD_REF | tr '[:upper:]' '[:lower:]')" 36 | echo "Dir name: $DIR_NAME" 37 | if [ "$prefix" != $DIR_NAME ]; then 38 | echo "Error: The ceremony artifacts directory name and ceremony prefix do not match!" 39 | exit 1 40 | else 41 | echo "Directory name and ceremony prefix match." 42 | fi -------------------------------------------------------------------------------- /web/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-project", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite --port 8080", 8 | "build": "tsc && vite build", 9 | "deploy:dev": "firebase deploy --only hosting --project dev", 10 | "deploy:staging": "firebase deploy --only hosting --project staging", 11 | "deploy:prod": "firebase deploy --only hosting --project prod", 12 | "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 13 | "preview": "vite preview" 14 | }, 15 | "dependencies": { 16 | "@chakra-ui/react": "^2.7.1", 17 | "@fontsource/poppins": "^5.0.5", 18 | "@octokit/auth-oauth-device": "^6.0.0", 19 | "@octokit/request": "^8.1.1", 20 | "firebase": "^9.23.0", 21 | "randomf": "^0.0.3", 22 | "react": "^18.2.0", 23 | "react-dom": "^18.2.0", 24 | "react-icons": "^4.10.1", 25 | "react-joyride": "^2.5.4", 26 | "react-router-dom": "^6.14.1", 27 | "snarkjs": "^0.7.0", 28 | "types.js": "link:@octokit/auth-oauth-device/dist-types/types.js", 29 | "zod": "^3.21.4" 30 | }, 31 | "devDependencies": { 32 | "@types/react": "^18.0.37", 33 | "@types/react-dom": "^18.0.11", 34 | "@typescript-eslint/eslint-plugin": "^5.59.0", 35 | "@typescript-eslint/parser": "^5.59.0", 36 | "@vitejs/plugin-react": "^4.0.0", 37 | "eslint": "^8.38.0", 38 | "eslint-plugin-react-hooks": "^4.6.0", 39 | "eslint-plugin-react-refresh": "^0.3.4", 40 | "process": "^0.11.10", 41 | "typescript": "^5.0.2", 42 | "vite": "^4.3.9" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /web/.default.env: -------------------------------------------------------------------------------- 1 | # The Firebase Application API key for making request against the services. 2 | # nb. this is going to be auto-generated when creating a new application. 3 | VITE_FIREBASE_API_KEY="YOUR-FIREBASE-API-KEY" 4 | # The URL to Firebase Authentication service (should point to default). 5 | # nb. this is going to be auto-generated when creating a new application. 6 | VITE_FIREBASE_AUTH_DOMAIN="YOUR-FIREBASE-AUTH-DOMAIN" 7 | # The Firebase Application project id (should match with application name). 8 | VITE_FIREBASE_PROJECT_ID="YOUR-FIREBASE-PROJECT-ID" 9 | # The Firebase unique message sender identifier (to recognize the application user). 10 | # nb. this is going to be auto-generated when creating a new application. 11 | VITE_FIREBASE_MESSAGING_SENDER_ID="YOUR-FIREBASE-MESSAGING-SENDER-ID" 12 | # The Firebase unique identifier for your application. 13 | # nb. this is going to be auto-generated when creating a new application. 14 | VITE_FIREBASE_APP_ID="YOUR-FIREBASE-APP-ID" 15 | # The AWS region where your buckets are located. 16 | VITE_AWS_REGION="YOUR-AWS-REGION" 17 | # The postfix used to create S3 buckets for storing the ceremonies artifacts. 18 | VITE_CONFIG_CEREMONY_BUCKET_POSTFIX="YOUR-CEREMONY-BUCKET-POSTFIX" 19 | # The GitHub auth id 20 | VITE_GITHUB_AUTH_ID="YOUR_GITHUB_AUTH_ID" 21 | # the verify contribution endpoint 22 | VITE_FIREBASE_CF_URL_VERIFY_CONTRIBUTION="YOUR_VERIFY_CONTRIBUTION_ENDPOINT" 23 | # GitHub reputation checks 24 | VITE_GITHUB_FOLLOWERS="YOUR_GITHUB_FOLLOWERS_THRESHOLD" 25 | VITE_GITHUB_FOLLOWING="YOUR_GITHUB_FOLLOWING_THRESHOLD" 26 | VITE_GITHUB_REPOS="YOUR_PUBLIC_GITHUB_REPOS_THRESHOLD" -------------------------------------------------------------------------------- /web/src/components/SearchResults.tsx: -------------------------------------------------------------------------------- 1 | // SearchResults.tsx 2 | 3 | import { Box, HStack, SimpleGrid, Text, VStack } from "@chakra-ui/react"; 4 | import { StateContext } from "../context/StateContext"; 5 | import { ProjectCard } from "./ProjectCard"; 6 | import { useContext, useEffect } from "react"; 7 | 8 | export default function SearchResults() { 9 | const { projects, search } = useContext(StateContext); 10 | 11 | useEffect(() => console.log("search", search), [search]); 12 | 13 | // console.log("search for", search) 14 | const results = projects.filter((project) => 15 | project.ceremony.data.title.toLowerCase().includes(search.toLowerCase()) 16 | ); 17 | 18 | return ( 19 | 20 | 21 | {results.length} results found 22 | 23 | 24 | 25 | 26 | 27 | {results.length > 0 ? ( 28 | 29 | {results.map((project, index) => ( 30 | // Render ProjectCard for each project in the results 31 | 32 | ))} 33 | 34 | ) : ( 35 | No results found. 36 | )} 37 | 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /web/src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Sofia+Sans:wght@200;300;400;500;700;800&display=swap"); 2 | 3 | :root { 4 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 5 | line-height: 1.5; 6 | font-weight: 400; 7 | 8 | color-scheme: light dark; 9 | color: rgba(255, 255, 255, 0.87); 10 | background-color: #000000; 11 | padding: 0%; 12 | font-synthesis: none; 13 | text-rendering: optimizeLegibility; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-text-size-adjust: 100%; 17 | } 18 | 19 | a { 20 | font-weight: 500; 21 | color: #646cff; 22 | text-decoration: inherit; 23 | } 24 | a:hover { 25 | color: #535bf2; 26 | } 27 | 28 | body { 29 | margin: 0; 30 | } 31 | 32 | .r-kemksi { 33 | background-color: #646cff; 34 | } 35 | 36 | /* button { 37 | border-radius: 8px; 38 | border: 1px solid transparent; 39 | padding: 0.6em 1.2em; 40 | font-size: 1em; 41 | font-weight: 500; 42 | font-family: inherit; 43 | background-color: #1a1a1a; 44 | cursor: pointer; 45 | transition: border-color 0.25s; 46 | } */ 47 | /* button:hover { 48 | border-color: #646cff; 49 | } */ 50 | /* button:focus, 51 | button:focus-visible { 52 | outline: 0px auto -webkit-focus-ring-color; 53 | } */ 54 | 55 | @media (prefers-color-scheme: light) { 56 | :root { 57 | color: #213547; 58 | background-color: #ffffff; 59 | } 60 | a:hover { 61 | color: #747bff; 62 | } 63 | button { 64 | background-color: #f9f9f9; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.github/workflows/deploy-hosting.yml: -------------------------------------------------------------------------------- 1 | # Deploy to Firebase hosting 2 | name: Deploy to Firebase - deploy on push 3 | 4 | # only on selected branches 5 | on: 6 | push: 7 | branches: [main, dev, staging] 8 | 9 | jobs: 10 | build_and_deploy_to_firebase_hosting: 11 | defaults: 12 | run: 13 | working-directory: ./web 14 | runs-on: ubuntu-latest 15 | environment: 16 | ${{ (github.ref == 'refs/heads/main' && 'p0tion-production') || 17 | (github.ref == 'refs/heads/staging' && 'p0tion-staging') || 18 | (github.ref == 'refs/heads/dev' && 'p0tion-development') }} 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | - name: Install deps and build 23 | run: | 24 | echo "${{ secrets.ENV_FILE }}" > ./.env 25 | npm install -g pnpm 26 | npm install -g firebase-tools 27 | pnpm install 28 | pnpm build 29 | 30 | - name: Write serviceAccountKey to a JSON file 31 | uses: jsdaniell/create-json@v1.2.1 32 | with: 33 | name: "./web/serviceAccountKey.json" 34 | json: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }} 35 | 36 | # Conditional deployment based on the target branch 37 | - name: Deploy 38 | run: | 39 | if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then 40 | pnpm deploy:prod 41 | elif [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then 42 | pnpm deploy:dev 43 | elif [[ "${{ github.ref }}" == "refs/heads/staging" ]]; then 44 | pnpm deploy:staging 45 | fi 46 | env: 47 | GOOGLE_APPLICATION_CREDENTIALS: ./serviceAccountKey.json 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Security vulnerabilities should be disclosed to the project maintainers through [Discord], or alternatively via telegram. 4 | 5 | [Discord]: https://discord.com/invite/bTdZfpc69U 6 | 7 | ## Bug Bounty 8 | 9 | At this time there is no active bug bounty for DefinitelySetup. 10 | 11 | ## Security Patches 12 | 13 | Security vulnerabilities will be patched as soon as responsibly possible, and published as an advisory on this repository (see [advisories]) and on the affected npm packages. 14 | 15 | [advisories]: https://github.com/privacy-scaling-explorations/DefinitelySetup/security/advisories 16 | 17 | ### Supported Versions 18 | 19 | Security patches will be released for the latest minor of a given major release. For example, if an issue is found in versions >=4.6.0 and the latest is 4.8.0, the patch will be released only in version 4.8.1. 20 | 21 | Only critical severity bug fixes will be backported to past major releases. 22 | 23 | | Version | Critical security fixes | Other security fixes | 24 | | ------- | ----------------------- | -------------------- | 25 | | 4.x | :white_check_mark: | :white_check_mark: | 26 | | 3.4 | :white_check_mark: | :x: | 27 | | 2.5 | :white_check_mark: | :x: | 28 | | < 2.0 | :x: | :x: | 29 | 30 | ## Legal 31 | 32 | You are solely responsible for any use of DefinitelySetup and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an on-going duty by any contributor, including the Ethereum Foundation (EF), to correct any flaws or alert you to all or any of the potential risks of utilizing the project. -------------------------------------------------------------------------------- /web/src/assets/LogoIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon, IconProps, useColorMode } from "@chakra-ui/react"; 2 | 3 | export const LogoIcon: React.FC = ({ boxSize, color, ...props }) => { 4 | const { colorMode } = useColorMode(); 5 | return ( 6 | 7 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /web/src/types/snarkjs.d.ts: -------------------------------------------------------------------------------- 1 | /** Declaration file generated by dts-gen */ 2 | 3 | declare module "snarkjs" { 4 | export = snarkjs 5 | 6 | declare const snarkjs: { 7 | fflonk: { 8 | exportSolidityCallData: any 9 | exportSolidityVerifier: any 10 | fullProve: any 11 | prove: any 12 | setup: any 13 | verify: any 14 | } 15 | groth16: { 16 | exportSolidityCallData: any 17 | fullProve: any 18 | prove: any 19 | verify: any 20 | } 21 | plonk: { 22 | exportSolidityCallData: any 23 | fullProve: any 24 | prove: any 25 | setup: any 26 | verify: any 27 | } 28 | powersOfTau: { 29 | beacon: any 30 | challengeContribute: any 31 | contribute: any 32 | convert: any 33 | exportChallenge: any 34 | exportJson: any 35 | importResponse: any 36 | newAccumulator: any 37 | preparePhase2: any 38 | truncate: any 39 | verify: any 40 | } 41 | r1cs: { 42 | exportJson: any 43 | info: any 44 | print: any 45 | } 46 | wtns: { 47 | calculate: any 48 | check: any 49 | debug: any 50 | exportJson: any 51 | } 52 | zKey: { 53 | beacon: any 54 | bellmanContribute: any 55 | contribute: any 56 | exportBellman: any 57 | exportJson: any 58 | exportSolidityVerifier: any 59 | exportVerificationKey: any 60 | importBellman: any 61 | newZKey: any 62 | verifyFromInit: any 63 | verifyFromR1cs: any 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 |

2 |

3 | DefinitelySetup frontend 🌵 4 |

5 |

The frontend for DefinitelySetup.

6 |

7 | 8 | 23 | 24 | | This folder contains the frontend code for DefinitelySetup. DefinitelySetup is a product designed to run and monitor Trusted Setup ceremonies for groth16 based snarks. | 25 | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 26 | 27 | 28 | ## 🛠 Installation 29 | 30 | ### pnpm 31 | 32 | First, ensure **pnpm** is installed on your machine. 33 | 34 | ```bash 35 | npm install -g pnpm 36 | ``` 37 | 38 | Then, install required dependencies with: 39 | 40 | ```bash 41 | pnpm install 42 | ``` 43 | 44 | ## 📜 Usage 45 | 46 | ### Local Development 47 | 48 | **Prerequisities** 49 | 50 | - Node.js version 16.0 or higher. 51 | - pnpm version 8.6.7 or higher. 52 | 53 | Copy the `.default.env` file to `.env`: 54 | 55 | ```bash 56 | cp .env.default .env 57 | ``` 58 | 59 | And add your environment variables. 60 | 61 | ### Build 62 | 63 | Run: 64 | 65 | ```bash 66 | pnpm build 67 | ``` 68 | 69 | ### Start development server 70 | 71 | ```bash 72 | pnpm dev 73 | ``` -------------------------------------------------------------------------------- /web/src/pages/LandingPage/Banner.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from "react"; 2 | import { Box, Text, HStack } from "@chakra-ui/react"; 3 | 4 | // Define the type for banner item props 5 | interface BannerItemProps { 6 | imageUrl: string; 7 | altText: string; 8 | bannerText?: string; 9 | } 10 | 11 | // Define the type for scroll banner props 12 | interface ScrollBannerProps { 13 | imageArray: BannerItemProps[]; 14 | } 15 | 16 | // Create BannerItem component 17 | const BannerItem: FC = ({ bannerText }) => ( 18 | 30 | 31 | {bannerText} 32 | 33 | 34 | ); 35 | 36 | 37 | // Create ScrollBanner component 38 | const ScrollBanner: FC = ({ imageArray }) => { 39 | // Create a merged array to replicate the infinite loop 40 | const loopArray = [...imageArray, ...imageArray]; 41 | 42 | return ( 43 | 55 | 73 | 74 | {loopArray.map((item, index) => ( 75 | 76 | ))} 77 | 78 | 79 | 80 | ); 81 | }; 82 | 83 | export { ScrollBanner, BannerItem }; 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

3 | DefinitelySetup Open BETA 4 |

5 |

The repository for high quality Trusted setups for groth16 based SNARKS.

6 |

7 | 8 | ## Introduction 9 | DefinitelySetup is a product designed to run Trusted Setup ceremonies for Groth16 based snarks. This document provides step-by-step guide on how to utilize DefinitelySetup. 10 | 11 | ### Instructions for DefinitelySetup 12 | 13 | You will generally need to prepare the p0tion infrastructure. See the [p0tion repo](https://github.com/privacy-scaling-explorations/p0tion) for details. A ceremony setup can be initiated either using GitHub actions, triggered by a PR, or by a command in the p0tion CLI (with coordinator privileges). 14 | 15 | Steps for using DefinitelySetup to run your own ceremony: 16 | 17 | - Prepare your files: Before anything else, you will need to prepare your R1CS, wasm, and ceremony config files for uploading to the DefinitelySetup repository. 18 | 19 | - Create a Pull Request: Once your files are ready, you'll need to create a pull request (PR) in the DefinitelySetup repository. Use the provided PR template to guide you in filling out the necessary information. 20 | 21 | - Approval and Merging: If your circuit's constraint size is less than 1M, your PR will be automatically approved and merged. 22 | 23 | - Starting the Ceremony: Once your PR is merged, the ceremony will commence. You and other users will be able to see the ceremony on the DefinitelySetup website. 24 | 25 | - Contribute via the CLI: During the ceremony, you can use the provided CLI to contribute to the process. Detailed instructions for using the CLI will be provided on the DefinitelySetup website. The browser can also be used if the circuit size is sufficiently small. 26 | 27 | - Download Finalized Zkeys: After the ceremony concludes, the finalized zkeys will be made available for download. Ensure to check back frequently for updates or await notifications regarding completion. 28 | 29 | Please note that these are the fundamental steps and additional details or steps may be necessary based on the specifics of your project or ceremony configuration. 30 | 31 | Remember, DefinitelySetup is designed to simplify and streamline the process of running Trusted Setup ceremonies, and we're here to support you through each step of the process. 32 | -------------------------------------------------------------------------------- /web/src/pages/LandingPage/HeroComponent.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Text, 4 | Heading, 5 | VStack, 6 | HStack, 7 | Spacer, 8 | SimpleGrid 9 | } from "@chakra-ui/react"; 10 | import { HeroComponentProps } from "../../helpers/interfaces"; 11 | import { ProjectCard } from "../../components/ProjectCard"; 12 | import { ScrollBanner } from "./Banner"; 13 | 14 | export function HeroComponent({ projects, waitingQueue }: HeroComponentProps) { 15 | const bannerImages: any[] = [] 16 | const sortedProjects = projects.sort((a, b) => b.ceremony.data.endDate - a.ceremony.data.endDate); 17 | 18 | for (const queue of waitingQueue) { 19 | bannerImages.push({ 20 | imageUrl: "https://res.cloudinary.com/pse-qf-maci/image/upload/v1690230945/Banner_qb6zlf.png", 21 | altText: queue.ceremonyName, 22 | bannerText: `${queue.ceremonyName} Waiting Queue for Circuit ${queue.circuitName}: ${ 23 | queue.waitingQueue ?? "no circuits!" 24 | } ` 25 | }) 26 | } 27 | 28 | return ( 29 | <> 30 | 31 | 32 | 33 | 34 | 42 | 43 | 44 | Ceremonies 45 | 46 | 47 | 48 | 54 | 55 | {projects.length > 0 ? ( 56 | 57 | {sortedProjects.map((project, index) => ( 58 | 59 | ))} 60 | 61 | ) : ( 62 | No ceremonies live yet! 63 | )} 64 | 65 | 66 | 67 | 68 | ); 69 | } -------------------------------------------------------------------------------- /web/src/components/Contribution.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Button, Spinner, Text } from "@chakra-ui/react" 2 | import React, { useState } from "react" 3 | import { contribute } from "../helpers/p0tion" 4 | 5 | /** 6 | * Components that allows to contribute to a ceremony on the browser 7 | * @param props 8 | * @returns 9 | */ 10 | export const Contribution = (props: any): React.JSX.Element => { 11 | const [ status, setStatus ] = useState("") 12 | const [ isLoading, setIsLoading ] = useState(false) 13 | const [ attestationLink, setAttestationLink ] = useState("") 14 | 15 | const ceremonyId = props.ceremonyId 16 | 17 | // function that is passed to the contribute function to update the status of the contribution 18 | const handleChanges = (message: string, loading?: boolean, attestationLink?: string) => { 19 | setStatus(message) 20 | if (typeof loading === 'boolean') setIsLoading(loading) 21 | if (typeof attestationLink === 'string') { 22 | setAttestationLink(attestationLink) 23 | } 24 | } 25 | 26 | return ( 27 | <> 28 | 29 | 30 | { 31 | status === "" && 32 | Press contribute to join the ceremony 33 | } 34 | If contributing on your phone, please do not leave the current browser tab 35 | 36 | 37 | {status} 38 | {isLoading && } 39 | 40 | { 41 | status === "" && 42 | 45 | } 46 | { 47 | attestationLink && 48 | 49 | 52 | 53 | } 54 | 55 | 56 | ) 57 | } -------------------------------------------------------------------------------- /web/src/components/ProjectCard.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | import { 4 | VStack, 5 | HStack, 6 | Text, 7 | Badge, 8 | Heading, 9 | Breadcrumb, 10 | BreadcrumbItem 11 | } from "@chakra-ui/react"; 12 | 13 | import { Project } from "../helpers/interfaces"; 14 | 15 | 16 | interface ProjectCardProps { 17 | project: Project; 18 | } 19 | 20 | export function ProjectCard({ project }: ProjectCardProps) { 21 | // Format a date to the form "mm.dd.yy" 22 | const formatDate = (date: Date): string => 23 | `${String(date.getMonth() + 1).padStart(2, "0")}.${String(date.getDate()).padStart(2, "0")}.${String(date.getFullYear()).slice(-2)}`; 24 | 25 | // Return a truncated string with the start and end, and an ellipsis in the middle 26 | const truncateString = (str: string, numCharacters = 5): string => 27 | str.length <= numCharacters * 2 ? str : `${str.slice(0, numCharacters)}...${str.slice(-numCharacters)}`; 28 | 29 | // Get a human-readable string indicating how far in the future or past a date is 30 | const getTimeDifference = (date: Date): string => { 31 | const currentDate = new Date(); 32 | const differenceInTime = date.getTime() - currentDate.getTime(); 33 | const differenceInDays = Math.round(differenceInTime / (1000 * 3600 * 24)); 34 | 35 | if (differenceInDays < 0) return `${Math.abs(differenceInDays)} days ago`; 36 | if (differenceInDays > 0) return `${differenceInDays} days from now`; 37 | return "Today"; 38 | }; 39 | 40 | return ( 41 | 42 | 43 | 44 | {project.ceremony.data.title} 45 | {project.ceremony.data.description} 46 | 47 | 48 | 49 | 56 | 57 | {project.ceremony.data.timeoutMechanismType ? "Fixed" : "Flexible"} 58 | 59 | Penalty: {project.ceremony.data.penalty} 60 | {project.ceremony.data.state} 61 | {project.ceremony.data.type} 62 | {truncateString(project.ceremony.uid, 5)} 63 | 64 | 65 | 66 | 67 | {formatDate(new Date(project.ceremony.data.startDate))} 68 | 69 | 70 | 71 | Deadline: {getTimeDifference(new Date(project.ceremony.data.endDate))} 72 | 73 | 74 | 75 | 76 | 77 | 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /.github/workflows/lighthouse-pr-audit.yml: -------------------------------------------------------------------------------- 1 | name: Frontend-Lighthouse 2 | 3 | 4 | on: 5 | pull_request: 6 | paths: 7 | - 'web/**' 8 | 9 | jobs: 10 | build_and_preview: 11 | runs-on: ubuntu-22.04 12 | defaults: 13 | run: 14 | working-directory: ./web 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - uses: pnpm/action-setup@v2 20 | with: 21 | version: 8 22 | 23 | - uses: actions/setup-node@v3 24 | with: 25 | node-version: '20' 26 | cache: 'pnpm' 27 | cache-dependency-path: './web/pnpm-lock.yaml' 28 | 29 | - name: Install deps and build 30 | run: | 31 | echo "${{ secrets.PREVIEW_ENV_FILE }}" > ./.env 32 | 33 | pnpm install 34 | pnpm build 35 | 36 | - uses: FirebaseExtended/action-hosting-deploy@v0 37 | id: firebase_preview_url 38 | with: 39 | repoToken: "${{ secrets.GITHUB_TOKEN }}" 40 | firebaseServiceAccount: "${{ secrets.PREVIEW_FIREBASE_SERVICE_ACCOUNT }}" 41 | expires: 2d 42 | projectId: pse-p0tion-staging 43 | channelId: "preview-${{ github.sha }}" 44 | entryPoint: ./web/ 45 | 46 | - name: '[Mobile] Audit preview URL with Lighthouse' 47 | id: lighthouse_audit_mobile 48 | uses: treosh/lighthouse-ci-action@v10 49 | with: 50 | urls: ${{ steps.firebase_preview_url.outputs.details_url }} 51 | temporaryPublicStorage: true 52 | 53 | - name: '[Desktop] Audit preview URL with Lighthouse' 54 | id: lighthouse_audit_desktop 55 | uses: treosh/lighthouse-ci-action@v10 56 | with: 57 | urls: ${{ steps.firebase_preview_url.outputs.details_url }} 58 | temporaryPublicStorage: true 59 | configPath: './.github/.lighthouserc.json' 60 | 61 | - name: Format lighthouse score 62 | id: format_lighthouse_score 63 | uses: actions/github-script@v3 64 | with: 65 | github-token: ${{secrets.GITHUB_TOKEN}} 66 | script: | 67 | const score = res => res >= 90 ? '🟢' : res >= 50 ? '🟠' : '🔴' 68 | const formatResult = (res) => Math.round((res * 100)) 69 | 70 | const desktop_result = ${{ steps.lighthouse_audit_desktop.outputs.manifest }}[0].summary 71 | const desktop_links = ${{ steps.lighthouse_audit_desktop.outputs.links }} 72 | Object.keys(desktop_result).forEach(key => desktop_result[key] = formatResult(desktop_result[key])) 73 | 74 | const mobile_result = ${{ steps.lighthouse_audit_mobile.outputs.manifest }}[0].summary 75 | const mobile_links = ${{ steps.lighthouse_audit_mobile.outputs.links }} 76 | Object.keys(mobile_result).forEach(key => mobile_result[key] = formatResult(mobile_result[key])) 77 | 78 | const comment = [ 79 | `⚡️ [(Desktop) Lighthouse report](${Object.values(desktop_links)[0]}) for the changes in this PR:`, 80 | '| Category | Score |', 81 | '| --- | --- |', 82 | `| ${score(desktop_result.performance)} Performance | ${desktop_result.performance} |`, 83 | `| ${score(desktop_result.accessibility)} Accessibility | ${desktop_result.accessibility} |`, 84 | `| ${score(desktop_result['best-practices'])} Best practices | ${desktop_result['best-practices']} |`, 85 | `| ${score(desktop_result.seo)} SEO | ${desktop_result.seo} |`, 86 | `| ${score(desktop_result.pwa)} PWA | ${desktop_result.pwa} |`, 87 | ' ', 88 | `⚡️ [(Mobile) Lighthouse report](${Object.values(mobile_links)[0]}) for the changes in this PR:`, 89 | '| Category | Score |', 90 | '| --- | --- |', 91 | `| ${score(mobile_result.performance)} Performance | ${mobile_result.performance} |`, 92 | `| ${score(mobile_result.accessibility)} Accessibility | ${mobile_result.accessibility} |`, 93 | `| ${score(mobile_result['best-practices'])} Best practices | ${mobile_result['best-practices']} |`, 94 | `| ${score(mobile_result.seo)} SEO | ${mobile_result.seo} |`, 95 | `| ${score(mobile_result.pwa)} PWA | ${mobile_result.pwa} |`, 96 | ' ', 97 | `*Lighthouse ran on [${Object.keys(mobile_links)[0]}](${Object.keys(mobile_links)[0]})*` 98 | ].join('\n') 99 | core.setOutput("comment", comment); 100 | 101 | - name: Add comment to PR 102 | id: comment_to_pr 103 | uses: marocchino/sticky-pull-request-comment@v1 104 | with: 105 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 106 | number: ${{ github.event.issue.number }} 107 | header: lighthouse 108 | message: | 109 | ${{ steps.format_lighthouse_score.outputs.comment }} -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | :tada: Thank you for being interested in contributing to DefinitelySetup! :tada: 4 | 5 | Feel welcome and read the following sections in order to know how to ask questions and how to work on something. 6 | 7 | All members of our community are expected to follow our [Code of Conduct](/CODE_OF_CONDUCT.md). Please make sure you are welcoming and friendly in all of our spaces. 8 | 9 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. There is a lot we want to achieve, and this can only be made possible thanks to your support. 👏 10 | 11 | ## Issues 12 | 13 | The best way to contribute to our projects is by opening a [new issue](https://github.com/privacy-scaling-explorations/DefinitelySetup/issues) or tackling one of the issues listed [here](https://github.com/privacy-scaling-explorations/DefinitelySetup/contribute). 14 | 15 | ## Pull Requests 16 | 17 | Pull requests are great if you want to add a feature or fix a bug. Here's a quick guide: 18 | 19 | 1. Fork the repo. 20 | 21 | 2. Run the tests. We only take pull requests with passing tests. 22 | 23 | 3. Add a test for your change. Only refactoring and documentation changes require no new tests. 24 | 25 | 4. Make sure to check out the [Style Guide](/CONTRIBUTING#style-guide) and ensure that your code complies with the rules. 26 | 27 | 5. Make the test pass. 28 | 29 | 6. Commit your changes. 30 | 31 | 7. Push to your fork and submit a pull request on our `dev` branch. Please provide us with some explanation of why you made the changes you made. For new features make sure to explain a standard use case to us. 32 | 33 | ## CI (Github Actions) Tests 34 | 35 | We use GitHub Actions to test each PR before it is merged. 36 | 37 | When you submit your PR (or later change that code), a CI build will automatically be kicked off. A note will be added to the PR, and will indicate the current status of the build. 38 | 39 | ## Style Guide 40 | 41 | ### Code rules 42 | 43 | We always use ESLint and Prettier. To check that your code follows the rules, simply run the npm script `yarn lint`. When committing, `eslint` is run automatically, so you will be required to fix any error before being able to push a commit. We highly recommend to tackle warnings as well. 44 | 45 | ### Commits rules 46 | 47 | For commits it is recommended to use [Conventional Commits](https://www.conventionalcommits.org). 48 | 49 | Don't worry if it looks complicated, after `git add`, `git commit` will make the next steps interactive. 50 | 51 | Each commit message consists of a **header**, a **body** and a **footer**. The **header** has a special format that includes a **type**, a **scope** and a **subject**: 52 | 53 | (): 54 | 55 | 56 | 57 |