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

Feat: voice credit per tokens (ERC20 or ETH sent to an address) #1998

Draft
wants to merge 17 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

## Confirmation

> [!IMPORTANT]
> We do not accept minor grammatical fixes (e.g., correcting typos, rewording sentences) unless they significantly improve clarity in technical documentation. These contributions, while appreciated, are not a priority for merging. If there is a grammatical error feel free to message the team.

- [ ] I have read and understand MACI's [contributor guidelines](https://maci.pse.dev/docs/contributing) and [code of conduct](https://maci.pse.dev/docs/contributing/code-of-conduct).
- [ ] I have read and understand MACI's [GitHub processes](https://github.com/privacy-scaling-explorations/maci/discussions/847).
- [ ] I have read and understand MACI's [testing guide](https://maci.pse.dev/docs/testing).
- [ ] I ran and verified that all tests pass according to MACI's [testing guide](https://maci.pse.dev/docs/guides/testing).
57 changes: 57 additions & 0 deletions .github/workflows/relayer-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Relayer

on:
push:
branches: [dev]
pull_request:

env:
RELAYER_RPC_URL: "http://localhost:8545"
TTL: ${{ vars.RELAYER_TTL }}
LIMIT: ${{ vars.RELAYER_LIMIT }}
MONGO_DB_URI: ${{ secrets.RELAYER_MONGO_DB_URI }}
MONGODB_USER: ${{ secrets.MONGODB_USER }}
MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }}
MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }}

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
run: |
pnpm install --frozen-lockfile --prefer-offline

- name: Build
run: |
pnpm run build

- name: Run hardhat
run: |
pnpm run hardhat &
sleep 5
working-directory: apps/relayer

- name: Test
run: pnpm run test:coverage
working-directory: apps/relayer

- name: Stop Hardhat
if: always()
run: kill $(lsof -t -i:8545)
21 changes: 21 additions & 0 deletions apps/relayer/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Rate limit configuation
TTL=60000
LIMIT=10

# Coordinator RPC url
RELAYER_RPC_URL=http://localhost:8545

# MongoDB configuration
MONGO_DB_URI=mongodb://localhost
MONGODB_USER=maci
MONGODB_PASSWORD=
MONGODB_DATABASE=maci-relayer

# Allowed origin host, use comma to separate each of them
ALLOWED_ORIGINS=

# Specify port for coordinator service (optional)
PORT=

# Mnemonic phrase
MNEMONIC=""
32 changes: 32 additions & 0 deletions apps/relayer/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const path = require("path");

module.exports = {
root: true,
env: {
node: true,
jest: true,
},
extends: ["../../.eslintrc.js"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: path.resolve(__dirname, "./tsconfig.json"),
sourceType: "module",
typescript: true,
ecmaVersion: 2022,
experimentalDecorators: true,
requireConfigFile: false,
ecmaFeatures: {
classes: true,
impliedStrict: true,
},
warnOnUnsupportedTypeScriptVersion: true,
},
overrides: [
{
files: ["./ts/**/*.module.ts"],
rules: {
"@typescript-eslint/no-extraneous-class": "off",
},
},
],
};
3 changes: 3 additions & 0 deletions apps/relayer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build/
coverage/
.env
5 changes: 5 additions & 0 deletions apps/relayer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Relayer service

## Instructions

1. Add `.env` file (see `.env.example`).
33 changes: 33 additions & 0 deletions apps/relayer/hardhat.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable @typescript-eslint/no-var-requires */
require("@nomicfoundation/hardhat-toolbox");
const dotenv = require("dotenv");

const path = require("path");

dotenv.config();

const parentDir = __dirname.includes("build") ? ".." : "";
const TEST_MNEMONIC = "test test test test test test test test test test test junk";

module.exports = {
defaultNetwork: "hardhat",
networks: {
localhost: {
url: process.env.RELAYER_RPC_URL || "",
accounts: {
mnemonic: process.env.MNEMONIC || TEST_MNEMONIC,
path: "m/44'/60'/0'/0",
initialIndex: 0,
count: 20,
},
loggingEnabled: false,
},
hardhat: {
loggingEnabled: false,
},
},
paths: {
sources: path.resolve(__dirname, parentDir, "./node_modules/maci-contracts/contracts"),
artifacts: path.resolve(__dirname, parentDir, "./node_modules/maci-contracts/build/artifacts"),
},
};
8 changes: 8 additions & 0 deletions apps/relayer/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "ts",
"compilerOptions": {
"deleteOutDir": true
}
}
106 changes: 106 additions & 0 deletions apps/relayer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"name": "maci-relayer",
"version": "0.1.0",
"private": true,
"description": "Relayer service for MACI",
"main": "build/ts/main.js",
"type": "module",
"exports": {
".": "./build/ts/main.js"
},
"files": [
"build",
"CHANGELOG.md",
"README.md"
],
"scripts": {
"hardhat": "hardhat node",
"build": "nest build",
"run:node": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));'",
"start": "pnpm run run:node ./ts/main.ts",
"start:prod": "pnpm run run:node build/ts/main.js",
"test": "jest --forceExit",
"test:coverage": "jest --coverage --forceExit",
"types": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
"@nestjs/common": "^10.4.7",
"@nestjs/core": "^10.4.7",
"@nestjs/mongoose": "^10.1.0",
"@nestjs/platform-express": "^10.4.7",
"@nestjs/platform-socket.io": "^10.3.10",
"@nestjs/swagger": "^8.0.3",
"@nestjs/throttler": "^6.3.0",
"@nestjs/websockets": "^10.4.7",
"@nomicfoundation/hardhat-ethers": "^3.0.8",
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"date-fns": "^4.1.0",
"dotenv": "^16.4.5",
"ethers": "^6.13.4",
"hardhat": "^2.22.15",
"helmet": "^8.0.0",
"maci-contracts": "workspace:^2.5.0",
"maci-domainobjs": "workspace:^2.5.0",
"mongoose": "^8.9.3",
"mustache": "^4.2.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"ts-node": "^10.9.1"
},
"devDependencies": {
"@nestjs/cli": "^10.4.2",
"@nestjs/schematics": "^10.1.2",
"@nestjs/testing": "^10.4.15",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.2",
"@types/node": "^22.10.5",
"@types/supertest": "^6.0.2",
"fast-check": "^3.23.1",
"jest": "^29.5.0",
"mongodb-memory-server": "^10.1.3",
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"typescript": "^5.7.2"
},
"jest": {
"testTimeout": 900000,
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": ".",
"roots": [
"<rootDir>/ts",
"<rootDir>/tests"
],
"testRegex": ".*\\.test\\.ts$",
"transform": {
"^.+\\.js$": [
"<rootDir>/ts/jest/transform.js",
{
"useESM": true
}
],
"^.+\\.(t|j)s$": [
"ts-jest",
{
"useESM": true
}
]
},
"collectCoverageFrom": [
"**/*.(t|j)s",
"!<rootDir>/ts/main.ts",
"!<rootDir>/ts/jest/*.js",
"!<rootDir>/hardhat.config.js"
],
"coveragePathIgnorePatterns": [
"<rootDir>/ts/sessionKeys/__tests__/utils.ts"
],
"coverageDirectory": "<rootDir>/coverage",
"testEnvironment": "node"
}
}
38 changes: 38 additions & 0 deletions apps/relayer/tests/app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { HttpStatus, ValidationPipe, type INestApplication } from "@nestjs/common";
import { Test } from "@nestjs/testing";
import request from "supertest";

import type { App } from "supertest/types";

import { AppModule } from "../ts/app.module";

describe("Integration", () => {
let app: INestApplication;

beforeAll(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();

app = moduleFixture.createNestApplication();
app.useGlobalPipes(new ValidationPipe({ transform: true }));
await app.listen(3000);
});

afterAll(async () => {
await app.close();
});

test("should throw an error if api is not found", async () => {
const result = await request(app.getHttpServer() as App)
.get("/unknown")
.send()
.expect(404);

expect(result.body).toStrictEqual({
error: "Not Found",
statusCode: HttpStatus.NOT_FOUND,
message: "Cannot GET /unknown",
});
});
});
Loading