diff --git a/.eslintignore b/.eslintignore index 240d8094..6c822ea8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,14 +1,10 @@ node_modules dist -.next coverage build typechain-types .eslintrc.js commitlint.config.js -subgraph/generated -public/mockServiceWorker.js zkeys -playwright-report -test-results -next.config.js +interface/playwright.config.ts +interface/playwright/fixtures.ts \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 9594edad..8bee0e46 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,7 +10,6 @@ module.exports = { extends: [ "airbnb", "prettier", - "next/core-web-vitals", "plugin:import/recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", @@ -20,26 +19,23 @@ module.exports = { "plugin:@typescript-eslint/stylistic", "plugin:@typescript-eslint/stylistic-type-checked", "plugin:import/typescript", - "plugin:react/recommended", - "plugin:playwright/playwright-test", ], - plugins: ["json", "prettier", "unused-imports", "import", "@typescript-eslint", "react-hooks"], + plugins: ["json", "prettier", "unused-imports", "import", "@typescript-eslint"], parser: "@typescript-eslint/parser", env: { - browser: true, node: true, - jest: true, + mocha: true, es2022: true, }, settings: { react: { - version: "18", + version: "999.999.999", }, "import/resolver": { typescript: {}, node: { - extensions: [".ts", ".js", ".tsx", ".jsx"], - moduleDirectory: ["node_modules", "src", "playwright"], + extensions: [".ts", ".js"], + moduleDirectory: ["node_modules", "ts", "src"], }, }, }, @@ -63,15 +59,7 @@ module.exports = { "import/no-extraneous-dependencies": [ "error", { - devDependencies: [ - "**/*.test.ts", - "./src/test-msw.ts", - "./src/test-setup.ts", - "./src/lib/eas/*.ts", - "./playwright/**/*.ts", - "./playwright.config.ts", - "./vitest.config.ts", - ], + devDependencies: ["**/*.test.ts", "**/__benchmarks__/**"], }, ], "no-debugger": isProduction ? "error" : "off", @@ -113,86 +101,9 @@ module.exports = { "error", { builtinGlobals: true, - allow: [ - "alert", - "location", - "event", - "history", - "name", - "status", - "Option", - "Image", - "Lock", - "test", - "expect", - "describe", - "beforeAll", - "afterAll", - ], + allow: ["location", "event", "history", "name", "status", "Option", "test", "expect"], }, ], "@typescript-eslint/restrict-template-expressions": ["error", { allowNumber: true }], - - "react/jsx-filename-extension": [ - "error", - { - extensions: [".tsx", ".jsx", ".js"], - }, - ], - "react/no-unknown-property": ["error", { ignore: ["tw", "global", "jsx"] }], - "react/jsx-sort-props": [ - "error", - { - callbacksLast: true, - shorthandFirst: true, - ignoreCase: true, - reservedFirst: true, - }, - ], - "react/sort-prop-types": [ - "error", - { - callbacksLast: true, - }, - ], - "react/react-in-jsx-scope": "off", - "react/jsx-boolean-value": "error", - "react/jsx-handler-names": "error", - "react/prop-types": "error", - "react/jsx-no-bind": "error", - "react-hooks/rules-of-hooks": "error", - "react/no-array-index-key": "warn", - "jsx-a11y/no-static-element-interactions": "warn", - "jsx-a11y/click-events-have-key-events": "warn", - "jsx-a11y/anchor-is-valid": "warn", - "react/jsx-props-no-spreading": "off", - "react/forbid-prop-types": "off", - "react/state-in-constructor": "off", - "react/jsx-fragments": "off", - "react/static-property-placement": ["off"], - "react/jsx-newline": ["error", { prevent: false }], - "jsx-a11y/label-has-associated-control": "off", - "jsx-a11y/label-has-for": "off", - "react/require-default-props": [ - "error", - { - functions: "defaultArguments", - }, - ], - "react/no-unused-prop-types": "error", - "react/function-component-definition": ["error", { namedComponents: ["arrow-function"] }], - - "playwright/prefer-lowercase-title": "error", - "playwright/prefer-to-be": "error", - "playwright/prefer-to-have-length": "error", - "playwright/prefer-strict-equal": "error", - "playwright/max-nested-describe": ["error", { max: 1 }], - "playwright/no-restricted-matchers": [ - "error", - { - toBeFalsy: "Use `toBe(false)` instead.", - not: null, - }, - ], }, }; diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh new file mode 100644 index 00000000..733197ed --- /dev/null +++ b/.github/scripts/build.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -ex + +cp packages/coordinator/.env.example packages/coordinator/.env + +sed -i "s|^\(COORDINATOR_RPC_URL=\).*|\1$1|" packages/coordinator/.env +sed -i "s|^\(COORDINATOR_ADDRESSES=\).*|\1$2|" packages/coordinator/.env +sed -i "s|^\(COORDINATOR_ALLOWED_ORIGINS=\).*|\1$3|" packages/coordinator/.env + +aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin 490752553772.dkr.ecr.eu-central-1.amazonaws.com + +docker build -t maci-coordinator -f packages/coordinator/apps/Dockerfile . +docker tag maci-coordinator:latest 490752553772.dkr.ecr.eu-central-1.amazonaws.com/maci-coordinator:latest +docker push 490752553772.dkr.ecr.eu-central-1.amazonaws.com/maci-coordinator:latest + +exit 0 diff --git a/.github/scripts/deploy.sh b/.github/scripts/deploy.sh new file mode 100644 index 00000000..3d987b14 --- /dev/null +++ b/.github/scripts/deploy.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -ex + +tasks="maci-coordinator" +for task in $tasks; do + maci_coordinator_revision=$(aws ecs describe-task-definition --task-definition $task --query "taskDefinition.revision") + aws ecs update-service --cluster maci-coordinator --service $task --force-new-deployment --task-definition $task:$maci_coordinator_revision +done + +for loop in {1..3}; do + [ "$loop" -eq 3 ] && exit 1 + aws ecs wait services-stable --cluster maci-coordinator --services $tasks && break || continue +done diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8e3634bf..6ff76288 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - command: ["prettier", "types", "lint", "test"] + command: ["prettier", "types", "lint"] runs-on: ubuntu-22.04 @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Use Node.js 20 uses: actions/setup-node@v4 diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index fe2541d3..955b0447 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -17,7 +17,7 @@ jobs: fetch-depth: 0 - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Use Node.js 20 uses: actions/setup-node@v4 diff --git a/.github/workflows/coordinator-build.yml b/.github/workflows/coordinator-build.yml new file mode 100644 index 00000000..7e881668 --- /dev/null +++ b/.github/workflows/coordinator-build.yml @@ -0,0 +1,114 @@ +name: Coordinator + +on: + push: + branches: [main] + pull_request: + +env: + COORDINATOR_RPC_URL: "http://localhost:8545" + COORDINATOR_PUBLIC_KEY_PATH: "./pub.key" + COORDINATOR_PRIVATE_KEY_PATH: "./priv.key" + COORDINATOR_TALLY_ZKEY_NAME: "TallyVotes_10-1-2_test" + COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME: "ProcessMessages_10-2-1-2_test" + COORDINATOR_ZKEY_PATH: "./zkeys/" + COORDINATOR_RAPIDSNARK_EXE: "~/rapidsnark/build/prover" + SUBGRAPH_FOLDER: "./node_modules/maci-subgraph" + SUBGRAPH_NAME: ${{ vars.SUBGRAPH_NAME }} + SUBGRAPH_PROVIDER_URL: ${{ vars.SUBGRAPH_PROVIDER_URL }} + SUBGRAPH_DEPLOY_KEY: ${{ secrets.SUBGRAPH_DEPLOY_KEY }} + # interface related variables as they are needed for building the monorepo + NEXT_PUBLIC_CHAIN_NAME: ${{ vars.NEXT_PUBLIC_CHAIN_NAME }} + NEXT_PUBLIC_ADMIN_ADDRESS: ${{ vars.NEXT_PUBLIC_ADMIN_ADDRESS }} + NEXT_PUBLIC_APPROVAL_SCHEMA: ${{ vars.NEXT_PUBLIC_APPROVAL_SCHEMA }} + NEXT_PUBLIC_METADATA_SCHEMA: ${{ vars.NEXT_PUBLIC_METADATA_SCHEMA }} + NEXT_PUBLIC_ROUND_ID: ${{ vars.NEXT_PUBLIC_ROUND_ID }} + NEXT_PUBLIC_SKIP_APPROVED_VOTER_CHECK: false + NEXT_PUBLIC_MACI_ADDRESS: ${{ vars.NEXT_PUBLIC_MACI_ADDRESS }} + NEXT_PUBLIC_TALLY_URL: ${{ vars.NEXT_PUBLIC_TALLY_URL }} + NEXT_PUBLIC_WALLETCONNECT_ID: ${{ secrets.NEXT_PUBLIC_WALLETCONNECT_ID }} + NEXT_PUBLIC_FEEDBACK_URL: ${{ vars.NEXT_PUBLIC_FEEDBACK_URL }} + NEXT_PUBLIC_MACI_START_BLOCK: ${{ vars.NEXT_PUBLIC_MACI_START_BLOCK }} + NEXT_PUBLIC_MACI_SUBGRAPH_URL: ${{ vars.NEXT_PUBLIC_MACI_SUBGRAPH_URL }} + NEXT_PUBLIC_TOKEN_NAME: ${{ vars.NEXT_PUBLIC_TOKEN_NAME }} + NEXT_PUBLIC_MAX_VOTES_TOTAL: ${{ vars.NEXT_PUBLIC_MAX_VOTES_TOTAL }} + NEXT_PUBLIC_MAX_VOTES_PROJECT: ${{ vars.NEXT_PUBLIC_MAX_VOTES_PROJECT }} + BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} + NEXT_PUBLIC_ALCHEMY_ID: ${{ secrets.NEXT_PUBLIC_ALCHEMY_ID }} + NEXT_PUBLIC_START_DATE: ${{ vars.NEXT_PUBLIC_START_DATE }} + NEXT_PUBLIC_REGISTRATION_END_DATE: ${{ vars.NEXT_PUBLIC_REGISTRATION_END_DATE }} + NEXT_PUBLIC_REVIEW_END_DATE: ${{ vars.NEXT_PUBLIC_REVIEW_END_DATE }} + NEXT_PUBLIC_VOTING_END_DATE: ${{ vars.NEXT_PUBLIC_VOTING_END_DATE }} + NEXT_PUBLIC_RESULTS_DATE: ${{ vars.NEXT_PUBLIC_RESULTS_DATE }} + NEXT_PUBLIC_POLL_MODE: ${{ vars.NEXT_PUBLIC_POLL_MODE }} + TEST_MNEMONIC: ${{ secrets.TEST_MNEMONIC }} + WALLET_PRIVATE_KEY: "" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "pnpm" + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install --yes \ + build-essential \ + libgmp-dev \ + libsodium-dev \ + nasm \ + nlohmann-json3-dev + + - name: Install + run: | + pnpm install --frozen-lockfile --prefer-offline + + - name: Build + run: | + pnpm run build + + - name: Run hardhat + run: | + pnpm run hardhat & + sleep 5 + working-directory: packages/coordinator + + - name: Download rapidsnark (1c137) + run: | + mkdir -p ~/rapidsnark/build + wget -qO ~/rapidsnark/build/prover https://maci-devops-zkeys.s3.ap-northeast-2.amazonaws.com/rapidsnark-linux-amd64-1c137 + chmod +x ~/rapidsnark/build/prover + + - name: Download circom Binary v2.1.6 + run: | + wget -qO ${{ github.workspace }}/circom https://github.com/iden3/circom/releases/download/v2.1.6/circom-linux-amd64 + chmod +x ${{ github.workspace }}/circom + sudo mv ${{ github.workspace }}/circom /bin/circom + + - name: Download zkeys + run: | + pnpm download-zkeys:test + + - name: Generate keypair + run: | + pnpm generate-keypair + working-directory: packages/coordinator + + - name: Test + run: pnpm run test + working-directory: packages/coordinator diff --git a/.github/workflows/coordinator-deploy.yml b/.github/workflows/coordinator-deploy.yml new file mode 100644 index 00000000..58665e92 --- /dev/null +++ b/.github/workflows/coordinator-deploy.yml @@ -0,0 +1,37 @@ +name: CoordinatorDeploy +on: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + deploy: + runs-on: ubuntu-22.04 + permissions: + id-token: write + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::490752553772:role/maci-coordinator-ecs-deploy-slc + role-duration-seconds: 2700 + aws-region: eu-central-1 + + - name: Build and Push images to ECR + run: | + .github/scripts/build.sh ${{ secrets.COORDINATOR_RPC_URL }} ${{ secrets.COORDINATOR_ADDRESSES }} ${{ secrets.COORDINATOR_ALLOWED_ORIGINS }} + + - name: Create Deployment + run: | + .github/scripts/deploy.sh diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 4c3fe025..f83c5b26 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -54,7 +54,7 @@ jobs: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Use Node.js 20 uses: actions/setup-node@v4 @@ -96,14 +96,17 @@ jobs: if: steps.playwright-cache.outputs.cache-hit != 'true' run: |- pnpm run install:chromium + working-directory: packages/interface - name: Build run: pnpm run build + working-directory: packages/interface - name: Run Playwright tests uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a with: run: pnpm run test:e2e + working-directory: packages/interface - uses: actions/upload-artifact@v4 if: always() diff --git a/.gitignore b/.gitignore index d36a51f6..6f4ab1f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,22 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies -/node_modules -/.pnp +node_modules +.pnp .pnp.js # testing -/coverage -/playwright-report -/test-results +coverage +playwright-report +test-results # next.js -/.next/ -/out/ +.next/ +out/ next-env.d.ts # production -/build +build # misc .DS_Store diff --git a/.husky/pre-commit b/.husky/pre-commit index 035932cf..ae5682d2 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -pnpm exec lint-staged && pnpm run types +pnpm lint && pnpm run types diff --git a/README.md b/README.md index bd5f0d47..012620f2 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,13 @@ -# MACI-RPGF +# MACI Platform -
+MACI Platform is a complete solution for running voting and funding rounds using [MACI](https://maci.pse.dev). -[](https://easy-retro-pgf.vercel.app) +It is comprised of two components: -## Documentation - -MACI-RPGF uses EAS as backbone to run Retroactive Public Goods Funding to reward contributors ([As used by the Optimism Collective](https://community.optimism.io/docs/governance/citizens-house/#how-retro-funding-works)) while adding a privacy layer to reduce bribery and collusion using MACI. - -## Video Tutorial - -A complete installation tutorial can be seen here: - -[![Watch the Video](https://img.youtube.com/vi/86VBbO1E4Vk/0.jpg)](https://www.youtube.com/watch?v=86VBbO1E4Vk) +- Coordinator Service - the complete automation of MACI operations +- Interface - a web app for managing and voting on MACI polls -### MACI-RPGF docs +### MACI-Platform docs - [Setup & Deployment](./docs/01_setup.md) - [Adding Projects & Approving](./docs/02_adding_projects.md) @@ -33,55 +20,39 @@ A complete installation tutorial can be seen here: - [Documentation](https://maci.pse.dev/docs/introduction) -## Supported Networks - -All networks EAS is deployed to are supported. If a network is not supported, you can follow the EAS documentation to deploy the contracts to the network. - -- https://docs.attest.sh/docs/quick--start/contracts - -#### Mainnets - -- Ethereum -- Optimism -- Base -- Arbitrum One & Nova -- Polygon -- Scroll -- Celo -- Linea - -#### Testnets - -- Sepolia -- Optimism Sepolia -- Base Sepolia -- Polygon Mumbai -- Scroll Sepolia - ## Development To run locally follow these instructions: ```sh -git clone https://github.com/privacy-scaling-explorations/maci-rpgf +git clone https://github.com/privacy-scaling-explorations/maci-platform + +pnpm install && pnpm build -cp .env.example .env # and update .env variables +cp packages/interface/.env.example packages/interface/.env # and update .env variables ``` At the very minimum you need to configure the subgraph url, admin address, maci address and the voting periods. For more details head to [Setup & Deployment](./docs/01_setup.md). Once you have set everything run: ```sh -pnpm install - -pnpm run dev +pnpm run dev:interface open localhost:3000 ``` -### Technical details +## Documentation + +MACI-Platform uses EAS as backbone to run Retroactive Public Goods Funding to reward contributors ([As used by the Optimism Collective](https://community.optimism.io/docs/governance/citizens-house/#how-retro-funding-works)) while adding a privacy layer to reduce bribery and collusion using MACI. + +## Video Tutorial + +A complete installation tutorial can be seen here: + +[![Watch the Video](https://img.youtube.com/vi/86VBbO1E4Vk/0.jpg)](https://www.youtube.com/watch?v=86VBbO1E4Vk) + +## Credits + +The interface started as a fork of [easy-rpgf](https://github.com/gitcoinco/easy-retro-pgf), but now has gone a completely different direction and thus we decided to detach the fork to clarify the new direction of the project, which is not focusing anymore on RPGF only, but other types of voting and funding. -- **EAS** - Projects, profiles, etc are all stored on-chain in Ethereum Attestation Service -- **Batched requests with tRPC** - Multiple requests are batched into one (for example when the frontend requests the metadata for 24 projects they are batched into 1 request) -- **Server-side caching of requests to EAS and IPFS** - Immediately returns the data without calling EAS and locally serving ipfs cids. -- **MACI** - Minimal Anti-Collusion Infrastructure (MACI) is an open-source public good that serves as infrastructure for private on-chain voting, handles the rounds and private voting of the badgeholders. +We are very thankful to the developers and all contributors of the [easy-rpgf](https://github.com/gitcoinco/easy-retro-pgf) project, and we hope to continue collaborating and wish to see their project succeed and help more communities/projects get funded. diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000..beafc3c4 --- /dev/null +++ b/lerna.json @@ -0,0 +1,47 @@ +{ + "packages": ["packages/*"], + "version": "0.1.0", + "npmClient": "pnpm", + "changelogPreset": { + "name": "conventionalcommits", + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "refactor", + "section": "Code Refactoring" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "chore", + "section": "Miscellaneous" + }, + { + "type": "docs", + "section": "Miscellaneous" + }, + { + "type": "style", + "section": "Miscellaneous" + }, + { + "type": "test", + "section": "Miscellaneous" + } + ], + "issuePrefixes": ["#"], + "issueUrlFormat": "{{host}}/{{owner}}/{{repository}}/issues/{{id}}", + "commitUrlFormat": "{{host}}/{{owner}}/{{repository}}/commit/{{hash}}", + "compareUrlFormat": "{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}", + "userUrlFormat": "{{host}}/{{user}}" + } +} diff --git a/package.json b/package.json index 8ae1fc6f..b3154bed 100644 --- a/package.json +++ b/package.json @@ -1,159 +1,64 @@ { - "name": "maci-rpgf", + "name": "maci-platform", "version": "0.1.0", - "private": true, + "description": "Minimal Anti-Collusion Infrastructure Platform", + "repository": "https://github.com/privacy-scaling-explorations/maci-rpgf", + "license": "MIT", "scripts": { - "build": "next build", - "dev": "next dev", - "lint": "next lint", - "lint:fix": "next lint --fix", - "start": "next start", - "test": "vitest run", + "build": "lerna run build", + "clean": "lerna exec -- rm -rf node_modules build && rm -rf node_modules", + "commit": "git cz", + "download-zkeys:test": "lerna run download-zkeys:test --scope=maci-coordinator", + "download-zkeys:prod": "lerna run download-zkeys:prod --scope=maci-coordinator", "prettier": "prettier -c .", "prettier:fix": "prettier -w .", - "types": "tsc -p tsconfig.json --noEmit", - "eas:registerSchemas": "npx tsx src/lib/eas/registerSchemas", - "install:chromium": "playwright install chromium", - "test:e2e": "playwright test --project=chromium", - "prepare": "is-ci || husky" - }, - "dependencies": { - "@ethereum-attestation-service/eas-sdk": "^1.5.0", - "@hookform/resolvers": "^3.3.4", - "@nivo/boxplot": "^0.84.0", - "@nivo/line": "^0.84.0", - "@pinata/sdk": "^2.1.0", - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-dropdown-menu": "^2.0.6", - "@rainbow-me/rainbowkit": "^2.0.1", - "@rainbow-me/rainbowkit-siwe-next-auth": "^0.4.0", - "@semaphore-protocol/core": "4.0.0-beta.16", - "@semaphore-protocol/data": "4.0.0-beta.16", - "@t3-oss/env-nextjs": "^0.8.0", - "@tailwindcss/forms": "^0.5.7", - "@tanstack/react-query": "^5.24.1", - "@testing-library/react": "^14.1.2", - "@trpc/client": "11.0.0-next-beta.294", - "@trpc/next": "11.0.0-next-beta.294", - "@trpc/react-query": "11.0.0-next-beta.294", - "@trpc/server": "11.0.0-next-beta.294", - "@vercel/blob": "^0.19.0", - "clsx": "^2.1.0", - "cmdk": "^0.2.0", - "date-fns": "^3.6.0", - "ethers": "^6.13.1", - "formidable": "^3.5.1", - "graphql-request": "^6.1.0", - "lowdb": "^1.0.0", - "lucide-react": "^0.316.0", - "maci-cli": "0.0.0-ci.4d2d340", - "maci-domainobjs": "0.0.0-ci.4d2d340", - "next": "^14.1.0", - "next-auth": "^4.24.5", - "next-themes": "^0.2.1", - "node-fetch-cache": "^4.1.0", - "nuqs": "^1.17.1", - "p-limit": "^5.0.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-hook-form": "^7.49.3", - "react-icons": "^5.0.1", - "react-markdown": "^9.0.1", - "react-number-format": "^5.3.1", - "react-use": "^17.5.0", - "siwe": "^2.1.4", - "sonner": "^1.4.0", - "superjson": "^2.2.1", - "tailwindcss": "^3.4.1", - "tailwind-merge": "^2.2.1", - "tailwind-variants": "^0.1.20", - "viem": "^2.7.15", - "wagmi": "^2.9.8", - "zod": "3.22.4" + "lint": "pnpm run lint:coordinator && pnpm run lint:interface", + "lint:coordinator": "eslint './packages/coordinator/**/*.ts'", + "lint:coordinator:fix": "eslint './packages/coordinator/**/*.ts' --fix", + "lint:interface": "lerna run lint --scope=maci-platform-interface", + "lint:interface:fix": "lerna run lint:fix --scope=maci-platform-interface", + "lint:fix": "pnpm run lint:coordinator:fix && pnpm run lint:interface:fix", + "types": "lerna run types", + "docs": "lerna run docs", + "prepare": "is-ci || husky", + "start": "lerna run start --scope=maci-platform-interface", + "dev:interface": "lerna run dev --scope=maci-platform-interface", + "test:coordinator": "lerna run test --scope=maci-coordinator", + "test:interface:e2e": "lerna run test:e2e --scope=maci-platform-interface", + "hardhat": "lerna run hardhat --scope=maci-platform-interface" }, + "author": "PSE", "devDependencies": { "@commitlint/cli": "^19.3.0", "@commitlint/config-conventional": "^19.2.2", - "@next/eslint-plugin-next": "^14.2.3", - "@playwright/test": "^1.45.0", - "@synthetixio/synpress": "^3.7.3", - "@tailwindcss/typography": "^0.5.10", - "@testing-library/jest-dom": "^6.4.5", - "@types/eslint": "^8.56.2", - "@types/formidable": "^3.4.5", - "@types/lowdb": "^1.0.15", - "@types/node": "^20.11.10", - "@types/node-fetch-cache": "^3.0.5", - "@types/papaparse": "^5.3.14", - "@types/react": "^18.2.48", - "@types/react-dom": "^18.2.18", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "@vitejs/plugin-react": "^4.3.1", - "autoprefixer": "^10.4.17", - "dotenv": "^16.4.1", + "@typescript-eslint/eslint-plugin": "^7.17.0", + "@typescript-eslint/parser": "^7.17.0", + "conventional-changelog-conventionalcommits": "^8.0.0", + "cz-conventional-changelog": "^3.3.0", "eslint": "^8.57.0", "eslint-config-airbnb": "^19.0.4", - "eslint-config-next": "14.2.4", - "eslint-config-prettier": "^9.1.0", + "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-json": "^4.0.0", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-playwright": "^1.6.2", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.3", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.35.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-unused-imports": "^4.0.0", - "happy-dom": "^13.3.2", - "hardhat": "^2.22.3", - "husky": "^9.0.11", + "eslint-plugin-unused-imports": "^3.2.0", + "husky": "^9.1.1", "is-ci": "^3.0.1", - "jsdom": "^24.0.0", - "ky": "^1.2.0", - "lint-staged": "^15.2.7", - "msw": "^2.1.5", - "msw-trpc": "2.0.0-beta.0", - "mws": "^2.0.11", - "next-router-mock": "^0.9.11", - "postcss": "^8.4.33", - "prettier": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.5.11", - "typescript": "^5.3.3", - "vite": "^5.3.1", - "vite-tsconfig-paths": "^4.3.2", - "vitest": "^1.6.0", - "vitest-mock-extended": "^1.3.1" - }, - "ct3aMetadata": { - "initVersion": "7.24.1" - }, - "msw": { - "workerDirectory": "public" + "lerna": "^8.1.7", + "prettier": "^3.3.3", + "typescript": "^5.5.4" }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "ts" - ], - "rootDir": ".", - "roots": [ - "