Compare commits

..

30 Commits

Author SHA1 Message Date
Vivian Plasencia
c67b888eb6 chore: v4.5.0 2024-10-28 20:23:40 +01:00
Vivian Plasencia
376cd11808 docs(identity): add export import identity to the docs (#887)
re #872
2024-10-28 13:29:35 +01:00
Vivian Plasencia
58132a9478 feat(identity): export point and signature types (#886)
* feat(identity): export point and signature types

re #885

* docs(identity): add the generate commitment function to the readme file
2024-10-28 13:29:03 +01:00
Vivian Plasencia
fadcf19206 chore: v4.4.2 2024-10-23 22:42:39 +02:00
Shikhar Singh
3be17268ab feat: remove prepublish script when creating template with Semaphore CLI (#882)
* feat(cli): remove @semaphore-protocol/cli prepublish script

The idea is to remove the prepublish script from the scripts object of the package.json file of
every cli template when the template is downloaded using the CLI.

BREAKING CHANGE: n

* refactor(cli): add comment

* refactor(cli): create seperate file for removePrePublishScript function

* refactor(cli): using updatedPackageJsonContent var instead of calling readFileSync again
2024-10-23 22:07:48 +02:00
Vivian Plasencia
82cdc60af6 fix: update shebang lines in the ts scripts (#881)
re #880
2024-10-23 10:50:46 +01:00
sripwoud
6c9ede6931 ci: install soldeer in release workflow (#867)
* ci: install `soldeer` in release workflow

* ci: setup soldeer login file (#868)

* chore: trigger release workflow

* chore: format

* ci: set `soldeer` credentials in github workspace

* chore: remove commentouts

* chore: add back tag trigger
2024-10-22 09:20:34 +01:00
cedoor
e6576cdc47 chore: v4.4.1 2024-10-21 12:41:11 +01:00
cedoor
c07dc88490 style: format code with prettier 2024-10-21 12:02:54 +01:00
Yago Pajariño
67060dd412 Update cli monorepo ethers and subgraph web app UI (#841)
* refactor(cli-template-monorepo-ethers): update cli-template-monorepo-ethers web app UI

re #836

* refactor(cli-template-monorepo-subgraph): update cli-template-monorepo-subgraph web app UI

re #836

* refactor(cli-template-monorepo-subgraph): rename subgraph web app on package.json

re #836

* refactor: update yarn.lock

re #836

* chore: fix indentation error on yarn.lock

re 836

* chore: update cli monorepo package.json

re #836

* chore(cli-template-monorepo-ethers): remove .env values

* chore(cli-template-monorepo-subgraph): change .env values

* chore(cli-template-monorepo-ethers): update .gitignore file

* chore(cli-template-monorepo-subgraph): update .gitignore file

* style(cli-template-monorepo-ethers): update globals.css

* refactor(cli-template-monorepo-ethers): replace chakra with plain html+css on cli-ethers page.tsx

* style(cli-template-monorepo-ethers): import globals css in layout

* style(cli-template-monorepo-ethers): remove chakra ui elements

* refactor(cli-template-monorepo-ethers): remove chakra ui from layout

* refactor(cli-template-monorepo-ethers): remove chakra ui from PageContainer, Stepper

* style(cli-template-monorepo-ethers): add font link

* chore(cli-template-monorepo-ethers): remove unused groups page

* style(cli-template-monorepo-ethers): remove chakra ui from group page

* style(cli-template-monorepo-ethers): remove chakra ui from proof page

* style(cli-template-monorepo-ethers): update css and add class names

* style(cli-template-monorepo-ethers): add css declarations

* style(cli-template-monorepo-ethers): add github icon

* style(cli-template-monorepo-ethers): add left arrow on stepper

* style(cli-template-monorepo-ethers): remove chakra from proofs page

* style(cli-template-monorepo-ethers): minor style improvements

* style(cli-template-monorepo-ethers): remove chakra libraries from package.json

* refactor(cli-template-monorepo-ethers): update yarn.lock file after package.json modified

* style(cli-template-monorepo-ethers): fix deepscan issues

* chore(cli-template-monorepo-ethers): remove unused packages and update dotenv version

* style(cli-template-monorepo-ethers): update stylesheet

* chore(cli-template-monorepo-ethers): update github logo

* chore(cli-template-monorepo-ethers): add loader to join group button

* chore(cli-template-monorepo-subgraph): update packages

* style(cli-template-monorepo-subgraph): update stylesheet

* style(cli-template-monorepo-subgraph): update user interface

* chore: update yarn.lock

* style: change styling and add feedback link

* chore(cli-template-monorepo-subgraph): remove unused styles and icons

* chore: remove unused context logs

* chore(cli-template-monorepo-subgraph): change data source subgraph web app

* chore: change repo url

* chore: remove unused hook useSemaphore
2024-10-21 11:58:05 +01:00
Cedoor
a4e540d8f4 chore(website): update roadmap (#878) 2024-10-18 13:03:16 +01:00
Jimmy Chu
79976f33cb Split SemaphoreVerifier key points into a separate library (#875)
* refactor(scripts): added a script to convert bigint to hex

* refactor(contracts): split SemaphoreVerifier verification key points into a separate library (#330)

* chore(contracts): yarn format & lint

* refactor(contracts): update SemaphoreVerifierKeyPts library to be internal

re #330

* chore(contracts): update spacing

* chore(contracts): updated per peer review and added invariant check for VerifierKeyPts lib

* chore(contracts): update invariant check to revert with custom error
2024-10-17 14:21:41 +01:00
cedoor
822530f2cf chore: v4.4.0 2024-10-17 14:19:38 +01:00
Vivian Plasencia
b3f862979d feat(identity): add generate commitment function (#877)
This static method is particularly useful after signature verification, as it allows retrieval of
the corresponding commitment associated with the public key.

re #873
2024-10-17 13:28:49 +02:00
cedoor
06e11d5c34 chore: v4.3.1 2024-10-16 12:20:26 +01:00
cedoor
88d4470b11 ci(circuits): add sudo before running wget command 2024-10-16 12:16:22 +01:00
Vivian Plasencia
bb1c6984b2 ci: add -O flag to the wget command 2024-10-16 13:04:32 +02:00
cedoor
5841327477 ci(circuits): update circom url 2024-10-16 11:52:02 +01:00
cedoor
eab3ab30c6 ci(circuits): update circom url 2024-10-16 11:48:30 +01:00
Cedoor
cd6dc38f9e ci(circuits): set static version of circom (#874)
* fix(circuits): add override for circom_runtime

* chore(circuits): use yarn syntax for overrides

* ci(circuits): set static version of circom
2024-10-16 11:05:07 +01:00
cedoor
3cb1b5757d revert(circuits): set previous circomkit version as static 2024-10-15 11:30:11 +01:00
cedoor
a8db8393c1 chore(circuits): update circomkit config 2024-10-15 11:24:55 +01:00
cedoor
391b571c31 chore(circuits): update circomkit dep version 2024-10-15 11:21:04 +01:00
cedoor
4c2769099f chore(circuits): update dev dependencies 2024-10-15 11:05:08 +01:00
Cedoor
29cabb49d6 build: move poseidon-lite to dependencies (#870) 2024-10-15 10:58:51 +01:00
cedoor
48b0694586 chore: v4.3.0 2024-10-03 12:46:01 +01:00
Cedoor
28684fdb1a Chore/mainnet deployments (#869)
* chore(contracts): deploy semaphore contracts on base

re #865

* chore(contracts): deploy semaphore contracts on linea

re #865

* refactor(data): add types for new networks

re #865
2024-10-03 12:42:36 +01:00
Cedoor
49a16635d8 chore(website): update roadmap.json (#866) 2024-10-01 19:04:11 +01:00
cedoor
4bfe6d8791 chore: v4.2.0 2024-10-01 18:48:37 +01:00
Cedoor
a3d97795fe Chore/new testnets (#864)
* chore(contracts): deploy contracts on base sepolia

re #863

* chore(contracts): deploy contracts on linea sepolia

re #863
2024-10-01 18:36:55 +01:00
89 changed files with 2430 additions and 1548 deletions

View File

@@ -83,7 +83,7 @@ jobs:
sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
- name: Setup Circom
run: wget https://github.com/iden3/circom/releases/latest/download/circom-linux-amd64 && sudo mv ./circom-linux-amd64 /usr/bin/circom && sudo chmod +x /usr/bin/circom
run: sudo wget https://github.com/iden3/circom/releases/download/v2.1.9/circom-linux-amd64 -O /usr/bin/circom && sudo chmod +x /usr/bin/circom
- name: Install dependencies
run: yarn

View File

@@ -111,7 +111,7 @@ jobs:
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
wget https://github.com/iden3/circom/releases/latest/download/circom-linux-amd64 && sudo mv ./circom-linux-amd64 /usr/bin/circom && sudo chmod +x /usr/bin/circom
sudo wget https://github.com/iden3/circom/releases/download/v2.1.9/circom-linux-amd64 -O /usr/bin/circom && sudo chmod +x /usr/bin/circom
yarn workspace @semaphore-protocol/group build
yarn workspace @semaphore-protocol/identity build
yarn workspace @semaphore-protocol/proof build

View File

@@ -17,6 +17,16 @@ jobs:
with:
fetch-depth: 0
- name: Install soldeer
uses: taiki-e/install-action@v2
with:
tool: soldeer
- name: Store soldeer login credential
env:
SOLDEER_TOKEN: ${{ secrets.SOLDEER_TOKEN }}
run: |
echo "$SOLDEER_TOKEN" > "$GITHUB_WORKSPACE"/soldeer_login
- name: Install Node.js
uses: actions/setup-node@v4
with:
@@ -37,6 +47,7 @@ jobs:
run: yarn version:publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
SOLDEER_LOGIN_FILE: ${{ github.workspace }}/soldeer_login
- run: yarn version:release
env:

View File

@@ -19,7 +19,7 @@
"@docusaurus/core": "3.1.1",
"@docusaurus/preset-classic": "3.1.1",
"@mdx-js/react": "^3.0.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/utils": "4.5.0",
"@svgr/webpack": "^5.5.0",
"clsx": "^1.2.1",
"docusaurus-plugin-sass": "^0.2.5",

View File

@@ -109,3 +109,33 @@ After a message is signed, anyone can verify the signature using the message its
// Static method.
Identity.verifySignature(message, signature, identity1.publicKey)
```
## Export and import an identity
A Semaphore Identity can be exported and then imported later for reuse.
### Export an identity
Returns the private key encoded as a base64 string.
```ts
import { Identity } from "@semaphore-protocol/identity"
const identity = new Identity()
const privateKey = identity.export()
```
### Import an identity
Returns a Semaphore identity based on a private key encoded as a base64 string.
```ts
import { Identity } from "@semaphore-protocol/identity"
const identity = new Identity()
const privateKey = identity.export()
const identity2 = Identity.import(privateKey)
```

View File

@@ -53,6 +53,10 @@ Supported networks:
- `arbitrum-sepolia`
- `matic`
- `polygon-amoy`
- `base-sepolia`
- `base`
- `linea-sepolia`
- `linea`
## 🛠 Install

View File

@@ -20,7 +20,7 @@
"dependencies": {
"@graphprotocol/graph-cli": "0.78.0",
"@graphprotocol/graph-ts": "0.35.1",
"@semaphore-protocol/utils": "4.1.0"
"@semaphore-protocol/utils": "workspace:packages/utils"
},
"devDependencies": {
"@types/mustache": "^4.2.2",

View File

@@ -17,18 +17,22 @@
},
{
"name": "LeanIMT Paper",
"done": true
},
{
"name": "Support more Testnets/Mainnets",
"done": true
},
{
"name": "Documentation improvements",
"done": false
},
{
"name": "New Explorer",
"done": false
},
{
"name": "RLN extension",
"done": false
},
{
"name": "Support more Testnets/Mainnets",
"done": false
},
{
"name": "Documentation Revamp",
"done": false
}
]

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/circuits",
"version": "4.1.0",
"version": "4.5.0",
"description": "Semaphore Circom circuits to generate zero-knowledge proofs.",
"license": "MIT",
"files": [
@@ -30,9 +30,9 @@
"devDependencies": {
"@semaphore-protocol/core": "workspace:^",
"@types/mocha": "^10.0.6",
"@zk-kit/baby-jubjub": "1.0.1",
"circomkit": "^0.0.19",
"@zk-kit/baby-jubjub": "1.0.3",
"circomkit": "0.0.19",
"mocha": "^10.2.0",
"poseidon-lite": "^0.2.0"
"poseidon-lite": "^0.3.0"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-contracts-hardhat",
"version": "4.1.0",
"version": "4.5.0",
"description": "Semaphore Hardhat template.",
"license": "Unlicense",
"files": [
@@ -41,9 +41,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.1.0",
"@semaphore-protocol/hardhat": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/core": "4.5.0",
"@semaphore-protocol/hardhat": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -71,7 +71,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.1.0"
"@semaphore-protocol/contracts": "4.5.0"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -20,9 +20,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.1.0",
"@semaphore-protocol/hardhat": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/core": "4.5.0",
"@semaphore-protocol/hardhat": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -50,7 +50,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.1.0"
"@semaphore-protocol/contracts": "4.5.0"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -1,4 +1,4 @@
NEXT_PUBLIC_DEFAULT_NETWORK=localhost
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9
NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
NEXT_PUBLIC_GROUP_ID=0

View File

@@ -1,5 +1,8 @@
NEXT_PUBLIC_DEFAULT_NETWORK=sepolia
NEXT_PUBLIC_INFURA_API_KEY=abf67af1010b4b8d877e04244f1eac3d
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=
NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS=0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f
NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK=https://api.defender.openzeppelin.com/actions/20fce2ae-844b-4ec0-a6a2-90a3350a9d2c/runs/webhook/303216d1-fa7d-4fca-8c5b-7ba1ba544fc7/2T7i9xrkZA5j37hoaQLUuw
NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT=https://api.gelato.digital/relays/v2/sponsored-call
NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID=11155111
NEXT_PUBLIC_GROUP_ID=

View File

@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# testing
/coverage
# next.js
/.next/
/out/
@@ -7,3 +10,18 @@
# production
/build
# misc
.DS_Store
*.pem
# typescript
*.tsbuildinfo
next-env.d.ts
# Auto Generated PWA files
public/sw.js
public/workbox-*.js
public/worker-*.js
public/sw.js.map
public/workbox-*.js.map
public/worker-*.js.map

View File

@@ -9,11 +9,6 @@
"internalType": "address",
"name": "semaphoreAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "_groupId",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
@@ -92,8 +87,8 @@
"type": "function"
}
],
"bytecode": "0x608060405234801561001057600080fd5b5060405161083f38038061083f833981810160405281019061003291906101a8565b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060018190555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c96e71fb600154306040518363ffffffff1660e01b81526004016100d6929190610206565b600060405180830381600087803b1580156100f057600080fd5b505af1158015610104573d6000803e3d6000fd5b50505050505061022f565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061013f82610114565b9050919050565b61014f81610134565b811461015a57600080fd5b50565b60008151905061016c81610146565b92915050565b6000819050919050565b61018581610172565b811461019057600080fd5b50565b6000815190506101a28161017c565b92915050565b600080604083850312156101bf576101be61010f565b5b60006101cd8582860161015d565b92505060206101de85828601610193565b9150509250929050565b6101f181610172565b82525050565b61020081610134565b82525050565b600060408201905061021b60008301856101e8565b61022860208301846101f7565b9392505050565b6106018061023e6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea2646970667358221220f33606b2d5ad7c0dfc5d22afb43476e1974ea7fd160e1f28203a3e433f29cb4964736f6c63430008170033",
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea2646970667358221220f33606b2d5ad7c0dfc5d22afb43476e1974ea7fd160e1f28203a3e433f29cb4964736f6c63430008170033",
"bytecode": "0x608060405234801561001057600080fd5b506040516108473803806108478339818101604052810190610032919061017d565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c3f3b60306040518263ffffffff1660e01b81526004016100cb91906101b9565b6020604051808303816000875af11580156100ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061010e919061020a565b60018190555050610237565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061014a8261011f565b9050919050565b61015a8161013f565b811461016557600080fd5b50565b60008151905061017781610151565b92915050565b6000602082840312156101935761019261011a565b5b60006101a184828501610168565b91505092915050565b6101b38161013f565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b6000819050919050565b6101e7816101d4565b81146101f257600080fd5b50565b600081519050610204816101de565b92915050565b6000602082840312156102205761021f61011a565b5b600061022e848285016101f5565b91505092915050565b610601806102466000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea264697066735822122078569abd7f309f3107c4d19e9b4a4f4812522ccc5dc57c7ccbe2b06a5ba461b064736f6c63430008170033",
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea264697066735822122078569abd7f309f3107c4d19e9b4a4f4812522ccc5dc57c7ccbe2b06a5ba461b064736f6c63430008170033",
"linkReferences": {},
"deployedLinkReferences": {}
}

View File

@@ -14,7 +14,8 @@ const nextConfig = withPWA({
})({
env: {
INFURA_API_KEY: process.env.INFURA_API_KEY,
ETHEREUM_PRIVATE_KEY: process.env.ETHEREUM_PRIVATE_KEY
ETHEREUM_PRIVATE_KEY: process.env.ETHEREUM_PRIVATE_KEY,
GELATO_RELAYER_API_KEY: process.env.GELATO_RELAYER_API_KEY
}
})

View File

@@ -9,9 +9,9 @@
"lint": "next lint"
},
"dependencies": {
"@semaphore-protocol/core": "4.1.0",
"@semaphore-protocol/data": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/core": "4.5.0",
"@semaphore-protocol/data": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"ethers": "^6.11.1",
"next": "14.1.0",
"next-pwa": "^5.6.0",

View File

@@ -3,26 +3,14 @@ import { NextRequest } from "next/server"
import Feedback from "../../../../contract-artifacts/Feedback.json"
export async function POST(req: NextRequest) {
if (typeof process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS !== "string") {
throw new Error("Please, define NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS in your .env file")
}
if (typeof process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "string") {
throw new Error("Please, define NEXT_PUBLIC_DEFAULT_NETWORK in your .env file")
}
if (typeof process.env.INFURA_API_KEY !== "string" && process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "localhost") {
throw new Error("Please, define INFURA_API_KEY in your .env file")
}
if (typeof process.env.ETHEREUM_PRIVATE_KEY !== "string") {
throw new Error("Please, define ETHEREUM_PRIVATE_KEY in your .env file")
}
const ethereumPrivateKey = process.env.ETHEREUM_PRIVATE_KEY
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK
const infuraApiKey = process.env.INFURA_API_KEY
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string
const infuraApiKey = process.env.NEXT_PUBLIC_INFURA_API_KEY as string
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
const provider =
ethereumNetwork === "localhost"

View File

@@ -3,26 +3,14 @@ import { NextRequest } from "next/server"
import Feedback from "../../../../contract-artifacts/Feedback.json"
export async function POST(req: NextRequest) {
if (typeof process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS !== "string") {
throw new Error("Please, define NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS in your .env file")
}
if (typeof process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "string") {
throw new Error("Please, define NEXT_PUBLIC_DEFAULT_NETWORK in your .env file")
}
if (typeof process.env.INFURA_API_KEY !== "string" && process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "localhost") {
throw new Error("Please, define INFURA_API_KEY in your .env file")
}
if (typeof process.env.ETHEREUM_PRIVATE_KEY !== "string") {
throw new Error("Please, define ETHEREUM_PRIVATE_KEY in your .env file")
}
const ethereumPrivateKey = process.env.ETHEREUM_PRIVATE_KEY
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK
const infuraApiKey = process.env.INFURA_API_KEY
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string
const infuraApiKey = process.env.NEXT_PUBLIC_INFURA_API_KEY as string
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
const provider =
ethereumNetwork === "localhost"

View File

@@ -1,29 +1,40 @@
:root {
--slate100: #f1f5f9;
--slate200: #e2e8f0;
--slate300: #cbd5e1;
--slate400: #94a3b8;
--slate500: #64748b;
--slate700: #334155;
--blue200: #bfdbfe;
--blue500: #3b82f6;
--blue600: #2563eb;
--blue700: #1d4ed8;
--blue800: #1e40af;
--blue900: #1e3a8a;
--blue100: #dde6fc;
--blue200: #c3d4fa;
--blue300: #9abaf6;
--blue400: #6a95f0;
--blue500: #4771ea;
--blue600: #3555df;
--blue700: #2940cc;
--blue800: #2735a6;
--blue900: #253183;
--blue950: #1b2050;
--darkBlueBg: #00020d;
--slate50: #f7f7f8;
--slate100: #eeeef0;
--slate200: #d9d9de;
--slate300: #b8b9c1;
--slate400: #92939e;
--slate500: #747583;
--slate600: #5e5f6b;
--slate700: #4d4e57;
--slate800: #42424a;
--slate900: #3a3a40;
--slate950: #26262b;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: "Outfit", sans-serif;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
height: 100vh;
}
body {
@@ -33,17 +44,30 @@ body {
p {
line-height: 1.5rem;
font-weight: 300;
overflow-wrap: break-word;
font-size: 1rem;
}
b {
font-weight: 600;
}
.key-wrapper {
padding-bottom: 1.5rem;
padding-left: 0.5rem;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
max-width: 32rem;
max-width: 40vw;
min-width: 35rem;
margin: auto;
padding: 1rem;
height: calc(100vh - 7rem - 1px);
padding-bottom: 5rem;
min-height: calc(100vh - 3.5rem);
}
@@ -57,28 +81,25 @@ p {
margin-bottom: 1rem;
}
ol {
padding: 1rem;
}
li {
margin-top: 1rem;
}
h2 {
font-size: 2.25rem;
font-weight: 500;
margin-bottom: 1rem;
line-height: 1.2;
}
h3 {
font-size: 1.125rem;
font-size: 1.15rem;
font-weight: 500;
}
.divider {
height: 1px;
background: var(--slate500);
opacity: 0.6;
border: 0;
border-style: solid;
border-bottom-width: 1px;
width: 100%;
border-color: var(--slate400);
margin: 2rem 0;
}
@@ -89,31 +110,44 @@ h3 {
}
a {
color: var(--blue500);
color: var(--blue400);
text-decoration: none;
}
a:hover {
text-decoration: underline;
text-decoration-color: var(--blue400);
}
.button {
background-color: var(--blue800);
width: 100%;
padding: 0.8rem 1rem;
border: 1px;
border-radius: 100px;
cursor: pointer;
color: var(--slate100);
font-size: 1.125rem;
font-weight: 500;
transition: all 200ms linear;
margin-top: 1rem;
margin-bottom: 1.5rem;
opacity: 0.9;
font-weight: 400;
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform;
transition-duration: 200ms;
padding-left: 18px !important;
padding-right: 18px !important;
height: 2.5rem;
min-width: 2.5rem;
font-size: 1rem;
-webkit-padding-start: 1rem;
padding-inline-start: 1rem;
-webkit-padding-end: 1rem;
padding-inline-end: 1rem;
background: var(--blue500);
color: white;
background-image: linear-gradient(to right, var(--blue500), var(--blue800));
transition-timing-function: linear;
width: 100%;
border: none;
display: flex;
justify-content: center;
height: 3rem;
align-items: center;
justify-content: center;
}
.button:hover {
background-color: var(--blue900);
background-color: var(--blue800);
background-image: none;
cursor: pointer;
}
.button:disabled {
@@ -123,54 +157,126 @@ a {
.button:disabled:hover {
background-color: var(--blue800);
background-image: none;
}
.button-stepper {
cursor: pointer;
color: var(--blue600);
color: var(--blue500);
font-size: 1.1rem;
border: none;
background: none;
width: 4rem;
margin: 0 1rem;
display: flex;
justify-content: center;
}
.button-link {
.button-stepper:hover {
text-decoration: underline;
}
.refresh-wrapper {
color: var(--slate400);
display: flex;
align-items: center;
}
.refresh-wrapper:hover {
text-decoration: underline;
}
.refresh-button {
cursor: pointer;
color: var(--slate300);
font-size: 1.1rem;
border: none;
background: none;
padding-right: 1rem;
display: flex;
align-items: center;
}
.refresh-button:hover {
text-decoration: underline;
}
.refresh-span {
width: 1.5em;
height: 1em;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
vertical-align: middle;
}
.refresh-icon {
margin-inline-end: 0.5rem;
}
.stepper-icon {
display: inline-flex;
align-self: center;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
}
.left-pad {
margin-inline-end: 0.5rem;
}
.right-pad {
margin-inline-start: 0.5rem;
}
.stepper-icon svg {
width: 1em;
height: 1em;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
vertical-align: super;
}
.box {
padding: 0.8rem;
border-style: solid;
border-width: 1px;
border-color: var(--slate500);
border-radius: 4px;
border-bottom: 1px solid white;
padding: 0.8rem 0;
max-height: 50px;
}
.box-text {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin: 0.5rem;
font-size: 1rem;
}
.header {
display: flex;
justify-content: space-between;
padding: 1.5rem;
padding: 0 1.5rem;
height: 3.5rem;
}
.header-left {
font-size: 1.125rem;
font-weight: 500;
text-decoration: none;
text-decoration: none !important;
display: flex;
align-items: center;
}
.header-right {
display: flex;
gap: 1.5rem;
align-items: center;
}
.footer {
@@ -188,6 +294,57 @@ a {
background: var(--slate500);
}
.users-wrapper,
.feedback-wrapper {
max-height: 300px;
overflow-y: scroll;
}
.keys-header {
margin-bottom: 1.5rem;
}
.users-header {
font-weight: 700;
font-size: 1.125rem;
font-family: "DM Sans", sans-serif;
}
.join-group-button,
.send-feedback-button {
margin-top: 1.5rem;
}
.github-icon {
width: 1.5rem;
height: 1.5rem;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
}
.github-button {
cursor: pointer;
color: var(--slate100);
font-size: 1.1rem;
border: none;
background: none;
padding-right: 1rem;
display: flex;
align-items: center;
box-sizing: border-box;
display: inline-block;
overflow: visible !important;
fill: currentColor;
color: #f0f6fc !important;
vertical-align: middle !important;
width: 2rem;
height: 2rem;
}
.loader {
width: 25px;
height: 25px;
@@ -196,7 +353,7 @@ a {
border-right: 2px solid transparent;
animation: spin 1s linear infinite;
z-index: 20;
margin-left: 1rem;
margin-left: 0.5rem;
}
@keyframes spin {

View File

@@ -0,0 +1,177 @@
"use client"
import Stepper from "@/components/Stepper"
import { useLogContext } from "@/context/LogContext"
import { useSemaphoreContext } from "@/context/SemaphoreContext"
import { useRouter } from "next/navigation"
import { useCallback, useEffect, useMemo } from "react"
import Feedback from "../../../contract-artifacts/Feedback.json"
import { ethers } from "ethers"
import useSemaphoreIdentity from "@/hooks/useSemaphoreIdentity"
import { useState } from "react"
export default function GroupsPage() {
const router = useRouter()
const { setLog } = useLogContext()
const { _users, refreshUsers, addUser } = useSemaphoreContext()
const [_loading, setLoading] = useState(false)
const { _identity } = useSemaphoreIdentity()
useEffect(() => {
if (_users.length > 0) {
setLog(`${_users.length} user${_users.length > 1 ? "s" : ""} retrieved from the group 🤙🏽`)
}
}, [_users, setLog])
const users = useMemo(() => [..._users].reverse(), [_users])
const joinGroup = useCallback(async () => {
if (!_identity) {
return
}
setLoading(true)
setLog(`Joining the Feedback group...`)
let joinedGroup: boolean = false
if (process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK) {
const response = await fetch(process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
abi: Feedback.abi,
address: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string,
functionName: "joinGroup",
functionParameters: [_identity.commitment.toString()]
})
})
if (response.status === 200) {
joinedGroup = true
}
} else if (
process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT &&
process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID &&
process.env.GELATO_RELAYER_API_KEY
) {
const iface = new ethers.Interface(Feedback.abi)
const request = {
chainId: process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID,
target: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
data: iface.encodeFunctionData("joinGroup", [_identity.commitment.toString()]),
sponsorApiKey: process.env.GELATO_RELAYER_API_KEY
}
const response = await fetch(process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
})
if (response.status === 201) {
joinedGroup = true
}
} else {
const response = await fetch("api/join", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
identityCommitment: _identity.commitment.toString()
})
})
if (response.status === 200) {
joinedGroup = true
}
}
if (joinedGroup) {
addUser(_identity.commitment.toString())
setLog(`You have joined the Feedback group event 🎉 Share your feedback anonymously!`)
} else {
setLog("Some error occurred, please try again!")
}
setLoading(false)
}, [_identity, addUser, setLoading, setLog])
const userHasJoined = useMemo(
() => _identity !== undefined && _users.includes(_identity.commitment.toString()),
[_identity, _users]
)
return (
<>
<h2>Groups</h2>
<p>
<a
href="https://docs.semaphore.pse.dev/guides/groups"
target="_blank"
rel="noreferrer noopener nofollow"
>
Semaphore groups
</a>{" "}
are{" "}
<a
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
target="_blank"
rel="noreferrer noopener nofollow"
>
Lean incremental Merkle trees
</a>{" "}
in which each leaf contains an identity commitment for a user. Groups can be abstracted to represent
events, polls, or organizations.
</p>
<div className="divider"></div>
<div className="text-top">
<h3 className="users-header">Group users ({_users.length})</h3>
<button className="refresh-button" onClick={refreshUsers}>
<span className="refresh-span">
<svg viewBox="0 0 24 24" focusable="false" className="refresh-icon">
<path
fill="currentColor"
d="M5.463 4.43301C7.27756 2.86067 9.59899 1.99666 12 2.00001C17.523 2.00001 22 6.47701 22 12C22 14.136 21.33 16.116 20.19 17.74L17 12H20C20.0001 10.4316 19.5392 8.89781 18.6747 7.58927C17.8101 6.28072 16.5799 5.25517 15.1372 4.64013C13.6944 4.0251 12.1027 3.84771 10.56 4.13003C9.0172 4.41234 7.59145 5.14191 6.46 6.22801L5.463 4.43301ZM18.537 19.567C16.7224 21.1393 14.401 22.0034 12 22C6.477 22 2 17.523 2 12C2 9.86401 2.67 7.88401 3.81 6.26001L7 12H4C3.99987 13.5684 4.46075 15.1022 5.32534 16.4108C6.18992 17.7193 7.42007 18.7449 8.86282 19.3599C10.3056 19.9749 11.8973 20.1523 13.44 19.87C14.9828 19.5877 16.4085 18.8581 17.54 17.772L18.537 19.567Z"
></path>
</svg>
</span>
Refresh
</button>
</div>
{_users.length > 0 && (
<div className="users-wrapper">
{users.map((user, i) => (
<div key={i}>
<p className="box box-text">
{_identity?.commitment.toString() === user ? <b>{user}</b> : user}
</p>
</div>
))}
</div>
)}
<div className="join-group-button">
<button
className="button"
onClick={joinGroup}
disabled={_loading || !_identity || userHasJoined}
type="button"
>
<span>Join group</span>
{_loading && <div className="loader"></div>}
</button>
</div>
<div className="divider" />
<Stepper
step={2}
onPrevClick={() => router.push("/")}
onNextClick={userHasJoined ? () => router.push("/proofs") : undefined}
/>
</>
)
}

View File

@@ -1,142 +0,0 @@
"use client"
import { Identity } from "@semaphore-protocol/core"
import { useRouter } from "next/navigation"
import { useCallback, useContext, useEffect, useState } from "react"
import Feedback from "../../../contract-artifacts/Feedback.json"
import Stepper from "@/components/Stepper"
import LogsContext from "@/context/LogsContext"
import SemaphoreContext from "@/context/SemaphoreContext"
export default function GroupsPage() {
const router = useRouter()
const { setLogs } = useContext(LogsContext)
const { _users, refreshUsers, addUser } = useContext(SemaphoreContext)
const [_loading, setLoading] = useState(false)
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (!privateKey) {
router.push("/")
return
}
setIdentity(new Identity(privateKey))
}, [router])
useEffect(() => {
if (_users.length > 0) {
setLogs(`${_users.length} user${_users.length > 1 ? "s" : ""} retrieved from the group 🤙🏽`)
}
}, [_users, setLogs])
const joinGroup = useCallback(async () => {
if (!_identity) {
return
}
setLoading(true)
setLogs(`Joining the Feedback group...`)
let response: any
if (process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK) {
response = await fetch(process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
abi: Feedback.abi,
address: process.env.FEEDBACK_CONTRACT_ADDRESS,
functionName: "joinGroup",
functionParameters: [_identity.commitment.toString()]
})
})
} else {
response = await fetch("api/join", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
identityCommitment: _identity.commitment.toString()
})
})
}
if (response.status === 200) {
addUser(_identity.commitment.toString())
setLogs(`You have joined the Feedback group event 🎉 Share your feedback anonymously!`)
} else {
setLogs("Some error occurred, please try again!")
}
setLoading(false)
}, [_identity, addUser, setLogs])
const userHasJoined = useCallback((identity: Identity) => _users.includes(identity.commitment.toString()), [_users])
return (
<>
<h2>Groups</h2>
<p>
<a
href="https://docs.semaphore.pse.dev/guides/groups"
target="_blank"
rel="noreferrer noopener nofollow"
>
Semaphore groups
</a>{" "}
are{" "}
<a
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
target="_blank"
rel="noreferrer noopener nofollow"
>
Lean incremental Merkle trees
</a>{" "}
in which each leaf contains an identity commitment for a user. Groups can be abstracted to represent
events, polls, or organizations.
</p>
<div className="divider"></div>
<div className="text-top">
<h3>Group users ({_users.length})</h3>
<button className="button-link" onClick={refreshUsers}>
Refresh
</button>
</div>
<div>
<button
className="button"
onClick={joinGroup}
disabled={_loading || !_identity || userHasJoined(_identity)}
>
<span>Join group</span>
{_loading && <div className="loader"></div>}
</button>
</div>
{_users.length > 0 && (
<div>
{_users.map((user, i) => (
<div key={i}>
<p className="box box-text">{user.toString()}</p>
</div>
))}
</div>
)}
<div className="divider"></div>
<Stepper
step={2}
onPrevClick={() => router.push("/")}
onNextClick={_identity && userHasJoined(_identity) ? () => router.push("/proofs") : undefined}
/>
</>
)
}

View File

@@ -1,8 +1,10 @@
import PageContainer from "@/components/PageContainer"
import type { Metadata } from "next"
import { Inter } from "next/font/google"
import { LogContextProvider } from "@/context/LogContext"
import { SemaphoreContextProvider } from "@/context/SemaphoreContext"
import "./globals.css"
import { Inter } from "next/font/google"
const inter = Inter({ subsets: ["latin"] })
export const metadata: Metadata = {
@@ -32,8 +34,20 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com"></link>
<link rel="preconnect" href="https://fonts.gstatic.com"></link>
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap"
rel="stylesheet"
></link>
</head>
<body suppressHydrationWarning className={inter.className}>
<PageContainer>{children}</PageContainer>
<SemaphoreContextProvider>
<LogContextProvider>
<PageContainer>{children}</PageContainer>
</LogContextProvider>
</SemaphoreContextProvider>
</body>
</html>
)

View File

@@ -2,42 +2,42 @@
import { Identity } from "@semaphore-protocol/core"
import { useRouter } from "next/navigation"
import { useCallback, useContext, useEffect, useState } from "react"
import { useCallback, useEffect, useState } from "react"
import Stepper from "../components/Stepper"
import LogsContext from "../context/LogsContext"
import { useLogContext } from "../context/LogContext"
export default function IdentitiesPage() {
const router = useRouter()
const { setLogs } = useContext(LogsContext)
const { setLog } = useLogContext()
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (privateKey) {
const identity = new Identity(privateKey)
const identity = Identity.import(privateKey)
setIdentity(identity)
setLogs("Your Semaphore identity has been retrieved from the browser cache 👌🏽")
setLog("Your Semaphore identity has been retrieved from the browser cache 👌🏽")
} else {
setLogs("Create your Semaphore identity 👆🏽")
setLog("Create your Semaphore identity 👆🏽")
}
}, [setLogs])
}, [setLog])
const createIdentity = useCallback(async () => {
const identity = new Identity()
setIdentity(identity)
localStorage.setItem("identity", identity.privateKey.toString())
localStorage.setItem("identity", identity.export())
setLogs("Your new Semaphore identity has just been created 🎉")
}, [setLogs])
setLog("Your new Semaphore identity has just been created 🎉")
}, [setLog])
return (
<>
<h2 className="font-size: 3rem;">Identities</h2>
<h2>Identities</h2>
<p>
The identity of a user in the Semaphore protocol. A{" "}
@@ -59,35 +59,36 @@ export default function IdentitiesPage() {
public/private key pair and a commitment, used as the public identifier of the identity.
</p>
<div className="divider"></div>
<div className="divider" />
<div className="text-top">
<div className="keys-header">
<h3>Identity</h3>
{_identity && (
<button className="button-link" onClick={createIdentity}>
New
</button>
)}
</div>
{_identity ? (
<div>
<div className="box">
<p className="box-text">Private Key: {_identity.privateKey.toString()}</p>
<p className="box-text">Commitment: {_identity.commitment.toString()}</p>
</div>
</div>
) : (
<div>
<button className="button" onClick={createIdentity}>
Create identity
</button>
{_identity && (
<div className="key-wrapper">
<p>
<b>Private Key (base64)</b>:<br /> {_identity.export()}
</p>
<p>
<b>Public Key</b>:<br /> [{_identity.publicKey[0].toString()},{" "}
{_identity.publicKey[1].toString()}]
</p>
<p>
<b>Commitment</b>:<br /> {_identity.commitment.toString()}
</p>
</div>
)}
<div className="divider"></div>
<div>
<button className="button" onClick={createIdentity} type="button">
Create identity
</button>
</div>
<Stepper step={1} onNextClick={_identity && (() => router.push("/groups"))} />
<div className="divider" />
<Stepper step={1} onNextClick={_identity && (() => router.push("/group"))} />
</>
)
}

View File

@@ -1,78 +1,94 @@
"use client"
import { Group, Identity, generateProof } from "@semaphore-protocol/core"
import Stepper from "@/components/Stepper"
import { useLogContext } from "@/context/LogContext"
import { useSemaphoreContext } from "@/context/SemaphoreContext"
import { generateProof, Group } from "@semaphore-protocol/core"
import { encodeBytes32String, ethers } from "ethers"
import { useRouter } from "next/navigation"
import { useCallback, useContext, useEffect, useState } from "react"
import { useCallback, useEffect, useMemo, useState } from "react"
import Feedback from "../../../contract-artifacts/Feedback.json"
import Stepper from "../../components/Stepper"
import LogsContext from "../../context/LogsContext"
import SemaphoreContext from "../../context/SemaphoreContext"
import useSemaphoreIdentity from "@/hooks/useSemaphoreIdentity"
export default function ProofsPage() {
const router = useRouter()
const { setLogs } = useContext(LogsContext)
const { _users, _feedback, refreshFeedback, addFeedback } = useContext(SemaphoreContext)
const { setLog } = useLogContext()
const { _users, _feedback, refreshFeedback, addFeedback } = useSemaphoreContext()
const [_loading, setLoading] = useState(false)
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (!privateKey) {
router.push("/")
return
}
setIdentity(new Identity(privateKey))
}, [router])
const { _identity } = useSemaphoreIdentity()
useEffect(() => {
if (_feedback.length > 0) {
setLogs(`${_feedback.length} feedback retrieved from the group 🤙🏽`)
setLog(`${_feedback.length} feedback retrieved from the group 🤙🏽`)
}
}, [_feedback, setLogs])
}, [_feedback, setLog])
const feedback = useMemo(() => [..._feedback].reverse(), [_feedback])
const sendFeedback = useCallback(async () => {
if (!_identity) {
return
}
if (typeof process.env.NEXT_PUBLIC_GROUP_ID !== "string") {
throw new Error("Please, define NEXT_PUBLIC_GROUP_ID in your .env file")
}
const feedback = prompt("Please enter your feedback:")
if (feedback && _users) {
setLoading(true)
setLogs(`Posting your anonymous feedback...`)
setLog(`Posting your anonymous feedback...`)
try {
const group = new Group(_users)
const { points, merkleTreeDepth, merkleTreeRoot, nullifier, message } = await generateProof(
const message = encodeBytes32String(feedback)
const { points, merkleTreeDepth, merkleTreeRoot, nullifier } = await generateProof(
_identity,
group,
feedback,
message,
process.env.NEXT_PUBLIC_GROUP_ID as string
)
let response: any
if (process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK) {
response = await fetch(process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK, {
let feedbackSent: boolean = false
const params = [merkleTreeDepth, merkleTreeRoot, nullifier, message, points]
if (process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK) {
const response = await fetch(process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
abi: Feedback.abi,
address: process.env.FEEDBACK_CONTRACT_ADDRESS,
address: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
functionName: "sendFeedback",
functionParameters: [merkleTreeDepth, merkleTreeRoot, nullifier, message, points]
functionParameters: params
})
})
if (response.status === 200) {
feedbackSent = true
}
} else if (
process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT &&
process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID &&
process.env.GELATO_RELAYER_API_KEY
) {
const iface = new ethers.Interface(Feedback.abi)
const request = {
chainId: process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID,
target: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
data: iface.encodeFunctionData("sendFeedback", params),
sponsorApiKey: process.env.GELATO_RELAYER_API_KEY
}
const response = await fetch(process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
})
if (response.status === 201) {
feedbackSent = true
}
} else {
response = await fetch("api/feedback", {
const response = await fetch("api/feedback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -83,24 +99,28 @@ export default function ProofsPage() {
points
})
})
if (response.status === 200) {
feedbackSent = true
}
}
if (response.status === 200) {
if (feedbackSent) {
addFeedback(feedback)
setLogs(`Your feedback has been posted 🎉`)
setLog(`Your feedback has been posted 🎉`)
} else {
setLogs("Some error occurred, please try again!")
setLog("Some error occurred, please try again!")
}
} catch (error) {
console.error(error)
setLogs("Some error occurred, please try again!")
setLog("Some error occurred, please try again!")
} finally {
setLoading(false)
}
}
}, [_identity, _users, addFeedback, setLogs])
}, [_identity, _users, addFeedback, setLoading, setLog])
return (
<>
@@ -122,22 +142,23 @@ export default function ProofsPage() {
<div className="divider"></div>
<div className="text-top">
<h3>Feedback messages ({_feedback.length})</h3>
<button className="button-link" onClick={refreshFeedback}>
<h3>Feedback ({_feedback.length})</h3>
<button className="refresh-button" onClick={refreshFeedback}>
<span className="refresh-span">
<svg viewBox="0 0 24 24" focusable="false" className="refresh-icon">
<path
fill="currentColor"
d="M5.463 4.43301C7.27756 2.86067 9.59899 1.99666 12 2.00001C17.523 2.00001 22 6.47701 22 12C22 14.136 21.33 16.116 20.19 17.74L17 12H20C20.0001 10.4316 19.5392 8.89781 18.6747 7.58927C17.8101 6.28072 16.5799 5.25517 15.1372 4.64013C13.6944 4.0251 12.1027 3.84771 10.56 4.13003C9.0172 4.41234 7.59145 5.14191 6.46 6.22801L5.463 4.43301ZM18.537 19.567C16.7224 21.1393 14.401 22.0034 12 22C6.477 22 2 17.523 2 12C2 9.86401 2.67 7.88401 3.81 6.26001L7 12H4C3.99987 13.5684 4.46075 15.1022 5.32534 16.4108C6.18992 17.7193 7.42007 18.7449 8.86282 19.3599C10.3056 19.9749 11.8973 20.1523 13.44 19.87C14.9828 19.5877 16.4085 18.8581 17.54 17.772L18.537 19.567Z"
></path>
</svg>
</span>
Refresh
</button>
</div>
<div>
<button className="button" onClick={sendFeedback} disabled={_loading}>
<span>Send Feedback</span>
{_loading && <div className="loader"></div>}
</button>
</div>
{_feedback.length > 0 && (
<div>
{_feedback.map((f, i) => (
{feedback.length > 0 && (
<div className="feedback-wrapper">
{feedback.map((f, i) => (
<div key={i}>
<p className="box box-text">{f}</p>
</div>
@@ -145,9 +166,16 @@ export default function ProofsPage() {
</div>
)}
<div className="send-feedback-button">
<button className="button" onClick={sendFeedback} disabled={_loading}>
<span>Send Feedback</span>
{_loading && <div className="loader"></div>}
</button>
</div>
<div className="divider"></div>
<Stepper step={3} onPrevClick={() => router.push("/groups")} />
<Stepper step={3} onPrevClick={() => router.push("/group")} />
</>
)
}

View File

@@ -1,12 +1,8 @@
"use client"
import LogsContext from "@/context/LogsContext"
import SemaphoreContext from "@/context/SemaphoreContext"
import useSemaphore from "@/hooks/useSemaphore"
import { useLogContext } from "@/context/LogContext"
import shortenString from "@/utils/shortenString"
import { SupportedNetwork } from "@semaphore-protocol/utils"
import { usePathname } from "next/navigation"
import { useEffect, useState } from "react"
import Link from "next/link"
export default function PageContainer({
@@ -15,15 +11,9 @@ export default function PageContainer({
children: React.ReactNode
}>) {
const pathname = usePathname()
const semaphore = useSemaphore()
const [_logs, setLogs] = useState<string>("")
const { log } = useLogContext()
useEffect(() => {
semaphore.refreshUsers()
semaphore.refreshFeedback()
}, [])
function getExplorerLink(network: SupportedNetwork, address: string) {
function getExplorerLink(network: string, address: string) {
switch (network) {
case "sepolia":
return `https://sepolia.etherscan.io/address/${address}`
@@ -35,7 +25,7 @@ export default function PageContainer({
}
return (
<div>
<>
<div className="header">
<Link href="/" className="header-left">
Feedback
@@ -43,7 +33,7 @@ export default function PageContainer({
<div className="header-right">
<a
href={getExplorerLink(
process.env.NEXT_PUBLIC_DEFAULT_NETWORK as SupportedNetwork,
process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string,
process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
)}
target="_blank"
@@ -52,47 +42,34 @@ export default function PageContainer({
<div>{shortenString(process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string, [6, 4])}</div>
</a>
<a
href="https://github.com/semaphore-protocol/semaphore"
href="https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-ethers"
target="_blank"
rel="noreferrer noopener nofollow"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="feather feather-github"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
<button type="button" className="github-button" aria-label="Github repository">
<svg
height="32"
aria-hidden="true"
viewBox="0 0 24 24"
version="1.1"
width="32"
data-view-component="true"
>
<path d="M12.5.75C6.146.75 1 5.896 1 12.25c0 5.089 3.292 9.387 7.863 10.91.575.101.79-.244.79-.546 0-.273-.014-1.178-.014-2.142-2.889.532-3.636-.704-3.866-1.35-.13-.331-.69-1.352-1.18-1.625-.402-.216-.977-.748-.014-.762.906-.014 1.553.834 1.769 1.179 1.035 1.74 2.688 1.25 3.349.948.1-.747.402-1.25.733-1.538-2.559-.287-5.232-1.279-5.232-5.678 0-1.25.445-2.285 1.178-3.09-.115-.288-.517-1.467.115-3.048 0 0 .963-.302 3.163 1.179.92-.259 1.897-.388 2.875-.388.977 0 1.955.13 2.875.388 2.2-1.495 3.162-1.179 3.162-1.179.633 1.581.23 2.76.115 3.048.733.805 1.179 1.825 1.179 3.09 0 4.413-2.688 5.39-5.247 5.678.417.36.776 1.05.776 2.128 0 1.538-.014 2.774-.014 3.162 0 .302.216.662.79.547C20.709 21.637 24 17.324 24 12.25 24 5.896 18.854.75 12.5.75Z"></path>
</svg>
</button>
</a>
</div>
</div>
<div className="container">
<SemaphoreContext.Provider value={semaphore}>
<LogsContext.Provider
value={{
_logs,
setLogs
}}
>
{children}
</LogsContext.Provider>
</SemaphoreContext.Provider>
</div>
<div className="container">{children}</div>
<div className="divider-footer"></div>
<div className="divider-footer" />
<div className="footer">
{_logs.endsWith("...")}
<p>{_logs || `Current step: ${pathname}`}</p>
{log.endsWith("...")}
<p>{log || `Current step: ${pathname}`}</p>
</div>
</div>
</>
)
}

View File

@@ -1,3 +1,5 @@
"use client"
export type StepperProps = {
step: number
onPrevClick?: () => void
@@ -8,21 +10,47 @@ export default function Stepper({ step, onPrevClick, onNextClick }: StepperProps
return (
<div className="stepper">
{onPrevClick !== undefined ? (
<button className="button-stepper" disabled={!onPrevClick} onClick={onPrevClick || undefined}>
<button
className="button-stepper"
disabled={!onPrevClick}
onClick={onPrevClick || undefined}
type="button"
>
<span className="stepper-icon left-pad">
<svg viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M16.2425 6.34317L14.8283 4.92896L7.75732 12L14.8284 19.0711L16.2426 17.6569L10.5857 12L16.2425 6.34317Z"
></path>
</svg>
</span>
Prev
</button>
) : (
<span></span>
<button className="button-stepper"></button>
)}
<p>{step.toString()}/3</p>
{onNextClick !== undefined ? (
<button className="button-stepper" disabled={!onNextClick} onClick={onNextClick || undefined}>
<button
className="button-stepper"
disabled={!onNextClick}
onClick={onNextClick || undefined}
type="button"
>
Next
<span className="stepper-icon right-pad">
<svg viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M10.5859 6.34317L12.0001 4.92896L19.0712 12L12.0001 19.0711L10.5859 17.6569L16.2428 12L10.5859 6.34317Z"
></path>
</svg>
</span>
</button>
) : (
<span></span>
<span className="button-stepper" />
)}
</div>
)

View File

@@ -0,0 +1,37 @@
"use client"
import React, { createContext, ReactNode, useContext, useState } from "react"
export type LogContextType = {
log: string
setLog: (logs: string) => void
}
const LogContext = createContext<LogContextType | null>(null)
interface ProviderProps {
children: ReactNode
}
export const LogContextProvider: React.FC<ProviderProps> = ({ children }) => {
const [log, setLog] = useState<string>("")
return (
<LogContext.Provider
value={{
log,
setLog
}}
>
{children}
</LogContext.Provider>
)
}
export const useLogContext = () => {
const context = useContext(LogContext)
if (context === null) {
throw new Error("LogContext must be used within a LogContextProvider")
}
return context
}

View File

@@ -1,11 +0,0 @@
import React from "react"
export type LogsContextType = {
_logs: string
setLogs: (logs: string) => void
}
export default React.createContext<LogsContextType>({
_logs: "",
setLogs: (logs: string) => logs
})

View File

@@ -1,19 +0,0 @@
import React from "react"
export type SemaphoreContextType = {
_users: string[]
_feedback: string[]
refreshUsers: () => Promise<void>
addUser: (user: string) => void
refreshFeedback: () => Promise<void>
addFeedback: (feedback: string) => void
}
export default React.createContext<SemaphoreContextType>({
_users: [],
_feedback: [],
refreshUsers: () => Promise.resolve(),
addUser: () => {},
refreshFeedback: () => Promise.resolve(),
addFeedback: () => {}
})

View File

@@ -0,0 +1,94 @@
"use client"
import React, { createContext, ReactNode, useCallback, useContext, useEffect, useState } from "react"
import { SemaphoreEthers } from "@semaphore-protocol/data"
import { decodeBytes32String, toBeHex } from "ethers"
export type SemaphoreContextType = {
_users: string[]
_feedback: string[]
refreshUsers: () => Promise<void>
addUser: (user: string) => void
refreshFeedback: () => Promise<void>
addFeedback: (feedback: string) => void
}
const SemaphoreContext = createContext<SemaphoreContextType | null>(null)
interface ProviderProps {
children: ReactNode
}
const ethereumNetwork =
process.env.NEXT_PUBLIC_DEFAULT_NETWORK === "localhost"
? "http://127.0.0.1:8545"
: process.env.NEXT_PUBLIC_DEFAULT_NETWORK
export const SemaphoreContextProvider: React.FC<ProviderProps> = ({ children }) => {
const [_users, setUsers] = useState<any[]>([])
const [_feedback, setFeedback] = useState<string[]>([])
const refreshUsers = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreEthers(ethereumNetwork, {
address: process.env.NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS,
projectId: process.env.NEXT_PUBLIC_INFURA_API_KEY
})
const members = await semaphore.getGroupMembers(process.env.NEXT_PUBLIC_GROUP_ID as string)
setUsers(members.map((member) => member.toString()))
}, [])
const addUser = useCallback(
(user: any) => {
setUsers([..._users, user])
},
[_users]
)
const refreshFeedback = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreEthers(ethereumNetwork, {
address: process.env.NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS,
projectId: process.env.NEXT_PUBLIC_INFURA_API_KEY
})
const proofs = await semaphore.getGroupValidatedProofs(process.env.NEXT_PUBLIC_GROUP_ID as string)
setFeedback(proofs.map(({ message }: any) => decodeBytes32String(toBeHex(message, 32))))
}, [])
const addFeedback = useCallback(
(feedback: string) => {
setFeedback([..._feedback, feedback])
},
[_feedback]
)
useEffect(() => {
refreshUsers()
refreshFeedback()
}, [refreshFeedback, refreshUsers])
return (
<SemaphoreContext.Provider
value={{
_users,
_feedback,
refreshUsers,
addUser,
refreshFeedback,
addFeedback
}}
>
{children}
</SemaphoreContext.Provider>
)
}
export const useSemaphoreContext = () => {
const context = useContext(SemaphoreContext)
if (context === null) {
throw new Error("SemaphoreContext must be used within a SemaphoreContextProvider")
}
return context
}

View File

@@ -1,57 +0,0 @@
import { SemaphoreEthers } from "@semaphore-protocol/data"
import { decodeBytes32String, toBeHex } from "ethers"
import { useCallback, useState } from "react"
import { SemaphoreContextType } from "../context/SemaphoreContext"
const ethereumNetwork =
process.env.NEXT_PUBLIC_DEFAULT_NETWORK === "localhost"
? "http://127.0.0.1:8545"
: process.env.NEXT_PUBLIC_DEFAULT_NETWORK
export default function useSemaphore(): SemaphoreContextType {
const [_users, setUsers] = useState<string[]>([])
const [_feedback, setFeedback] = useState<string[]>([])
const refreshUsers = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreEthers(ethereumNetwork, {
address: process.env.NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS
})
const members = await semaphore.getGroupMembers(process.env.NEXT_PUBLIC_GROUP_ID as string)
setUsers(members)
}, [])
const addUser = useCallback(
(user: any) => {
setUsers([..._users, user])
},
[_users]
)
const refreshFeedback = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreEthers(ethereumNetwork, {
address: process.env.NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS
})
const proofs = await semaphore.getGroupValidatedProofs(process.env.NEXT_PUBLIC_GROUP_ID as string)
setFeedback(proofs.map(({ message }: any) => decodeBytes32String(toBeHex(message, 32))))
}, [])
const addFeedback = useCallback(
(feedback: string) => {
setFeedback([..._feedback, feedback])
},
[_feedback]
)
return {
_users,
_feedback,
refreshUsers,
addUser,
refreshFeedback,
addFeedback
}
}

View File

@@ -0,0 +1,23 @@
import { useEffect, useState } from "react"
import { Identity } from "@semaphore-protocol/core"
import { useRouter } from "next/navigation"
export default function useSemaphoreIdentity() {
const router = useRouter()
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (!privateKey) {
router.push("/")
return
}
setIdentity(new Identity(privateKey))
}, [router])
return {
_identity
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-monorepo-ethers",
"version": "4.1.0",
"version": "4.5.0",
"description": "Semaphore Hardhat + Next.js + SemaphoreEthers template.",
"license": "Unlicense",
"files": [

View File

@@ -20,9 +20,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.1.0",
"@semaphore-protocol/hardhat": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/core": "4.5.0",
"@semaphore-protocol/hardhat": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -50,7 +50,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.1.0"
"@semaphore-protocol/contracts": "4.5.0"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -1,4 +1,4 @@
NEXT_PUBLIC_DEFAULT_NETWORK=localhost
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9
NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
NEXT_PUBLIC_GROUP_ID=0

View File

@@ -1,5 +1,8 @@
NEXT_PUBLIC_DEFAULT_NETWORK=sepolia
NEXT_PUBLIC_INFURA_API_KEY=abf67af1010b4b8d877e04244f1eac3d
NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS=
NEXT_PUBLIC_SEMAPHORE_CONTRACT_ADDRESS=0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f
NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK=https://api.defender.openzeppelin.com/actions/20fce2ae-844b-4ec0-a6a2-90a3350a9d2c/runs/webhook/303216d1-fa7d-4fca-8c5b-7ba1ba544fc7/2T7i9xrkZA5j37hoaQLUuw
NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT=https://api.gelato.digital/relays/v2/sponsored-call
NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID=11155111
NEXT_PUBLIC_GROUP_ID=

View File

@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# testing
/coverage
# next.js
/.next/
/out/
@@ -7,3 +10,18 @@
# production
/build
# misc
.DS_Store
*.pem
# typescript
*.tsbuildinfo
next-env.d.ts
# Auto Generated PWA files
public/sw.js
public/workbox-*.js
public/worker-*.js
public/sw.js.map
public/workbox-*.js.map
public/worker-*.js.map

View File

@@ -9,11 +9,6 @@
"internalType": "address",
"name": "semaphoreAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "_groupId",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
@@ -92,8 +87,8 @@
"type": "function"
}
],
"bytecode": "0x608060405234801561001057600080fd5b5060405161083f38038061083f833981810160405281019061003291906101a8565b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060018190555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c96e71fb600154306040518363ffffffff1660e01b81526004016100d6929190610206565b600060405180830381600087803b1580156100f057600080fd5b505af1158015610104573d6000803e3d6000fd5b50505050505061022f565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061013f82610114565b9050919050565b61014f81610134565b811461015a57600080fd5b50565b60008151905061016c81610146565b92915050565b6000819050919050565b61018581610172565b811461019057600080fd5b50565b6000815190506101a28161017c565b92915050565b600080604083850312156101bf576101be61010f565b5b60006101cd8582860161015d565b92505060206101de85828601610193565b9150509250929050565b6101f181610172565b82525050565b61020081610134565b82525050565b600060408201905061021b60008301856101e8565b61022860208301846101f7565b9392505050565b6106018061023e6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea2646970667358221220f33606b2d5ad7c0dfc5d22afb43476e1974ea7fd160e1f28203a3e433f29cb4964736f6c63430008170033",
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea2646970667358221220f33606b2d5ad7c0dfc5d22afb43476e1974ea7fd160e1f28203a3e433f29cb4964736f6c63430008170033",
"bytecode": "0x608060405234801561001057600080fd5b506040516108473803806108478339818101604052810190610032919061017d565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c3f3b60306040518263ffffffff1660e01b81526004016100cb91906101b9565b6020604051808303816000875af11580156100ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061010e919061020a565b60018190555050610237565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061014a8261011f565b9050919050565b61015a8161013f565b811461016557600080fd5b50565b60008151905061017781610151565b92915050565b6000602082840312156101935761019261011a565b5b60006101a184828501610168565b91505092915050565b6101b38161013f565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b6000819050919050565b6101e7816101d4565b81146101f257600080fd5b50565b600081519050610204816101de565b92915050565b6000602082840312156102205761021f61011a565b5b600061022e848285016101f5565b91505092915050565b610601806102466000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea264697066735822122078569abd7f309f3107c4d19e9b4a4f4812522ccc5dc57c7ccbe2b06a5ba461b064736f6c63430008170033",
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80637b5d2534146100515780637b85d27a1461006f578063a0f44c921461008b578063eed02e4b146100a9575b600080fd5b6100596100c5565b6040516100669190610301565b60405180910390f35b6100896004803603810190610084919061037e565b6100e9565b005b6100936101ea565b6040516100a09190610409565b60405180910390f35b6100c360048036038101906100be9190610424565b6101f0565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006040518060c001604052808781526020018681526020018581526020018481526020016001548152602001836008806020026040519081016040528092919082600860200280828437600081840152601f19601f820116905080830192505050505050815250905060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0d898dd600154836040518363ffffffff1660e01b81526004016101b0929190610578565b600060405180830381600087803b1580156101ca57600080fd5b505af11580156101de573d6000803e3d6000fd5b50505050505050505050565b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631783efc3600154836040518363ffffffff1660e01b815260040161024d9291906105a2565b600060405180830381600087803b15801561026757600080fd5b505af115801561027b573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006102c76102c26102bd84610282565b6102a2565b610282565b9050919050565b60006102d9826102ac565b9050919050565b60006102eb826102ce565b9050919050565b6102fb816102e0565b82525050565b600060208201905061031660008301846102f2565b92915050565b600080fd5b6000819050919050565b61033481610321565b811461033f57600080fd5b50565b6000813590506103518161032b565b92915050565b600080fd5b60008190508260206008028201111561037857610377610357565b5b92915050565b6000806000806000610180868803121561039b5761039a61031c565b5b60006103a988828901610342565b95505060206103ba88828901610342565b94505060406103cb88828901610342565b93505060606103dc88828901610342565b92505060806103ed8882890161035c565b9150509295509295909350565b61040381610321565b82525050565b600060208201905061041e60008301846103fa565b92915050565b60006020828403121561043a5761043961031c565b5b600061044884828501610342565b91505092915050565b61045a81610321565b82525050565b600060089050919050565b600081905092915050565b6000819050919050565b600061048c8383610451565b60208301905092915050565b6000602082019050919050565b6104ae81610460565b6104b8818461046b565b92506104c382610476565b8060005b838110156104f45781516104db8782610480565b96506104e683610498565b9250506001810190506104c7565b505050505050565b6101a0820160008201516105136000850182610451565b5060208201516105266020850182610451565b5060408201516105396040850182610451565b50606082015161054c6060850182610451565b50608082015161055f6080850182610451565b5060a082015161057260a08501826104a5565b50505050565b60006101c08201905061058e60008301856103fa565b61059b60208301846104fc565b9392505050565b60006040820190506105b760008301856103fa565b6105c460208301846103fa565b939250505056fea264697066735822122078569abd7f309f3107c4d19e9b4a4f4812522ccc5dc57c7ccbe2b06a5ba461b064736f6c63430008170033",
"linkReferences": {},
"deployedLinkReferences": {}
}

View File

@@ -14,7 +14,8 @@ const nextConfig = withPWA({
})({
env: {
INFURA_API_KEY: process.env.INFURA_API_KEY,
ETHEREUM_PRIVATE_KEY: process.env.ETHEREUM_PRIVATE_KEY
ETHEREUM_PRIVATE_KEY: process.env.ETHEREUM_PRIVATE_KEY,
GELATO_RELAYER_API_KEY: process.env.GELATO_RELAYER_API_KEY
}
})

View File

@@ -9,9 +9,9 @@
"lint": "next lint"
},
"dependencies": {
"@semaphore-protocol/core": "4.1.0",
"@semaphore-protocol/data": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/core": "4.5.0",
"@semaphore-protocol/data": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"ethers": "^6.11.1",
"next": "14.1.0",
"next-pwa": "^5.6.0",

View File

@@ -3,26 +3,14 @@ import { NextRequest } from "next/server"
import Feedback from "../../../../contract-artifacts/Feedback.json"
export async function POST(req: NextRequest) {
if (typeof process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS !== "string") {
throw new Error("Please, define NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS in your .env file")
}
if (typeof process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "string") {
throw new Error("Please, define NEXT_PUBLIC_DEFAULT_NETWORK in your .env file")
}
if (typeof process.env.INFURA_API_KEY !== "string" && process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "localhost") {
throw new Error("Please, define INFURA_API_KEY in your .env file")
}
if (typeof process.env.ETHEREUM_PRIVATE_KEY !== "string") {
throw new Error("Please, define ETHEREUM_PRIVATE_KEY in your .env file")
}
const ethereumPrivateKey = process.env.ETHEREUM_PRIVATE_KEY
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK
const infuraApiKey = process.env.INFURA_API_KEY
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string
const infuraApiKey = process.env.NEXT_PUBLIC_INFURA_API_KEY as string
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
const provider =
ethereumNetwork === "localhost"

View File

@@ -3,26 +3,14 @@ import { NextRequest } from "next/server"
import Feedback from "../../../../contract-artifacts/Feedback.json"
export async function POST(req: NextRequest) {
if (typeof process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS !== "string") {
throw new Error("Please, define NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS in your .env file")
}
if (typeof process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "string") {
throw new Error("Please, define NEXT_PUBLIC_DEFAULT_NETWORK in your .env file")
}
if (typeof process.env.INFURA_API_KEY !== "string" && process.env.NEXT_PUBLIC_DEFAULT_NETWORK !== "localhost") {
throw new Error("Please, define INFURA_API_KEY in your .env file")
}
if (typeof process.env.ETHEREUM_PRIVATE_KEY !== "string") {
throw new Error("Please, define ETHEREUM_PRIVATE_KEY in your .env file")
}
const ethereumPrivateKey = process.env.ETHEREUM_PRIVATE_KEY
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK
const infuraApiKey = process.env.INFURA_API_KEY
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS
const ethereumNetwork = process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string
const infuraApiKey = process.env.NEXT_PUBLIC_INFURA_API_KEY as string
const contractAddress = process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
const provider =
ethereumNetwork === "localhost"

View File

@@ -1,29 +1,40 @@
:root {
--slate100: #f1f5f9;
--slate200: #e2e8f0;
--slate300: #cbd5e1;
--slate400: #94a3b8;
--slate500: #64748b;
--slate700: #334155;
--blue200: #bfdbfe;
--blue500: #3b82f6;
--blue600: #2563eb;
--blue700: #1d4ed8;
--blue800: #1e40af;
--blue900: #1e3a8a;
--blue100: #dde6fc;
--blue200: #c3d4fa;
--blue300: #9abaf6;
--blue400: #6a95f0;
--blue500: #4771ea;
--blue600: #3555df;
--blue700: #2940cc;
--blue800: #2735a6;
--blue900: #253183;
--blue950: #1b2050;
--darkBlueBg: #00020d;
--slate50: #f7f7f8;
--slate100: #eeeef0;
--slate200: #d9d9de;
--slate300: #b8b9c1;
--slate400: #92939e;
--slate500: #747583;
--slate600: #5e5f6b;
--slate700: #4d4e57;
--slate800: #42424a;
--slate900: #3a3a40;
--slate950: #26262b;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: "Outfit", sans-serif;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
height: 100vh;
}
body {
@@ -33,17 +44,30 @@ body {
p {
line-height: 1.5rem;
font-weight: 300;
overflow-wrap: break-word;
font-size: 1rem;
}
b {
font-weight: 600;
}
.key-wrapper {
padding-bottom: 1.5rem;
padding-left: 0.5rem;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
max-width: 32rem;
max-width: 40vw;
min-width: 35rem;
margin: auto;
padding: 1rem;
height: calc(100vh - 7rem - 1px);
padding-bottom: 5rem;
min-height: calc(100vh - 3.5rem);
}
@@ -57,28 +81,25 @@ p {
margin-bottom: 1rem;
}
ol {
padding: 1rem;
}
li {
margin-top: 1rem;
}
h2 {
font-size: 2.25rem;
font-weight: 500;
margin-bottom: 1rem;
line-height: 1.2;
}
h3 {
font-size: 1.125rem;
font-size: 1.15rem;
font-weight: 500;
}
.divider {
height: 1px;
background: var(--slate500);
opacity: 0.6;
border: 0;
border-style: solid;
border-bottom-width: 1px;
width: 100%;
border-color: var(--slate400);
margin: 2rem 0;
}
@@ -89,31 +110,44 @@ h3 {
}
a {
color: var(--blue500);
color: var(--blue400);
text-decoration: none;
}
a:hover {
text-decoration: underline;
text-decoration-color: var(--blue400);
}
.button {
background-color: var(--blue800);
width: 100%;
padding: 0.8rem 1rem;
border: 1px;
border-radius: 100px;
cursor: pointer;
color: var(--slate100);
font-size: 1.125rem;
font-weight: 500;
transition: all 200ms linear;
margin-top: 1rem;
margin-bottom: 1.5rem;
opacity: 0.9;
font-weight: 400;
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform;
transition-duration: 200ms;
padding-left: 18px !important;
padding-right: 18px !important;
height: 2.5rem;
min-width: 2.5rem;
font-size: 1rem;
-webkit-padding-start: 1rem;
padding-inline-start: 1rem;
-webkit-padding-end: 1rem;
padding-inline-end: 1rem;
background: var(--blue500);
color: white;
background-image: linear-gradient(to right, var(--blue500), var(--blue800));
transition-timing-function: linear;
width: 100%;
border: none;
display: flex;
justify-content: center;
height: 3rem;
align-items: center;
justify-content: center;
}
.button:hover {
background-color: var(--blue900);
background-color: var(--blue800);
background-image: none;
cursor: pointer;
}
.button:disabled {
@@ -123,54 +157,126 @@ a {
.button:disabled:hover {
background-color: var(--blue800);
background-image: none;
}
.button-stepper {
cursor: pointer;
color: var(--blue600);
color: var(--blue500);
font-size: 1.1rem;
border: none;
background: none;
width: 4rem;
margin: 0 1rem;
display: flex;
justify-content: center;
}
.button-link {
.button-stepper:hover {
text-decoration: underline;
}
.refresh-wrapper {
color: var(--slate400);
display: flex;
align-items: center;
}
.refresh-wrapper:hover {
text-decoration: underline;
}
.refresh-button {
cursor: pointer;
color: var(--slate300);
font-size: 1.1rem;
border: none;
background: none;
padding-right: 1rem;
display: flex;
align-items: center;
}
.refresh-button:hover {
text-decoration: underline;
}
.refresh-span {
width: 1.5em;
height: 1em;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
vertical-align: middle;
}
.refresh-icon {
margin-inline-end: 0.5rem;
}
.stepper-icon {
display: inline-flex;
align-self: center;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
}
.left-pad {
margin-inline-end: 0.5rem;
}
.right-pad {
margin-inline-start: 0.5rem;
}
.stepper-icon svg {
width: 1em;
height: 1em;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
vertical-align: super;
}
.box {
padding: 0.8rem;
border-style: solid;
border-width: 1px;
border-color: var(--slate500);
border-radius: 4px;
border-bottom: 1px solid white;
padding: 0.8rem 0;
max-height: 50px;
}
.box-text {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin: 0.5rem;
font-size: 1rem;
}
.header {
display: flex;
justify-content: space-between;
padding: 1.5rem;
padding: 0 1.5rem;
height: 3.5rem;
}
.header-left {
font-size: 1.125rem;
font-weight: 500;
text-decoration: none;
text-decoration: none !important;
display: flex;
align-items: center;
}
.header-right {
display: flex;
gap: 1.5rem;
align-items: center;
}
.footer {
@@ -188,6 +294,57 @@ a {
background: var(--slate500);
}
.users-wrapper,
.feedback-wrapper {
max-height: 300px;
overflow-y: scroll;
}
.keys-header {
margin-bottom: 1.5rem;
}
.users-header {
font-weight: 700;
font-size: 1.125rem;
font-family: "DM Sans", sans-serif;
}
.join-group-button,
.send-feedback-button {
margin-top: 1.5rem;
}
.github-icon {
width: 1.5rem;
height: 1.5rem;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
color: currentColor;
}
.github-button {
cursor: pointer;
color: var(--slate100);
font-size: 1.1rem;
border: none;
background: none;
padding-right: 1rem;
display: flex;
align-items: center;
box-sizing: border-box;
display: inline-block;
overflow: visible !important;
fill: currentColor;
color: #f0f6fc !important;
vertical-align: middle !important;
width: 2rem;
height: 2rem;
}
.loader {
width: 25px;
height: 25px;
@@ -196,7 +353,7 @@ a {
border-right: 2px solid transparent;
animation: spin 1s linear infinite;
z-index: 20;
margin-left: 1rem;
margin-left: 0.5rem;
}
@keyframes spin {

View File

@@ -0,0 +1,177 @@
"use client"
import Stepper from "@/components/Stepper"
import { useLogContext } from "@/context/LogContext"
import { useSemaphoreContext } from "@/context/SemaphoreContext"
import { useRouter } from "next/navigation"
import { useCallback, useEffect, useMemo } from "react"
import Feedback from "../../../contract-artifacts/Feedback.json"
import { ethers } from "ethers"
import useSemaphoreIdentity from "@/hooks/useSemaphoreIdentity"
import { useState } from "react"
export default function GroupsPage() {
const router = useRouter()
const { setLog } = useLogContext()
const { _users, refreshUsers, addUser } = useSemaphoreContext()
const [_loading, setLoading] = useState(false)
const { _identity } = useSemaphoreIdentity()
useEffect(() => {
if (_users.length > 0) {
setLog(`${_users.length} user${_users.length > 1 ? "s" : ""} retrieved from the group 🤙🏽`)
}
}, [_users, setLog])
const users = useMemo(() => [..._users].reverse(), [_users])
const joinGroup = useCallback(async () => {
if (!_identity) {
return
}
setLoading(true)
setLog(`Joining the Feedback group...`)
let joinedGroup: boolean = false
if (process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK) {
const response = await fetch(process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
abi: Feedback.abi,
address: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string,
functionName: "joinGroup",
functionParameters: [_identity.commitment.toString()]
})
})
if (response.status === 200) {
joinedGroup = true
}
} else if (
process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT &&
process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID &&
process.env.GELATO_RELAYER_API_KEY
) {
const iface = new ethers.Interface(Feedback.abi)
const request = {
chainId: process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID,
target: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
data: iface.encodeFunctionData("joinGroup", [_identity.commitment.toString()]),
sponsorApiKey: process.env.GELATO_RELAYER_API_KEY
}
const response = await fetch(process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
})
if (response.status === 201) {
joinedGroup = true
}
} else {
const response = await fetch("api/join", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
identityCommitment: _identity.commitment.toString()
})
})
if (response.status === 200) {
joinedGroup = true
}
}
if (joinedGroup) {
addUser(_identity.commitment.toString())
setLog(`You have joined the Feedback group event 🎉 Share your feedback anonymously!`)
} else {
setLog("Some error occurred, please try again!")
}
setLoading(false)
}, [_identity, addUser, setLoading, setLog])
const userHasJoined = useMemo(
() => _identity !== undefined && _users.includes(_identity.commitment.toString()),
[_identity, _users]
)
return (
<>
<h2>Groups</h2>
<p>
<a
href="https://docs.semaphore.pse.dev/guides/groups"
target="_blank"
rel="noreferrer noopener nofollow"
>
Semaphore groups
</a>{" "}
are{" "}
<a
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
target="_blank"
rel="noreferrer noopener nofollow"
>
Lean incremental Merkle trees
</a>{" "}
in which each leaf contains an identity commitment for a user. Groups can be abstracted to represent
events, polls, or organizations.
</p>
<div className="divider"></div>
<div className="text-top">
<h3 className="users-header">Group users ({_users.length})</h3>
<button className="refresh-button" onClick={refreshUsers}>
<span className="refresh-span">
<svg viewBox="0 0 24 24" focusable="false" className="refresh-icon">
<path
fill="currentColor"
d="M5.463 4.43301C7.27756 2.86067 9.59899 1.99666 12 2.00001C17.523 2.00001 22 6.47701 22 12C22 14.136 21.33 16.116 20.19 17.74L17 12H20C20.0001 10.4316 19.5392 8.89781 18.6747 7.58927C17.8101 6.28072 16.5799 5.25517 15.1372 4.64013C13.6944 4.0251 12.1027 3.84771 10.56 4.13003C9.0172 4.41234 7.59145 5.14191 6.46 6.22801L5.463 4.43301ZM18.537 19.567C16.7224 21.1393 14.401 22.0034 12 22C6.477 22 2 17.523 2 12C2 9.86401 2.67 7.88401 3.81 6.26001L7 12H4C3.99987 13.5684 4.46075 15.1022 5.32534 16.4108C6.18992 17.7193 7.42007 18.7449 8.86282 19.3599C10.3056 19.9749 11.8973 20.1523 13.44 19.87C14.9828 19.5877 16.4085 18.8581 17.54 17.772L18.537 19.567Z"
></path>
</svg>
</span>
Refresh
</button>
</div>
{_users.length > 0 && (
<div className="users-wrapper">
{users.map((user, i) => (
<div key={i}>
<p className="box box-text">
{_identity?.commitment.toString() === user ? <b>{user}</b> : user}
</p>
</div>
))}
</div>
)}
<div className="join-group-button">
<button
className="button"
onClick={joinGroup}
disabled={_loading || !_identity || userHasJoined}
type="button"
>
<span>Join group</span>
{_loading && <div className="loader"></div>}
</button>
</div>
<div className="divider" />
<Stepper
step={2}
onPrevClick={() => router.push("/")}
onNextClick={userHasJoined ? () => router.push("/proofs") : undefined}
/>
</>
)
}

View File

@@ -1,8 +1,10 @@
import PageContainer from "@/components/PageContainer"
import type { Metadata } from "next"
import { Inter } from "next/font/google"
import { LogContextProvider } from "@/context/LogContext"
import { SemaphoreContextProvider } from "@/context/SemaphoreContext"
import "./globals.css"
import { Inter } from "next/font/google"
const inter = Inter({ subsets: ["latin"] })
export const metadata: Metadata = {
@@ -32,8 +34,20 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com"></link>
<link rel="preconnect" href="https://fonts.gstatic.com"></link>
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap"
rel="stylesheet"
></link>
</head>
<body suppressHydrationWarning className={inter.className}>
<PageContainer>{children}</PageContainer>
<SemaphoreContextProvider>
<LogContextProvider>
<PageContainer>{children}</PageContainer>
</LogContextProvider>
</SemaphoreContextProvider>
</body>
</html>
)

View File

@@ -2,42 +2,42 @@
import { Identity } from "@semaphore-protocol/core"
import { useRouter } from "next/navigation"
import { useCallback, useContext, useEffect, useState } from "react"
import { useCallback, useEffect, useState } from "react"
import Stepper from "../components/Stepper"
import LogsContext from "../context/LogsContext"
import { useLogContext } from "../context/LogContext"
export default function IdentitiesPage() {
const router = useRouter()
const { setLogs } = useContext(LogsContext)
const { setLog } = useLogContext()
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (privateKey) {
const identity = new Identity(privateKey)
const identity = Identity.import(privateKey)
setIdentity(identity)
setLogs("Your Semaphore identity has been retrieved from the browser cache 👌🏽")
setLog("Your Semaphore identity has been retrieved from the browser cache 👌🏽")
} else {
setLogs("Create your Semaphore identity 👆🏽")
setLog("Create your Semaphore identity 👆🏽")
}
}, [setLogs])
}, [setLog])
const createIdentity = useCallback(async () => {
const identity = new Identity()
setIdentity(identity)
localStorage.setItem("identity", identity.privateKey.toString())
localStorage.setItem("identity", identity.export())
setLogs("Your new Semaphore identity has just been created 🎉")
}, [setLogs])
setLog("Your new Semaphore identity has just been created 🎉")
}, [setLog])
return (
<>
<h2 className="font-size: 3rem;">Identities</h2>
<h2>Identities</h2>
<p>
The identity of a user in the Semaphore protocol. A{" "}
@@ -59,35 +59,36 @@ export default function IdentitiesPage() {
public/private key pair and a commitment, used as the public identifier of the identity.
</p>
<div className="divider"></div>
<div className="divider" />
<div className="text-top">
<div className="keys-header">
<h3>Identity</h3>
{_identity && (
<button className="button-link" onClick={createIdentity}>
New
</button>
)}
</div>
{_identity ? (
<div>
<div className="box">
<p className="box-text">Private Key: {_identity.privateKey.toString()}</p>
<p className="box-text">Commitment: {_identity.commitment.toString()}</p>
</div>
</div>
) : (
<div>
<button className="button" onClick={createIdentity}>
Create identity
</button>
{_identity && (
<div className="key-wrapper">
<p>
<b>Private Key (base64)</b>:<br /> {_identity.export()}
</p>
<p>
<b>Public Key</b>:<br /> [{_identity.publicKey[0].toString()},{" "}
{_identity.publicKey[1].toString()}]
</p>
<p>
<b>Commitment</b>:<br /> {_identity.commitment.toString()}
</p>
</div>
)}
<div className="divider"></div>
<div>
<button className="button" onClick={createIdentity} type="button">
Create identity
</button>
</div>
<Stepper step={1} onNextClick={_identity && (() => router.push("/groups"))} />
<div className="divider" />
<Stepper step={1} onNextClick={_identity && (() => router.push("/group"))} />
</>
)
}

View File

@@ -1,78 +1,94 @@
"use client"
import { Group, Identity, generateProof } from "@semaphore-protocol/core"
import Stepper from "@/components/Stepper"
import { useLogContext } from "@/context/LogContext"
import { useSemaphoreContext } from "@/context/SemaphoreContext"
import { generateProof, Group } from "@semaphore-protocol/core"
import { encodeBytes32String, ethers } from "ethers"
import { useRouter } from "next/navigation"
import { useCallback, useContext, useEffect, useState } from "react"
import { useCallback, useEffect, useMemo, useState } from "react"
import Feedback from "../../../contract-artifacts/Feedback.json"
import Stepper from "../../components/Stepper"
import LogsContext from "../../context/LogsContext"
import SemaphoreContext from "../../context/SemaphoreContext"
import useSemaphoreIdentity from "@/hooks/useSemaphoreIdentity"
export default function ProofsPage() {
const router = useRouter()
const { setLogs } = useContext(LogsContext)
const { _users, _feedback, refreshFeedback, addFeedback } = useContext(SemaphoreContext)
const { setLog } = useLogContext()
const { _users, _feedback, refreshFeedback, addFeedback } = useSemaphoreContext()
const [_loading, setLoading] = useState(false)
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (!privateKey) {
router.push("/")
return
}
setIdentity(new Identity(privateKey))
}, [router])
const { _identity } = useSemaphoreIdentity()
useEffect(() => {
if (_feedback.length > 0) {
setLogs(`${_feedback.length} feedback retrieved from the group 🤙🏽`)
setLog(`${_feedback.length} feedback retrieved from the group 🤙🏽`)
}
}, [_feedback, setLogs])
}, [_feedback, setLog])
const feedback = useMemo(() => [..._feedback].reverse(), [_feedback])
const sendFeedback = useCallback(async () => {
if (!_identity) {
return
}
if (typeof process.env.NEXT_PUBLIC_GROUP_ID !== "string") {
throw new Error("Please, define NEXT_PUBLIC_GROUP_ID in your .env file")
}
const feedback = prompt("Please enter your feedback:")
if (feedback && _users) {
setLoading(true)
setLogs(`Posting your anonymous feedback...`)
setLog(`Posting your anonymous feedback...`)
try {
const group = new Group(_users)
const { points, merkleTreeDepth, merkleTreeRoot, nullifier, message } = await generateProof(
const message = encodeBytes32String(feedback)
const { points, merkleTreeDepth, merkleTreeRoot, nullifier } = await generateProof(
_identity,
group,
feedback,
message,
process.env.NEXT_PUBLIC_GROUP_ID as string
)
let response: any
if (process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK) {
response = await fetch(process.env.OPENZEPPELIN_AUTOTASK_WEBHOOK, {
let feedbackSent: boolean = false
const params = [merkleTreeDepth, merkleTreeRoot, nullifier, message, points]
if (process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK) {
const response = await fetch(process.env.NEXT_PUBLIC_OPENZEPPELIN_AUTOTASK_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
abi: Feedback.abi,
address: process.env.FEEDBACK_CONTRACT_ADDRESS,
address: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
functionName: "sendFeedback",
functionParameters: [merkleTreeDepth, merkleTreeRoot, nullifier, message, points]
functionParameters: params
})
})
if (response.status === 200) {
feedbackSent = true
}
} else if (
process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT &&
process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID &&
process.env.GELATO_RELAYER_API_KEY
) {
const iface = new ethers.Interface(Feedback.abi)
const request = {
chainId: process.env.NEXT_PUBLIC_GELATO_RELAYER_CHAIN_ID,
target: process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS,
data: iface.encodeFunctionData("sendFeedback", params),
sponsorApiKey: process.env.GELATO_RELAYER_API_KEY
}
const response = await fetch(process.env.NEXT_PUBLIC_GELATO_RELAYER_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
})
if (response.status === 201) {
feedbackSent = true
}
} else {
response = await fetch("api/feedback", {
const response = await fetch("api/feedback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -83,24 +99,28 @@ export default function ProofsPage() {
points
})
})
if (response.status === 200) {
feedbackSent = true
}
}
if (response.status === 200) {
if (feedbackSent) {
addFeedback(feedback)
setLogs(`Your feedback has been posted 🎉`)
setLog(`Your feedback has been posted 🎉`)
} else {
setLogs("Some error occurred, please try again!")
setLog("Some error occurred, please try again!")
}
} catch (error) {
console.error(error)
setLogs("Some error occurred, please try again!")
setLog("Some error occurred, please try again!")
} finally {
setLoading(false)
}
}
}, [_identity, _users, addFeedback, setLogs])
}, [_identity, _users, addFeedback, setLoading, setLog])
return (
<>
@@ -122,22 +142,23 @@ export default function ProofsPage() {
<div className="divider"></div>
<div className="text-top">
<h3>Feedback messages ({_feedback.length})</h3>
<button className="button-link" onClick={refreshFeedback}>
<h3>Feedback ({_feedback.length})</h3>
<button className="refresh-button" onClick={refreshFeedback}>
<span className="refresh-span">
<svg viewBox="0 0 24 24" focusable="false" className="refresh-icon">
<path
fill="currentColor"
d="M5.463 4.43301C7.27756 2.86067 9.59899 1.99666 12 2.00001C17.523 2.00001 22 6.47701 22 12C22 14.136 21.33 16.116 20.19 17.74L17 12H20C20.0001 10.4316 19.5392 8.89781 18.6747 7.58927C17.8101 6.28072 16.5799 5.25517 15.1372 4.64013C13.6944 4.0251 12.1027 3.84771 10.56 4.13003C9.0172 4.41234 7.59145 5.14191 6.46 6.22801L5.463 4.43301ZM18.537 19.567C16.7224 21.1393 14.401 22.0034 12 22C6.477 22 2 17.523 2 12C2 9.86401 2.67 7.88401 3.81 6.26001L7 12H4C3.99987 13.5684 4.46075 15.1022 5.32534 16.4108C6.18992 17.7193 7.42007 18.7449 8.86282 19.3599C10.3056 19.9749 11.8973 20.1523 13.44 19.87C14.9828 19.5877 16.4085 18.8581 17.54 17.772L18.537 19.567Z"
></path>
</svg>
</span>
Refresh
</button>
</div>
<div>
<button className="button" onClick={sendFeedback} disabled={_loading}>
<span>Send Feedback</span>
{_loading && <div className="loader"></div>}
</button>
</div>
{_feedback.length > 0 && (
<div>
{_feedback.map((f, i) => (
{feedback.length > 0 && (
<div className="feedback-wrapper">
{feedback.map((f, i) => (
<div key={i}>
<p className="box box-text">{f}</p>
</div>
@@ -145,9 +166,16 @@ export default function ProofsPage() {
</div>
)}
<div className="send-feedback-button">
<button className="button" onClick={sendFeedback} disabled={_loading}>
<span>Send Feedback</span>
{_loading && <div className="loader"></div>}
</button>
</div>
<div className="divider"></div>
<Stepper step={3} onPrevClick={() => router.push("/groups")} />
<Stepper step={3} onPrevClick={() => router.push("/group")} />
</>
)
}

View File

@@ -0,0 +1,13 @@
"use client"
import { CacheProvider } from "@chakra-ui/next-js"
import { ChakraProvider } from "@chakra-ui/react"
import theme from "../styles/index"
export default function Providers({ children }: { children: React.ReactNode }) {
return (
<CacheProvider>
<ChakraProvider theme={theme}>{children}</ChakraProvider>
</CacheProvider>
)
}

View File

@@ -1,12 +1,8 @@
"use client"
import LogsContext from "@/context/LogsContext"
import SemaphoreContext from "@/context/SemaphoreContext"
import useSemaphore from "@/hooks/useSemaphore"
import { useLogContext } from "@/context/LogContext"
import shortenString from "@/utils/shortenString"
import { SupportedNetwork } from "@semaphore-protocol/utils"
import { usePathname } from "next/navigation"
import { useEffect, useState } from "react"
import Link from "next/link"
export default function PageContainer({
@@ -15,15 +11,9 @@ export default function PageContainer({
children: React.ReactNode
}>) {
const pathname = usePathname()
const semaphore = useSemaphore()
const [_logs, setLogs] = useState<string>("")
const { log } = useLogContext()
useEffect(() => {
semaphore.refreshUsers()
semaphore.refreshFeedback()
}, [])
function getExplorerLink(network: SupportedNetwork, address: string) {
function getExplorerLink(network: string, address: string) {
switch (network) {
case "sepolia":
return `https://sepolia.etherscan.io/address/${address}`
@@ -35,7 +25,7 @@ export default function PageContainer({
}
return (
<div>
<>
<div className="header">
<Link href="/" className="header-left">
Feedback
@@ -43,7 +33,7 @@ export default function PageContainer({
<div className="header-right">
<a
href={getExplorerLink(
process.env.NEXT_PUBLIC_DEFAULT_NETWORK as SupportedNetwork,
process.env.NEXT_PUBLIC_DEFAULT_NETWORK as string,
process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string
)}
target="_blank"
@@ -52,47 +42,34 @@ export default function PageContainer({
<div>{shortenString(process.env.NEXT_PUBLIC_FEEDBACK_CONTRACT_ADDRESS as string, [6, 4])}</div>
</a>
<a
href="https://github.com/semaphore-protocol/semaphore"
href="https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-subgraph"
target="_blank"
rel="noreferrer noopener nofollow"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="feather feather-github"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
<button type="button" className="github-button" aria-label="Github repository">
<svg
height="32"
aria-hidden="true"
viewBox="0 0 24 24"
version="1.1"
width="32"
data-view-component="true"
>
<path d="M12.5.75C6.146.75 1 5.896 1 12.25c0 5.089 3.292 9.387 7.863 10.91.575.101.79-.244.79-.546 0-.273-.014-1.178-.014-2.142-2.889.532-3.636-.704-3.866-1.35-.13-.331-.69-1.352-1.18-1.625-.402-.216-.977-.748-.014-.762.906-.014 1.553.834 1.769 1.179 1.035 1.74 2.688 1.25 3.349.948.1-.747.402-1.25.733-1.538-2.559-.287-5.232-1.279-5.232-5.678 0-1.25.445-2.285 1.178-3.09-.115-.288-.517-1.467.115-3.048 0 0 .963-.302 3.163 1.179.92-.259 1.897-.388 2.875-.388.977 0 1.955.13 2.875.388 2.2-1.495 3.162-1.179 3.162-1.179.633 1.581.23 2.76.115 3.048.733.805 1.179 1.825 1.179 3.09 0 4.413-2.688 5.39-5.247 5.678.417.36.776 1.05.776 2.128 0 1.538-.014 2.774-.014 3.162 0 .302.216.662.79.547C20.709 21.637 24 17.324 24 12.25 24 5.896 18.854.75 12.5.75Z"></path>
</svg>
</button>
</a>
</div>
</div>
<div className="container">
<SemaphoreContext.Provider value={semaphore}>
<LogsContext.Provider
value={{
_logs,
setLogs
}}
>
{children}
</LogsContext.Provider>
</SemaphoreContext.Provider>
</div>
<div className="container">{children}</div>
<div className="divider-footer"></div>
<div className="divider-footer" />
<div className="footer">
{_logs.endsWith("...")}
<p>{_logs || `Current step: ${pathname}`}</p>
{log.endsWith("...")}
<p>{log || `Current step: ${pathname}`}</p>
</div>
</div>
</>
)
}

View File

@@ -1,3 +1,5 @@
"use client"
export type StepperProps = {
step: number
onPrevClick?: () => void
@@ -8,21 +10,47 @@ export default function Stepper({ step, onPrevClick, onNextClick }: StepperProps
return (
<div className="stepper">
{onPrevClick !== undefined ? (
<button className="button-stepper" disabled={!onPrevClick} onClick={onPrevClick || undefined}>
<button
className="button-stepper"
disabled={!onPrevClick}
onClick={onPrevClick || undefined}
type="button"
>
<span className="stepper-icon left-pad">
<svg viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M16.2425 6.34317L14.8283 4.92896L7.75732 12L14.8284 19.0711L16.2426 17.6569L10.5857 12L16.2425 6.34317Z"
></path>
</svg>
</span>
Prev
</button>
) : (
<span></span>
<button className="button-stepper"></button>
)}
<p>{step.toString()}/3</p>
{onNextClick !== undefined ? (
<button className="button-stepper" disabled={!onNextClick} onClick={onNextClick || undefined}>
<button
className="button-stepper"
disabled={!onNextClick}
onClick={onNextClick || undefined}
type="button"
>
Next
<span className="stepper-icon right-pad">
<svg viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M10.5859 6.34317L12.0001 4.92896L19.0712 12L12.0001 19.0711L10.5859 17.6569L16.2428 12L10.5859 6.34317Z"
></path>
</svg>
</span>
</button>
) : (
<span></span>
<span className="button-stepper" />
)}
</div>
)

View File

@@ -0,0 +1,37 @@
"use client"
import React, { createContext, ReactNode, useContext, useState } from "react"
export type LogContextType = {
log: string
setLog: (logs: string) => void
}
const LogContext = createContext<LogContextType | null>(null)
interface ProviderProps {
children: ReactNode
}
export const LogContextProvider: React.FC<ProviderProps> = ({ children }) => {
const [log, setLog] = useState<string>("")
return (
<LogContext.Provider
value={{
log,
setLog
}}
>
{children}
</LogContext.Provider>
)
}
export const useLogContext = () => {
const context = useContext(LogContext)
if (context === null) {
throw new Error("LogContext must be used within a LogContextProvider")
}
return context
}

View File

@@ -1,11 +0,0 @@
import React from "react"
export type LogsContextType = {
_logs: string
setLogs: (logs: string) => void
}
export default React.createContext<LogsContextType>({
_logs: "",
setLogs: (logs: string) => logs
})

View File

@@ -1,19 +0,0 @@
import React from "react"
export type SemaphoreContextType = {
_users: string[]
_feedback: string[]
refreshUsers: () => Promise<void>
addUser: (user: string) => void
refreshFeedback: () => Promise<void>
addFeedback: (feedback: string) => void
}
export default React.createContext<SemaphoreContextType>({
_users: [],
_feedback: [],
refreshUsers: () => Promise.resolve(),
addUser: () => {},
refreshFeedback: () => Promise.resolve(),
addFeedback: () => {}
})

View File

@@ -0,0 +1,88 @@
"use client"
import React, { createContext, ReactNode, useCallback, useContext, useEffect, useState } from "react"
import { SemaphoreSubgraph } from "@semaphore-protocol/data"
import { decodeBytes32String, toBeHex } from "ethers"
export type SemaphoreContextType = {
_users: string[]
_feedback: string[]
refreshUsers: () => Promise<void>
addUser: (user: string) => void
refreshFeedback: () => Promise<void>
addFeedback: (feedback: string) => void
}
const SemaphoreContext = createContext<SemaphoreContextType | null>(null)
interface ProviderProps {
children: ReactNode
}
const ethereumNetwork =
process.env.NEXT_PUBLIC_DEFAULT_NETWORK === "localhost"
? "http://127.0.0.1:8545"
: process.env.NEXT_PUBLIC_DEFAULT_NETWORK
export const SemaphoreContextProvider: React.FC<ProviderProps> = ({ children }) => {
const [_users, setUsers] = useState<any[]>([])
const [_feedback, setFeedback] = useState<string[]>([])
const refreshUsers = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreSubgraph(ethereumNetwork)
const members = await semaphore.getGroupMembers(process.env.NEXT_PUBLIC_GROUP_ID as string)
setUsers(members.map((member) => member.toString()))
}, [])
const addUser = useCallback(
(user: any) => {
setUsers([..._users, user])
},
[_users]
)
const refreshFeedback = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreSubgraph(ethereumNetwork)
const proofs = await semaphore.getGroupValidatedProofs(process.env.NEXT_PUBLIC_GROUP_ID as string)
setFeedback(proofs.map(({ message }: any) => decodeBytes32String(toBeHex(message, 32))))
}, [])
const addFeedback = useCallback(
(feedback: string) => {
setFeedback([..._feedback, feedback])
},
[_feedback]
)
useEffect(() => {
refreshUsers()
refreshFeedback()
}, [refreshFeedback, refreshUsers])
return (
<SemaphoreContext.Provider
value={{
_users,
_feedback,
refreshUsers,
addUser,
refreshFeedback,
addFeedback
}}
>
{children}
</SemaphoreContext.Provider>
)
}
export const useSemaphoreContext = () => {
const context = useContext(SemaphoreContext)
if (context === null) {
throw new Error("SemaphoreContext must be used within a SemaphoreContextProvider")
}
return context
}

View File

@@ -1,55 +0,0 @@
import { SemaphoreSubgraph } from "@semaphore-protocol/data"
import { decodeBytes32String, toBeHex } from "ethers"
import { useCallback, useState } from "react"
import { SemaphoreContextType } from "../context/SemaphoreContext"
const ethereumNetwork =
process.env.NEXT_PUBLIC_DEFAULT_NETWORK === "localhost"
? "http://127.0.0.1:8545"
: process.env.NEXT_PUBLIC_DEFAULT_NETWORK
export default function useSemaphore(): SemaphoreContextType {
const [_users, setUsers] = useState<any[]>([])
const [_feedback, setFeedback] = useState<string[]>([])
const refreshUsers = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreSubgraph(ethereumNetwork)
const group = await semaphore.getGroup(process.env.NEXT_PUBLIC_GROUP_ID as string, { members: true })
setUsers(group.members!)
}, [])
const addUser = useCallback(
(user: any) => {
setUsers([..._users, user])
},
[_users]
)
const refreshFeedback = useCallback(async (): Promise<void> => {
const semaphore = new SemaphoreSubgraph(ethereumNetwork)
const group = await semaphore.getGroup(process.env.NEXT_PUBLIC_GROUP_ID as string, {
validatedProofs: true
})
setFeedback(group.validatedProofs!.map(({ message }: any) => decodeBytes32String(toBeHex(message, 32))))
}, [])
const addFeedback = useCallback(
(feedback: string) => {
setFeedback([..._feedback, feedback])
},
[_feedback]
)
return {
_users,
_feedback,
refreshUsers,
addUser,
refreshFeedback,
addFeedback
}
}

View File

@@ -0,0 +1,23 @@
import { useEffect, useState } from "react"
import { Identity } from "@semaphore-protocol/core"
import { useRouter } from "next/navigation"
export default function useSemaphoreIdentity() {
const router = useRouter()
const [_identity, setIdentity] = useState<Identity>()
useEffect(() => {
const privateKey = localStorage.getItem("identity")
if (!privateKey) {
router.push("/")
return
}
setIdentity(new Identity(privateKey))
}, [router])
return {
_identity
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-monorepo-subgraph",
"version": "4.1.0",
"version": "4.5.0",
"description": "Semaphore Hardhat + Next.js + SemaphoreSubgraph template.",
"license": "Unlicense",
"files": [

View File

@@ -1,7 +1,7 @@
{
"name": "@semaphore-protocol/cli",
"type": "module",
"version": "4.1.0",
"version": "4.5.0",
"description": "A command line tool to set up your Semaphore project and get group data.",
"license": "MIT",
"bin": {
@@ -41,8 +41,8 @@
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@semaphore-protocol/data": "4.1.0",
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/data": "4.5.0",
"@semaphore-protocol/utils": "4.5.0",
"axios": "^1.6.7",
"boxen": "^7.1.1",
"chalk": "^5.3.0",

View File

@@ -13,6 +13,7 @@ import checkLatestVersion from "./checkLatestVersion.js"
import getGroupIds from "./getGroupIds.js"
import { getGroupId, getProjectName, getSupportedNetwork, getSupportedTemplate } from "./inquirerPrompts.js"
import Spinner from "./spinner.js"
import removePrePublishScript from "./removePrePublishScript.js"
// Define the path to the package.json file to extract metadata for the CLI.
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
@@ -103,6 +104,12 @@ program
// Create an empty yarn.lock file to install dependencies successfully
writeFileSync(`${currentDirectory}/${projectDirectory}/yarn.lock`, "")
// Read and modify package.json to remove prepublish script
const packageJsonPath = `${currentDirectory}/${projectDirectory}/package.json`
const packageJsonContent = readFileSync(packageJsonPath, "utf8")
const updatedPackageJsonContent = removePrePublishScript(packageJsonContent)
writeFileSync(packageJsonPath, updatedPackageJsonContent)
spinner.stop()
console.info(`\n ${logSymbols.success}`, `Your project is ready!\n`)
@@ -111,7 +118,7 @@ program
console.info(` ${chalk.cyan("yarn install")}\n`)
// Read the package.json to list available npm scripts.
const { scripts } = JSON.parse(readFileSync(`${currentDirectory}/${projectDirectory}/package.json`, "utf8"))
const { scripts } = JSON.parse(updatedPackageJsonContent)
if (scripts) {
console.info(` Available scripts:\n`)

View File

@@ -0,0 +1,16 @@
// Remove the prepublish script from the package.json file when creating a new project using the Semaphore CLI.
export default function removePrePublishScript(packageJsonContent: string): string {
try {
const packageJson = JSON.parse(packageJsonContent)
if (packageJson.scripts && "prepublish" in packageJson.scripts) {
delete packageJson.scripts.prepublish
if (Object.keys(packageJson.scripts).length === 0) {
delete packageJson.scripts
}
}
return JSON.stringify(packageJson, null, 2)
} catch (error) {
console.error("Error processing package.json:", error)
return packageJsonContent
}
}

View File

@@ -4,6 +4,7 @@
pragma solidity 0.8.23;
import {MAX_DEPTH} from "./Constants.sol";
import {SemaphoreVerifierKeyPts} from "./SemaphoreVerifierKeyPts.sol";
contract SemaphoreVerifier {
// Scalar field size
@@ -23,530 +24,16 @@ contract SemaphoreVerifier {
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
// Verification Key points.
// These values are taken from the verification key json file generated with snarkjs.
// It allows to use the same verifier to verify proofs for all the tree depths supported by Semaphore.
uint256[14][MAX_DEPTH] VK_POINTS = [
[
18358547564487905095688479908858987846616998213156437518686067355563592118237,
15662648751553932653781975807624464121405704024803073886925976686616010387354,
1545474538105908330267074270190095622354834966212647889547653097055078098224,
12579159544968648693964563165973893448704730885005100826654630574108054705556,
20602000776800724705104231353971008348678632605343811527051139864158800058742,
14100125742256756091734688090621667470723401759459592787502475801413744195297,
5090583730862410755830979584235210054631184460526892606022709842010236308675,
4935746665478263580470501879719907639988899436008466660042851826337922233613,
3603230519262933722323237889869128969156000998401789817930265262617368730462,
11467103179184542033012124498958167915605281189440445972230559164572312725202,
20354120984011889701917116306955017859695028034788955847437411305304360829487,
16952752114474306858880411587178692742589121096026762314329638709126787301483,
18678961143994743003180318723146092299060216598083112257165966782010215931454,
5866474510945308764957529269555101130643879788634167019342763906927794156659
],
[
15357842752194390032830879177519514606613356943505010426726499926726016517582,
13720528004476084359207196371475762368424714925503835663451917882430924467554,
2196656647584375999320189230399052835502476576494068012902156164580595749760,
14571933744484927053512012311263939678215066456565339237074260778179419354637,
15947740979005208428427315036716544174249364023308166418156254508145278950889,
13324328715790405384125386378518079709609297588403011236512446709595322048979,
18308129219862888344083447566760955160779532192553849267018614487088634836563,
6372459765603725576424215986727450779217530423615747931788702584026023386877,
7093003777162632186231777482293120808844116758585672698445917711442486215336,
15357576732947512625016950088762579987226580659874157718142226214458009204755,
13910597919064508360434043231000553781072135406219661606166769706745413894201,
9475901949906914147982792916474633312982452326368523201024844634638043554494,
5845138751782936895477553974859998077996624699108246120208069774017428318479,
3326095377373657419775174404381825686428913179751401123841216020519623741775
],
[
1096090542237876305763822439899873238394525438826581012748557492836778110917,
18282758355470198230938465615400409713402004038201360061031317503584711879237,
7973969975759518869552865162652900479072033124669141796195141770899882758383,
2920496587818605789230962034477809982324000981266163502059117507002917895757,
8027751638293718359199675565570157214590620386957299982399037269650333307021,
19002113380575481191643777830101182489616906893723699470070419138254788369727,
13631613009301650992828160964785768170789209232530437462516754147352285424672,
10537705110128905270703523362934130036880036854847578111990360444182641655212,
15557574650831364767567015658284909068256128766563081293491003990055297878366,
4049724481871929240016595616316679773340938699307608349394228543495262553744,
9967066649437927083270210032320564587652082866881800887188539489167094397640,
12463426560961961450861478284334163210886016242490079948590082000657390077088,
21318595425700216078579789307308348011199610228556265752904860757510620370622,
7430155508771673067823897542900534022148544854722115377830369283854627952599
],
[
14033304028688398404089545751254979569049699915340551984412184456786819712695,
17529478610649635357901422564682249462969460088983393810272144503916885638629,
968190632906420692452807865081290940343138767641492735661467959437198373032,
7242759178038747404494096998044224993169513816067824413031492987300456908934,
12017353327534072098763415761011052990865822334777878720246921848197559257711,
4746680322053291743787031203095442352574780441873349801788355375401126089939,
6764632552006100580460767171096753901452726344615530017064702126145414585640,
11581587935666673652762153205827599529022773836189155792609728856814288572033,
3123694825428833189943974730387937552931713004458396242443840668462184834558,
3432192610292569155696646287493678963086402014898209278361624573082188247990,
12349833666000936285363634772178969342930188247085371717039135170012686159900,
5587426338437935681688079936152042996259869611071713486439341129143155921959,
12022589354168680516901928073724404259700970836413687340697868887207353139344,
2351613311284811919248989036726852289804810348516261915606564943623124473717
],
[
15740655435463241944594855735935231648684671883923953096410588018036769516770,
12964751171177929169670182425240761498461607040020835118601467328036987558858,
21474571159868965455306627669334290549452576803823591301731326342326814568896,
6954370193053655486251406740905618458518953022289151868757271522548301919472,
3115002343037487520580459802807906562630507097436525958861415456096559884443,
11775142132959919266954507317832500578453517368862270948538792702813845219681,
5975456097652384580746132945351678665917860606511206167023154005883554813508,
10958037207675554032315788914627312943186758288936582678633536154169678007202,
16345185674805541466042568997276776714209785989761944600635051035243995431568,
3326264593228494909568322793066180033820330146744162800569972963329142251537,
20721047231464194965879320004420846916587593568519526251056516572985788552732,
2552439778142862614309289213707433798337671284267429041900242151271508522517,
2849386127826497959217687777221941766595094589431869464564268817450132435018,
12188539304210779665491473755999603070354632830707125660270270405780470402800
],
[
16239592155161765109648123193105804251252701943901733499502441663333912783245,
18702593988046837524790351483331632258278160532977261915119611324471253407466,
13746033878407070858115621843430829498309218839316343379025665907999784574154,
19358066347678636498093783612000296194480758342913325289131948678991962529441,
6024976123298004874848602709755399197808739071863728225378332097920450236516,
11108084608972457539770160222798307153256767409158349747526974841008717682367,
3009127146923662343754766534488769100730310563110562565512507605403185571089,
10560679284132950437595738585637379866590755950272794729013445350206405316661,
16015321530803994569819047219560485624444041236327101681073970215458831987478,
18489840631710745699731219026737904723160484479846032199737023956049067434815,
609265187318362115240245160721406765003010398230819869810290394123140807290,
2656965952206569220410287839949134856874352189248192147930831679380007159249,
13957423432693450118120092425077530751840166358932317773385901323790404449641,
7610225795517710715985874151201119876406845575780133396869144717381641586640
],
[
6482921272760726478838066628157548923897782117283646773208763176771446379138,
4562585331778730670899179927104513856322577370213643119870201750008533040214,
9299549824594530154451155704400285409056448609359755927574262701418672785771,
16654459784024455427280229763380300423080811024668332509526284511491790880990,
18178936861568428015361893654874798233785855995042899944660014774323534883903,
534506139369949013962728832141783820104682340925384016906020027968881380951,
13888044772855561714276444972404100722751042044045312252045340354941233320135,
13061437363756343100054622876229104455920015737970195589611281743974716159827,
15297052669271818809266618537917704542138894789392864971735934945598379827363,
3240592020743113440365790241401792477958041186219702004441781545015089517479,
12939402739160799630996576545137073878726141216092557580496570401396343874133,
409838859583542828209958035048329036930557790097408442597169497017958367880,
4849352055719384218783567790347020036570406423962447054960403165168624679411,
10140481868950825952506002812679553069445144019364683137830173127833535162812
],
[
4169753203433043290708949478342499350225971996935208104044673971132510531963,
16198597482473356107060462797493408464959815651823410647378959304462364790023,
17831214733154720272879709021886998538183166751338990495293296921834561417050,
15996002991058741836925286413107190453488985346498046642177496721490001022163,
12128929995926069335150064696726717100038806543084523729572253928762150006902,
1527343541447603983494013575570118174442170324803005341835852970207664984106,
3864366504647042739453971869413719136218296278515580744588126485271535533745,
16390744785373846505589339019032992526980013169808686005019244934399314954484,
1189371614834081242339044631966546656514169937037419744085755746584992776112,
2490564128297998291899011962907372091056992851367564813460897014374926950158,
2632864541439030478006092584387470079076010621748787710053145987733131826177,
10997016251008884590554668186933912000821350188750456144761529496433221911191,
3662989402605074726032541754492900291134797145446056852785520146936851543244,
8371074929323402425468930212402691638137013802793901226648986870188378349904
],
[
17920452210119585965813298538098997746450528307627971419517604274103840658730,
8026613233416032931155189579997899527124867847165186585887532521124762242171,
12536429843060624487053183271774959575059067729019923970247266906616071589989,
18354222295715868456732739635697044486544782691576216892030243636076554800619,
11685593308965088606881675161829854229906033467171784802160080423031157953626,
18989841286028554273231159314070667749621876499337485447347239057791285949659,
13501500842653069022700095920888317808542113497043735775280862312089436522286,
16284422417487952110266526583186344607656490299306406671512902584454645262294,
14766820041476554952520399418749355774195705334216487399328042021346008099854,
11502099463338241997177160748027482497157165595330950109059924501733819344412,
21097733162892834226328090737666232905549661288100963226189626007151883115218,
3620141777236347892405766912767968106066233413607983266884777435591408542679,
4465316625088681267432956930147995293521314127558426510839100849580054135068,
15951396696291486543574989938200386934444721629903447106494532971713975302198
],
[
21420692366857794685888663542888709905237738746850069466081467001353666342965,
18343503004862189418033094393114515169584171574852422315350418500159030922263,
16439186901063853414808045554962977634854311593865750348846556486836509716488,
15200551988732901161699976788357951085426436066677048420098461828563894176150,
15140772590596966074591171894694986645347795546765667852915300358255369432294,
7383386342436648909729802223228006548918015494414484659175617833341830753463,
11436445698241305906567677067532324081573492145508451249291326304016376374466,
17397405229027848655285535331264669055168427730382628461971653096729174692794,
8888190346365862431131132945799487885295183925892581338098808269532220115208,
17373048493258440814074078107890527278667903472831731635546171123117085702144,
5394355195223713516914582580686192473163629785306318732489822694588538915692,
20814957740385525027786677509245187599649792998372465800981035312224123940783,
11167741662268878371451552983943563550747492198375641214347145843414778750740,
1505498991925224080559736158020686494389967648228591899080542175743913505975
],
[
8482807834840099486107357849095958421708288941420679407730439668240369271197,
1531932691795154082010331247272128035283420450879984505970978649526303671013,
10326017741190716069982105202291613302347042236075737537452333444753171570010,
2890563104449202149521252385842115871596603958515320789619311677428773944295,
5091938011714608365574587822261119297677309310900626302766934784886036216676,
18792973255357094538588824962661759194320829424712347846315600994520652609459,
5819484726278895533547092474664732368175576227992878488267454637556311136768,
14087278759052154922504944654932471722205352537489748711235261956958139094423,
6676755499836944199268283133886528716777488598645051771936175647684814488319,
7841200200792172536039490995922340397104113825218911994623753022413575084536,
9685171750835271647846188024034904289604883281120913275229696726161494108338,
13804722593058778047599265964893015518608567919815229008355552695901539135617,
133210224564739370698401112580329091433152068231765294734991529050629411851,
6253365067148837443745536970484493754157158998156041417978340186561909915882
],
[
6379626794062388565530320965673584683811331210463512233691169393056454417810,
8031021217500376290269114216814836477415391402921787637085737712949651005952,
15261959534341262089656432084966075417921918036565394975811438856221288978192,
12412675319987657724460960278402203548317535126494687402198671892291826563464,
11594484527416994136900781664743660516883697944736099448760569480817952218099,
5525949004768282420418522754788387377346850869414250693501350383184014395566,
13423677678153887686951876961584096043047689175638209759158420018856273430250,
688554022717474500337948897714325469989973507431329797109415877246281679190,
5767985312159947447966233995178318554138266544591427341210101818005833690773,
13782057493439290506357575012457041256926849070794382612465582256292384507590,
2009465632383454183075946487099156558696455704620200103263777377956167571948,
10265570962161934109202420603055144010322859077969741656080416572925588897009,
13063467510206676485181697613068184940643350938488359709447602318070297992418,
8824580488237789516855671915345935747743201560548603121129517348234754630838
],
[
18405974527641184935569939050199806786119735189423462681352004154947586987761,
11063658239692825381704700810385108349384459703800229121613802621026834850995,
20401912636755055463157317129314482008782101856095804626717136888886428939725,
10581036997862130058603889786198200057133900928078268413900852134308841628552,
15613862437263830065893280422700893831122147824370200118126675792748158214283,
11637898091445829201992956909089879348463617460955895182594618572267100421779,
676470684249461112964281503193041675013396554434239929609436328672155420783,
14862758280768060051884504554805186980208629806423451755599092137651959992706,
5623342967419780942118234966618900971275224510117264341831041912523393680166,
12293742687505619727765346377361630310803471543338450439759434637239250426631,
17107107724389526013252251054585363312805578717860151655674796329456502453436,
695490429984933474058785653390434166254929169748519672533632124843844650437,
7941603993861390710630117468483386570984050378175531457457840811645822985465,
19423663035279971057851778008344970269742436279020301703706239058210708410668
],
[
2844460676842285471844840162496739784337096369846435331204280645139535043731,
5914749649291606384462747717764850940787906745751128721215181537027495043325,
16403998562201315274383761287898474039980386929670468025842124690312505385798,
16679714051449621657256662882211432986285335589270632187081448168743144646010,
14178974435133537452754432783693851994073934244854394772136599698341675338748,
14490318493007296294817313593753116388501252549516359980240258503496717340194,
21219478166573360512901478467779541318881953172337799756939010190701884653821,
13653038712207413996195005796658436532811211815454701512198612316602372800026,
6606031466185873676955137126631780808678269492505994174970319773811652852017,
6998326006251734945119834407770954155028321677085545151592873301468610324946,
15717984973502827230694305820570642040862757036680118080574899662027439132392,
6129387663611887185666499162725019000386957238200546358846681873950634080364,
3229894653990057163047872622628926092609943988699832798310941005306795398260,
1577249093608064810495237122250056987651980088410811739655744853476971398741
],
[
8019490235657930229602545685025618469913840887375206662306714562639338096359,
6360514614281299182411878013125972206098844277909449064382248671632240409416,
18532505668867290379738328175003759079607042632729982459107375168365918757976,
8421518624327767035539667378193845962377888010421324291966623261409058898245,
21508024236353721936402111331734487542417525255582275314005272967405040862839,
18027689383014810715963711252886295463940938266456411644747464137365500951807,
14484077699638992615220759300878276902226958277985946809174186953862915299590,
4817080763362108602919187869554992685382108795016276838137423588157592666796,
10791657063117982548380087239678382293931165307389242284595466175088416832331,
17574587559710800088797913763598808892829608388483075257576879500511250128297,
20931338330271163055101602391315623325223860904427973201832184784566097488773,
1954574324880132355431783868495392698894997264747376529310223470792870288803,
2551137710278149502571112114560159376697849893483916552857521579500208583200,
3997814265160290573081282672183091638735659350920634229735367532175023689675
],
[
20759074837657564809501685143530456377562536015816086555379080667602653298306,
11573288866341175121647407708978273297857024597782918874282176717371576773130,
19475107603336226504587469711392819869087288902355805230614724291289122375846,
21884242265301052283286073107133504985083194336113478618838523331660374213570,
11844625750737259417493690805104254337758743574820507915512371579679338049474,
18479163117067129250021591308069049721232170743585134941796617403156042279597,
4434911559893931929914698652677389633068778061297646529129767359157675249407,
316682746098441691626372255125560321251096997722401729182940832349927288255,
19610390525670030492896894087745165507340241783776573708027658938288182681300,
5840208148535790468526125686220196099566194081164771919666034943299219873755,
3679027218793663842409677356801552901605408436635647286999251784339864591201,
9878321578558671609403512127325051261043472923444011356477587484000484178928,
16646455734597629493777237097088292344110223995728568379569260368267096014288,
14735311379463771264009437608444808852233202023120148855228542005281236140064
],
[
3066170574229466435407264700502616839626082070514501523679452764935485028736,
7951387307333182634684754650901435973768779794218900331714625086350726274942,
13578824606544430966133042087468301830727811282121948825028360301706303669231,
19848381031896652139349791682530465833719275685855743122849792015759588531339,
6922136549797750291447751953663854475218048098902194660515442295348938322083,
10287261443878564608994021014993200221021609196127927226041534661185500281120,
6329063805909277980282354325384845982783657973381777424581891744521604640994,
11017548748010510224711773916683171526878158646735796493859902304094594577338,
7338335804036221772945379382782674399589206056354184002757176151341198318122,
16538115574966264108203522400275571374556020887608210819563613080068710593180,
5138245976626127736555381649425906350640183768145541963359703291501245587848,
11347291457433539838423910567581114929056891897670787919546976342310334767900,
16731418617609356258989018213857655050257827940403117452476763890174877962606,
5300557287595854140445529914668848275536281916366261035684431572728600543772
],
[
6573154341426354993599623914164155921131813615298607946435982334364383320793,
16419308144058642981524756443290703631729426627385646905142158478345164404879,
942314767315789144256266064192022265579304275774793342260835421710673918285,
17945712678641984649495876620223190782305382105763957622870181201252059717682,
6497446328454795535775520142893202697197882656922991300092165933292014766725,
4597431274747983679157649737399090093759447324935531801532881928263496852124,
20581664438782214735167492264807215952133504025063870863776714994387749970180,
5854805250432620287068939301087113989827350315462338534819773170350910225622,
13548539273975522227017059057161374261181128673406746320122994151943985128196,
7414800418339434590171697383031637744601564309993253226498272110927128779715,
1052987139013233499761917411027037646861657729931697227519754049539833189269,
657108667626796780066815408290681939596246857020023912757838581820942772606,
19088282520683145597098955555305422198780142332183007920340899996970202127885,
12616611543293706969401642310383814806112402432261338062963427055972449363741
],
[
9271002136483424788269278316391606491360153732024211579417926107994995432826,
8228171988949250866347662896961764196608750080646539001443256474901139877051,
20240081759615964816136232877050251456333669788276947762731625798225823502998,
3685474186777860155223706676482968796090983045736466861690878558020083034916,
305741399293956298249448376598537769086716682101868856634885453070917344627,
14942830908704142867090451021371809832404069532430585621173997534136021340349,
11873341523902185373029537495825388400298468809112431373607438726587086076801,
16566421774425889929886838459987430622148040878072136298073788804726016806526,
18314173705630320437871113612645566255775444265992974192826331109357704470403,
8597072000455186494551694692524831407069966911367008568012412188890924300508,
12713907619301764178052509321657058919935892208409394514649600000706175319189,
14893305145776480356274920935320977108910444566603040558476174175562031483300,
11027938853766719633497710751595847377263279173227878474215846011660771149283,
6927793728403485743741891409676155921703126599118383623637742555953569891357
],
[
275116175553159498718561489405169511232715998055900506709208190227728439831,
7338708370982730261395030177227912514214944721567888714384503728042214055309,
2285508597732647746841213906783440647997136124356359059650028586535477309792,
15163443940499746648640851269666923560658903809778640616581862089179343108182,
37868753390676617287004841173348795594362354905038492583057282228528019603,
19475937072595290694509025801956972632863465524774747773770243946674956142538,
1818532521520079200500527816308109106767855745862413136331026404438772138114,
7893556755641665136576228990240239515272703124353568551151593029797349984766,
21843411659343488969197036446870567462789014279182131087406329675847260538394,
13883536936296384480685931731174096875043607202415233199362935327975006076376,
3061885619227488514362869971925298711535995206671454426027635264218303442708,
18477632669759047471715211461337808302603089797347923153039515976242018999984,
4953684980989921770137053964305439167945572062294709110871332076115076441738,
849590699713478394267684876803414882497887483062076673282369901261463387635
],
[
7481617454708320190331411214970150566519243590120906863698168124347483283307,
3790897889674729687102011235738708037383393765058266352188381434189575086080,
17582850308142585333519054672998882111865339708436809129995518706804527076353,
18961585057625546222763334757505522771740769338010572292783220912986926586854,
17761332237343741278668998123360108574589045018570742689473320560784505694171,
2985768806786881176362869973473950745997650698247163897069614623128281191971,
14099532828736062687388547070054719462342298981811592749594569670955512096417,
11038429458121896617356666499000022639824993159854464409767840206807807728043,
7092464867594165410092487979619486929166817679669939558999555261465867685619,
20690943609696626243672018055336898909740557628366317533030490341400911534771,
11468803355345327303851639215186997122074583511720489615730106184659306943551,
9723340381470060111632263437706139036358918795037011403763820908081655273682,
15929497108714526572140462634902391796285476840034863688822264979709196730555,
10556139316790113226399166507094772235069235781001645893008903131855134732783
],
[
9679690373149117563754317307037586538394929348733117229177073999196519450461,
13953490152873041611053779700802518995304489998104548903919774028525032867964,
8584860336778813488021026261425560177968889952950706471574873674510806966419,
8400619522468195192079024924375785176686244213372269992523849676384018875300,
16018239095599670975582212156736908990475077583136160880304021421989907078233,
13442762142079759258078337448325782252795445513077684243558458356586404542166,
8012524517439221218249889438165569497775551565363444399021079689755695756644,
18993442931337392722189844722480176040693468853419121807183123246184718322422,
3920077716342530896195446297162279477088824676672184510151991496745985467962,
5663885918690734602622426696143772526257235018784490039324179199552252272203,
11007942216549411481832816505096362871539130535791764225892613523847180067807,
12333277086717649179464584335417603775633093807601488202185840108448843332123,
18845646001611639216437777320622198530894193094859924604338859788769244491906,
4365664869724113934112630479809518948808449158812862195377335314227128146059
],
[
1895928299034844696630794694609519515092896092191683631304721647222032914779,
19026513891744713045426845531420132126578554294461150386909840193098440147673,
4073281111734161932072345995811001896063226222777392994725894652964051683943,
13362867147840304033834065229457670563442204439046527165143934160967798444725,
9724485076061228092177286932258189815958450833155679889060988975712535081230,
1627333086421877964064603957348348763696708139082607562629629725119997724989,
15641874381988682075545920458678901707167602315586561132909307694310257446023,
11034182059786563285109970430313289917032071817373248775707546493147901388113,
19299574745226772810381056007321573284793444116746272581694295128392282602507,
6482638271546132546782310681506292669989505915370438641175376336582811537739,
5515138970831679245126906315331906152285174207704247085730757090763031968272,
5476746571008230667726688443817396210804752373221945489797046634505665572661,
7666694240010574980777401583687953099995588711474009270339615112182231942529,
5345423812126487230177352826531606752132805611025916574123407915411930666385
],
[
7211419275788152379372992549185439317698375419836488104253705518694042119228,
9112140750806762434510825375931543886135367141484613422947675423683311130537,
12020406779776320543918475257645763209221278449775176154727249143619468329590,
6961266423823329910790066424248133365666435921221127260870444632539329606224,
3527954161191330198309290076708590175518992377857531220243324230315686986882,
4506493800007416260514839382433205292331764028735360433653631210611507932973,
5530043493028748853396066194331787195114268917530734310055878976603589658986,
6225101949608434111198442012357272827532649788667254718474232856896193900534,
18857681750145313162493356993928966938826030906289025101399379263672964054354,
869004496821135911657110194622810910776043851317139916414752924319830673140,
1563829187789877652048924285544523323087888587074484491222967490033068091506,
3746011388196035005128740753677692387874351474501361202463946309770129429478,
8923361680602360491637539340186330583808472610027697444204036893010926051377,
17386658730777389148551542774423634880430074554050371095211396948875032586750
],
[
18803497674827878184210135371703804206276128582022416604041787392310845729622,
6590008305704976915857671866558706505394630312395969823040635040879201337002,
2714759247406808259589803854440914533632699567907406761316959511568030744066,
16299600292583383998706243035294548578562168326056377699804434906128380481545,
18030052417377603682453955579175094175373404791176719861146533099419481910116,
8281176924556272137773300347187527516223668703826908452855802099328657344885,
11849913964821118293258226409033507680960291656604016015128854810099746642358,
2718653438901851962181612429288634518502998150085578586248082443515454453331,
17998120665039026798317726060462551095622279047136565816648549826384179735803,
5133986071087432716437635164720916024596119526725252628340805179596147643344,
10436725621240227608920674037516192343160590540839553356331196590007025190330,
15618861474705274368161439159831328775613537777134266634959100526889759124590,
2511040106219966488942941427805413210834998861588095124665874406004322450915,
9256734357641210393451356199893573129989430877284906007481196262323584132500
],
[
9325238625126515763679853550553375879158552597544709459784109512243397955590,
8484194759795978556088297437107686617328133596604796277228418191688537911573,
7354463117736585470843139230227589188304331389476818932256765377140053168035,
13482530129860761195447497269660263095272961608736579417124458190809007451755,
14565877561081097978808851096191380459292726072163754601747539666057949167693,
2135718143241813932226161801358235289781058013695871838383051572102928884567,
20522747851108608773003772892187458826390403588440155512773881116135635256410,
11218511591600821722003994140994121719832310771637604152054113941332818455369,
16404237709834224719800904205708261378663612035126521203425485585484994986837,
3167586669955731698085513002461997957955073343333183557668566807567186590619,
12910675356590890481798719900077391291951346627685199305549632303581651173802,
20462953503625657093808736208830478011818679863351201550868889073055617578896,
18947108562530644410102590841857357185115081182319111952079371871969663671988,
6652719222291337824561052377450295064566587460338214284424446330320206208978
],
[
7333723286812204168407439917521565157977670700382476881790986792115201279410,
21462572925415337738214437933606587540653694853107274549824898449394152530908,
6820993392268884858152757378169835647522978080101384568523885945756789014349,
16253055713127198337468919465234896268161918860396508551871391729457324125212,
10110377608880446364161064735161091842938826397512230713135002732708361876777,
6013899729219769410326935661934883558337463050053435907100782150692294649745,
18208889227209298598015138525374980382541030144328510393048300775270787949840,
15191444075449840811990314906356975059662539527217455842253932605838538105879,
19203188682890514423320800755662084436821947463936810212920115637567986869322,
3424855308164288636262956984024538145687254883958282264766019244372264927134,
19586353501601321585672146098476085745700368665390426128801697725086439710122,
15010004828387861046033155948517332272437733117418549079342100218646019702080,
13686339229559293872534012092085760944059315023471369613822812965287369238447,
3695584012986626869153168308549979767804807828687034680677188403817830418810
],
[
11102327427527201346056529148642207216130990405495165914761901542247835149412,
17544563341965869668707473190805417639220912289969746146554006791986582724590,
4470848226757772603246285686584200798638888970547659211297578619392420918858,
4999887962989142396481351641254451370620928952306237803174890583736074770292,
18696621645163318552472841991871104820660024833640321869898695219244792544787,
16940838088709411711968888146075539661653566927745755478421474505108166140656,
11530916114120676768574532193664705720045810431665651204245333670674998923676,
7355883923626920336916662475522243088902821161113628716197989160163721774248,
11855011297239142909723378707832446926509921514737098047687587969894126468497,
14942813403879667533705178220673159254886774089783887482228941707848831481300,
12982663140753853847528768000921561826340636419307931766400467366396846035169,
7171806600323437636744282845777660095738436086868856062406225133619265520575,
15982491779929281894294451486893882850583039973528579274058985191703359466543,
19910319651211685401050894240685395121165652955380089146603485967076493605680
],
[
5314337765479745092537090978913989310916802510812096192767666377841447850226,
19811002121850954821192061183148615163420706271800817927960207430256612524059,
18254735365473444026840717290492248863101576601864757410600437101587001057517,
3428844080448214358238191483671878854080864964895729401025193865570307658787,
17688699129722255312471132988267997472426043097741089176095207368928695347323,
4698778325800416923484519718058460264124242609977080857699400967590134848728,
11905991584861721837480962390330989450197421918781662074678555052926188909272,
11195321655863853696452219195252788379254952714823481930861848719672010792417,
7364573423043519994861038175593500896079924196888521130462378149111415036167,
8488161531239994007634631892382512438657593769374020273048837520623507271908,
10948897450624334536526533930990935852623955696383743452358741253735922067160,
7654175296077985337834288232610181411799310934515705881481549241949669590123,
2456818423512317060112219756429819064402183920202453945509918337536940292593,
10561627566351771351550703479997725668661012955063201536370060753602302262655
],
[
4310089243116651250383251477034324245457116277666484671624575402227833925755,
11882651094700172542567008359015417490389070633573140242127755563781024148099,
9304328383406369649010049197573360507944684656613297568584394172735340111263,
18874624159090765871635243875933482675871258293088886749847315202391523956097,
21295163659036117126535933666532228255134275601226122998452204301238438701469,
12010652807420347304532358791037860496459429689113682253200903987591679627067,
16035147304145989851106586435462674695447030608653337914734493255503105122271,
9396862051344040260236487045030117425080665841603826234795752404308634565281,
9623434193020540057685957851610556657916120473978726845338192370747426064401,
20738972702824723087864078264786214906718601061526079118500228332898388551221,
457108501000029082366810998923133233303603111079376685755578228260824733356,
13918719735797746251051948238671198059940858851588937008268023917020073366433,
19519317439483352367895890468095276150233498159453735432212409926941855183358,
8400170000010792082337905010575114377571921640630709589910201278654198179035
],
[
9476241965146735006848999585927664857836027675817848342111996150638876938940,
20383112265143113621158547584533108172173014612497300318772355462448750327634,
10370498046215116715134085566322498900073301617448752966999679321197451973184,
20733082136685384602293372077980283048183069753990343452404863587763569081917,
209896847902324756441033880218169809685412620378498856437573937154846479551,
19434208870058033389225349051527401299247475125763108527095891214558119617655,
4154375339831547300427516624109559852426973786711444825735879648391004291098,
2168897082728012692838287354581700563166925732559863316849698306675591131396,
3690054103601385333490512469861728231387681704127049683413276534001532261943,
3997073653940540957268729302105309759820513901669570962308110503858257659002,
1493108383089723041516694658460301260449183718295935886883417227290045091286,
1479721274324005701970059663387618978577823761358404739977258141309872068056,
20291086357406391640638647514048720424247838755446061571102712546958076851767,
6860718845648137601753080432837091439893783461195961430761483584544410630099
],
[
7929983584961755765377471515178883367433439212271736050025708429355823243624,
10728358412340769313351519567620170787387770135423141966436844748162218854008,
4169855297038740915695363102363044976292665711211255871324667594694964037773,
2424224908982307794171893487036131370038399449016750026546326391873466118335,
1265438250797513961458031163301351393237543067943565114202366151377865506872,
11342865295714982458109220575532930834959120923837779800176462280225501198217,
10415384677581396651184780193811022815145977389536746022901590915883889609878,
5311187015233522007413118391261106264838418369874755037462489089469638365756,
7499079368996193403750547553190134606728655877653629403923945654291953825315,
1743769713774086589463238504150542785039161133276706463569974209707667651575,
5792276842105452143354445764064878932177699791644537942211472215636738768211,
9443070058088199873709166495831389298947366881168483562080569357428781583046,
14451507664847323254023899990839043037382802537389529773382951366995420730648,
7633550475637360595097128986678209600092185294414596687526062925070686318486
]
];
// Memory data
uint16 constant pVk = 0;
uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
constructor() {
SemaphoreVerifierKeyPts.checkInvariant(MAX_DEPTH);
}
function verifyProof(
uint[2] calldata _pA,
uint[2][2] calldata _pB,
@@ -554,7 +41,7 @@ contract SemaphoreVerifier {
uint[4] calldata _pubSignals,
uint merkleTreeDepth
) external view returns (bool) {
uint[14] memory _vkPoints = VK_POINTS[merkleTreeDepth - 1];
uint[14] memory _vkPoints = SemaphoreVerifierKeyPts.getPts(merkleTreeDepth);
assembly {
function checkField(v) {

View File

@@ -0,0 +1,482 @@
// SPDX-License-Identifier: MIT
// Part of this file was generated with [snarkJS](https://github.com/iden3/snarkjs).
pragma solidity 0.8.23;
library SemaphoreVerifierKeyPts {
error Semaphore__VKPtBytesMaxDepthInvariantViolated(uint256 actual, uint256 expected);
// Verification Key points.
// These values are taken from the verification key json file generated with snarkjs.
// It allows to use the same verifier to verify proofs for all the tree depths supported by Semaphore.
uint256 private constant SET_SIZE = 14;
bytes private constant VK_POINT_BYTES =
hex"289691d7705934b5504ae4bd7be283f3465af66f62fc7f1e66f03876b445efdd"
hex"22a0bebada6ba60c3e190e9e8c2b1420244a14c9e02868b862c7945667416f9a"
hex"036ab5249fee75e0644ed259d45fbbd0142b638e421b948f5dc00cf3ff14a530"
hex"1bcf8d4f8bf886d2c7960badc94b3abf6beb4e43571d2b4b0f14928c10e0d594"
hex"2d8c51b7fa4ea9ea16765377aaae4ae0a416a89b600fc0b8ec35e9e6e5621976"
hex"1f2c636b4954a865946d69fed3ecd2bb60a61af38fa31f2a290ae28915d1f6e1"
hex"0b412b14d9dddf3f9031ffb51eb3f73602b9e49cfa9bec4a02ec9c0e3020ccc3"
hex"0ae9889ae5f4f6021af9e16dd1f2c445ed863fd6a374b329337f2fef4715350d"
hex"07f75b300b401d2435b96459d2b64f6f848411f246d8478199dd2351a35c1b5e"
hex"195a26806d907b6d9a9a9c235e09a48e94f8eb8da80f0d40bc4143e3d006e6d2"
hex"2d0006337513747c51f8f3e87364d2852113a83e586ef629c88cee6d4cbd422f"
hex"257aeaec24103ea15e4592c32d0ad9846ff1a2f3a836e0c19947980912b9006b"
hex"294bead7a3378f80183af735f6bc8529ddc73d9e0a35d594dcf93524403c9e3e"
hex"0cf84e9163744a9a65520f4b8cbb4ca35c428d1c4a5789e11f42636c6d197473"
hex"21f43b1ffa301d565dbc37ef1eb2ef669b8a1876e3754b79657b26fe43c845ce"
hex"1e558b2ca618dfa02f0d640fdd45f56492a577154989cd09523829b5e15f2d62"
hex"04db437b7b4fa0f6eea95403dd25c6a674b3e81be98ad4532affe8507ec05380"
hex"20376c16b97ad98b8dfaa6f10d42a3c5e264c56018d32b0e8af528db157eb60d"
hex"234219fd49f941520883c13c1f01ff7b2f7f512a3046f91d33cdc3900ffb9de9"
hex"1d754d84438f79e6b701f7d665d59755a7bcd0b63f7c2da94b737606c16de1d3"
hex"287a08af195521f756271ec64bdc4ca8a7a95fae892c0fd2cf0c148d6c0cb653"
hex"0e16af35936b356d5974b385528f6d9a873568eda614ed0e54be4494c2acdefd"
hex"0fae7f745efa5884dc82f1595b5c10d931ed6da07b5dc4bd6f99dd5318c7c2a8"
hex"21f41494c6685503d748b45672c65d059260bb205113882458c86f6da7ea3813"
hex"1ec11e919c80981c8a905161c48caab360994e8f31cfe88536c5ad8b2c360039"
hex"14f32ba1f584bafc3aa283f79d5d65e97a6a280c7c51cec192ee9e48d593a2be"
hex"0cec3b3618ebb60152be2987b910940e79a421d666a71764f25ded99159de90f"
hex"075a80d650b5c6f8a0b3261ae5ec4c5a1b53762f30c559aaa6c501e207c2514f"
hex"026c5d81cf4e6cbade3622323c4ee3b4568333e79504044d2ad4d2ba01abefc5"
hex"286bacad6fb92895c85483e837d7c821d3f7bd612ddd932c16d618455ee62a45"
hex"11a11b68cb7aa85f42325a3d0fa45e0887719f05c9cd472183b1c7c78eabd0ef"
hex"0674f14710e453bc1f9255babc8d2aeb3b2e321c68e6871b54c285e71456be4d"
hex"11bf8be1878d5dee6820ec405b079360da81da7b79f29aa54096ae195ea1108d"
hex"2a02d0a645dcfcafb2235e7f9ed37df27c3f7cbd5ad11ee831fa17cb36881d3f"
hex"1e2338342dcdeec5d3ebd82d4b767ed93989d9147ac711dd07d8aebac0962c20"
hex"174c21361611783b0dc90d87a6128cd4d7e427cca10db1d713495d8281ce3dac"
hex"22654673d8af40026294acb3c0e51f0f367576d83a554bd9ad72de06a796095e"
hex"08f410159146e32feb7a585ad437c4a48ff2109d7f74f58e709b66c292e1c690"
hex"160928e9343db00c99255a53ea3948b547d0bb68332069c2d5ca632156a53ac8"
hex"1b8e0ca895ea976f5d42029c964ea52d622388e90f947cba08b3924b470d84a0"
hex"2f21e5bcc52e6d794afbf44a0dcb938554c7c94fbde66c1b7965ebb2d266d6be"
hex"106d51a9231260949c37fcb7c8296c246566259829e98ef52683900a433ad7d7"
hex"1f0691902d412d4afe6e49f546ad03d739f42a159af9530d717c01a3e9bc86b7"
hex"26c15552cf455e161693ea7f01601fed166f79653153fb5beec9e8393c1efde5"
hex"0223f9fa8192ae6be752d29b47e8b8a75e2172fbd4c89cfec400a9766e1430a8"
hex"100341a4e94a5cfffa3c6cfa1be6ac3bf6b0c4fe578f8c99cc4f67e4d7bf4886"
hex"1a9194b8c654ebf4f3cbb607c8bff2ddebaff87b8bdec06745ad4ed802728a6f"
hex"0a7e869e75859fe47e51b3b79ad155670af4e6780d3edd3c13812db0197854d3"
hex"0ef4a576b0bef4d037549aa24282378e13b438fc9bf49efcfd65cf3aa8935d28"
hex"199af24c0e98e72c37d87bfb9386003c2a0192ccf015be777c4305d5eaaf0e81"
hex"06e7f2d897f05617580ccc132040f3b83f3fe1a496354b33f39d27b15fb2a5fe"
hex"07968d5b67877cf32da7858c85479a891164a19b1ddc26fdb2772d294addf3b6"
hex"1b4dc215f06081e276803f1650d67324801c0a4f48d4b4fac9f6650d2fcd901c"
hex"0c5a5f0969147d312118768cd73a762e53d3984088be93e46d8433d129939427"
hex"1a948b5fcbf5918fad1f3c69d9d58c2df72cd9a15ff57a35c86c9e5082ee4090"
hex"0532f7499522ad56592a815a303b33b648fe170e0c2f47d831255298200cd775"
hex"22cce52f921a79b56993baaa1854b37ea74caf7e6f2d957048fe5e5d1e536ce2"
hex"1ca9ca03dcd6b6539118fc036663b6deae0bdb0df258f18e23613f4e80bd5bca"
hex"2f7a2d324bace30583592592d82bb970ed33f9753d03dcd3b54a44af04a0f1c0"
hex"0f6008b6f13bcf8f2663e7392e2538406a7cdf15ad387e2eda92bb1de03f74f0"
hex"06e30762808351c935656ddd7ac3499a2b497991d02f54c178277fce024ce89b"
hex"1a087e883f78b0e1ecbc92dbe9d82258e4c91baac53d71836902953f8e5a6961"
hex"0d35fd011b125ac12fd1d7c655fbb7b1ebc9eb47008676c750907f7768f6d644"
hex"183a077e1a0a2dba1ffcf7e2a490859a5f60d5d04b3599506249b6d534848ba2"
hex"24230c1864237bf6dc8d6b3e40bb277c02dab92e86aa515aaa62b1ad496b8290"
hex"075a995ae152c5f9737f6848a2d5ef93a8e7809981a06834ef8b684390456011"
hex"2dcfb2766574efd57331146186055ee967cdd14d5efac43389a29605d13d561c"
hex"05a4a1353e53e1b5622a2200ee1fb2e1a8e224a8ec5554bb670bb377505cb615"
hex"064cb205829acdaf1af3d45060ffa3433c02d3a7ae61b66ece50967b97e1f04a"
hex"1af278018cfd4d2edc11dd77454ed0cc4ef3ca1dba5b0ba96bb2bdc43f1e8ef0"
hex"23e7488f10d910e129d466443a7adb99fad7ac0b0bb37a51c9d0f1b7c527a98d"
hex"29594b068af04ce6fe6b248aeb06051d6f66a39d9f3d13cdde5b343f31ec16ea"
hex"1e63fabe17ec748ba86bf78cd84029d23ca6c543ee800179dad25964fae41cca"
hex"2acc46fb9f4ba2abecc49ddb33c0314c7a940bfa021c07d44a73614599995ea1"
hex"0d520400f15c87d18376ebfc03c8ed06b9ed713a654a0024cf310b64175d1064"
hex"188ef3fd8a2134f2d4237dd7657f410ba5172ae081a6ca117dc21c7ffe71d6bf"
hex"06a71b093737f1ebae5924f2d5f47b8b14526c4831c50f9e9c7c032dc011e511"
hex"175921f58fb9fd90e2a1d2cf951ad606104a1676c9d2e6fc8fee6ea105239035"
hex"236859cb45dff68ffa2524619936a9cb457d2c0defe59b5863607e439369f316"
hex"28e0e101f6b62767f587d7dd8e0a4d4e32fbed3fc65c940d8aa8509bd826e33f"
hex"0158d4f5cd5085c6e4ae2fd1330a52435eb0745d54c7c8a6ad5b7a3cf5333a7a"
hex"05dfca18855acba1a5409f714a77297952277658af5e7d5e3a05bacd0b8005d1"
hex"1edb9f2871655c1418f9c7b5851dd8b1713d1f9d7d78c9b915b2d3ecb62e7569"
hex"10d33c3349ddff796b66b2c800a9fdf51d44235d14d74def1b2c112bf88647d0"
hex"0e55341297ed43dfa1312685a260ec51b42ed6c24e46b79900549fd023441282"
hex"0a1654efc1b702b4ffbcd21a9e0e3323a40e4a136bfa0cf81cf01bd89d433c56"
hex"148f5bd214818a2b59ed67a8d79e54a048f357989e2046b3e7b587dc4893896b"
hex"24d21716ac3c7fa8d8945b7b04479a0b397b8fe46e3424c0db7e1d7d824e40de"
hex"2830e9e432e9bc3e8dc48c98c12ee9081273f5be246347769d0a34e2f0e7ec3f"
hex"012e850e98e970f096522ef6f4f537529f296f7f3ec9ade921780c45fca74e57"
hex"1eb45ad2eccb950133aec7d4da6d03c301cebe782ba71e3533d5a0879bd6d0c7"
hex"1ce082f6108befc4c6133865cdf1b35a587868b99c36f59811bd3771a75c3753"
hex"21d1d3327b86bcb2514eac6f11a77867856f5a2cb24ff4f72f65742854baa0a3"
hex"072a1c2e8d55ba7a49807bbf09ad71e000d67b09bba8ea2ec6009086342753a7"
hex"1c9b7142435f0c29a9ad5549dcb9ac289104f48d39d4e196025268dfa1b6a255"
hex"00e7f5e830053d6bd9dbd5a2546f2b38820b7ec18b55b638f189c2cb86598288"
hex"0ab8a2d0b81f7a40ac8a6a8bed4df0643df2a4dd4606194c8508595e116f39f3"
hex"166b4f313145815f8ab8a09e6fac91e3cfa404438c8c430dda4d121eef70a9bc"
hex"0937ff264a4c22904c66b8466165d9302052f5687326970486277a54f458717b"
hex"23d014ce251eb044d74105355f1ae0b5dcdf0ef73fece10777328b86b0bb4d07"
hex"276c1c219fdc62892dd095536db3525c18d0409121171197c99bdd8a95eb2f5a"
hex"235d6ab6cef9830493b2c71bacd3782d67eeffacf4aed5bc07c2524203344cd3"
hex"1ad0bb296be4e478c61149c736ad66168c2d0ba4410e05513c1af1ebe644b076"
hex"0360722094dd4a26a16d8f12264b25accafdc6a3f55736f0de1e55dbdb28d02a"
hex"088b276813522c901c6ac134a1ffa00cd61276e1221bbd7ff377d1dba5e1beb1"
hex"243cd531b8f9fcb0cd9e8d9418c6e9306b89d96e0136eeaa66ebdb248bfd08f4"
hex"02a12915178a6e7d4a612dbc3a878db9ce7153bdc9130d3df7308c13b2e97fb0"
hex"05819bfdd569b0009e9bd1f9a41c7eb23ec33d8cd37d5d05b705b4511dc09f0e"
hex"05d2260582a4a391c8180a17189b98a53b831ebced724333194f2f6809571401"
hex"185017332cad227b54dca48915a4a78875967f8ed352fd96d5446946a64b4297"
hex"08192db4386fcba811f000733a6f28b929be4f9aa1d2140ccc3f9616f82f34cc"
hex"1281dc4a2838c70842102a997a6bc26a737209d42266e815738ec3943516e150"
hex"279e9dd39bd768a08ad9ceca41993b8e8408d025affd64237b5985ed9a37d52a"
hex"11bee6efbee9ff1ffe2f060d79bd751d43bfdec4d5fa5e323582f8d735f44c7b"
hex"1bb75e2ad0bf3e1f255a9e983428b9baa96cfae8bf71d1aa4d3a786235e21065"
hex"28941f264db478bce46c697bc574a5dc0b956d033eb29194de103a9a70bccdeb"
hex"19d5cfb9c2ace7ec529ea27438d22668f09c2acbdc9c099bbd5554a6f3ae145a"
hex"29fbde88fcb5e46ca563fad42cc7e26ddbdc0e655f88057a8a8f6e51354f74db"
hex"1dd99423b0d860b8ee34e292b4616f7c870094c265f52cc450f98a575323872e"
hex"2400a80de9d38f539c9b0b9580ccb9ae2e382f3092a657ff50a83ea03a4ba7d6"
hex"20a5b9553d48bdf8ff66139e723e6a1655823b62add790b62e605d90044bec0e"
hex"196df524c0987fe4b832add37f546b835dd259e7c03de7226a43a6a062b4e61c"
hex"2ea4e4d02236497c570aeac4ea1896e1e3a19343f6e50eadb273cb5a7becdad2"
hex"0800ed797700c5e269e0c1edf4947c65348976d4a67e16ee547c6c870c36e3d7"
hex"09df4796e7cc0d89f1fc722c7d967d4c0baa823f93f9c4d6c7913edd185bc11c"
hex"23442bab611ff64c7eb49ab07f32f52008673d80ba54e04bbc5c61ca1f0c3836"
hex"2f5baea6ca93f7a41762a2b4f5b6c31c4e0d140e422fbe379f2686522dccb035"
hex"288e0e05b537a48d5470921b9d724c26fb8d2900dc7d6f0741ba2c1a35138c17"
hex"24584003a84247aeb78b30e2d8fb4cf7147785647ddeb68a7df6a79ff84fb008"
hex"219b35214df5048253b823fcaf329a45a2ae7f959af6539ae7753e3554d28996"
hex"21795fa4312815b80472036b9f35c1495378f172c7157a9440e62ee46692ace6"
hex"1052d93c57b9902620b22e1c29b9106ad076f25f69fed4106736de133d72ecb7"
hex"1948cc83425a81e7f7c6486e0f08b4b412724759ce41f950d65fa5283c31a4c2"
hex"26769518d0ab71ba583b0022557cddceec3566637a6c1c519999523b44d953ba"
hex"13a68997032013798fc580d466367a6a04502f500f7dcf4c2e6e03e777484908"
hex"2668cc07461b1088861db6bf4c03528227a20d2b473e088aff34daa78be83800"
hex"0bed18cab0f02716c9ee5e68f2434a241e6784ba03ca69df0edd97dd72038b6c"
hex"2e04d93cc4f54309390fe572d6affd4cbb1989ddcf410fb476e3a8681656efaf"
hex"18b0b7c0a137e1454dd3ca510d220987b5aaa51124e157fa372ec6099a03a714"
hex"0354150d34ffc1b4ea2bcc2d705f72e2bfac4619f6ba35de7a5c08d5d7ec34b7"
hex"12c1195df5fc75284ebe217430760ab4862de0255f75dbe24f4fe60f90c3419d"
hex"03630b0da0e292c1088354c075dd1e00694fc14db1878a5cfacf2b7b797742e5"
hex"16d451a52d64de482f4bf60beb30fa565a4e29904042fe36288002bb84325d5a"
hex"0664003075b0ef9bfd1573f70b84f7b75ce76563169be92df533d5aeb47ffbe7"
hex"0b41ef4deb720d4d2fe7dc11b4483b3d0b226ef5cfd8ba9a4e46bea1018fbb64"
hex"298c7227e27ecf7291ff64ebbab81169202697e8e76afbe9fe1504243b4077b3"
hex"0cddb62d67cbb120c38a93a9d10466381bcc71a202ee0a75f1bf952ac1c61a00"
hex"1f251e0231fb968a4b39bd089704ca99438b645cfc29920e0f8f4988f77e9597"
hex"0ec2e8e1aa9376bd31702a93e024f654ed26a324bf744d53271e510a1f7cc2ff"
hex"1155f64822affa2c0d2fcd555aa5dad8698731fca61bd3a3d072cf33c1a8d9f8"
hex"15699cea496017d4bf9fcf96e5a384e7c105d2ac074571e600afd0e9b4e7e8b2"
hex"1e85323381cf7d3ba3431e64e894ce4d693f0c463b6d104dd33dedd7f1b9f081"
hex"004b64f1d7c848aa7c28d6a815b7ec34ff2bb76d2d8c25f93265ad8b20b7140b"
hex"0dd34779b2145df8b131bfb71ffed5c835d2b696299ed813bb472be2f3a880ea"
hex"0e1abda56faf0df6daf6b166c95c5edc97bac1f73d539a4e419e36cae7ee1d92"
hex"11c1659cf668bedf75fe21edb2ff2b1fc695bbd538c1331845f24839897b6200"
hex"21bdf685c361d30014b4396b358599cefdc9d5f3b464d67a54c9cb2978925710"
hex"1b7153446f1040fd153236c214b0b502ccb8c202c54ddfa527132962133d3988"
hex"19a23ee53b40796801a094627b87364921ae981e57f9f478ddb3fe9e3050dbf3"
hex"0c3793885e6423402d09a54736d9a0fab9f8e5edf858b7be1710b5ee2a46c8ae"
hex"1dad8846162762182f95a6360199cd0ccad756cea2e4fbb6f17bf7bb643cc6ea"
hex"0185b530295447254ce398130e4f1bac6a4135c8b9be462422bb6ed88d7d8156"
hex"0cc09061f82989f499b935c855c6446ee4c02f2b5ec74205bb2681a3d39cae95"
hex"1e785e3c3ce8c5a93d9a16f466e1df548f855d70d18613fe8dd861f3e4f486c6"
hex"04715136d512b998cab28f4cada627caf8da082e1b11e2438ae4f8ed17b259ec"
hex"16b21b75881cfd9f0ae30c2ebb472bcfafd4c09ff390f3a381e2098d9b057cf1"
hex"1ce1a91c61b317ca6f871105d6034a1ae73832671555965c2deeb24c5da51ce2"
hex"1382891a3df8d5ba54ddcbd4a9061a4574b0a4813c7d5fd49797bcd8ebbda4b6"
hex"28b1699345f2327ed7e3a35dbcac11e9704a2d019568e273b2ddbbdda61b96f1"
hex"1875cf03eaefd3c4a503d2499a9524ba9c8e8b1906511a4a85800ee21ad424b3"
hex"2d1b12c661616bf91e9616cf0dd1823f5e33799035dd1bcb92bbb8bd7b9fb5cd"
hex"1764a79b21973a65541bb9bf58bae57a63de6e20a207369f85b0ece77b1da388"
hex"22852209e2034dac637154e40c26004c7d2f8d6b0f2f649fe920d916a0b9608b"
hex"19bad11fd19291c1d7aba146796c8bc076303184293b05257a2e95aa1b35be93"
hex"017ede6c3a4fadb0c3b384fc1bb3ba2515ede2ddf470bbc5279817dccba8486f"
hex"20dc05e84fe2b3674dbf6cfbc4ea1888a95c385a682b198665ea24fe875f9182"
hex"0c6eb30738c6c686153cef7a45b97d5da153ed62a67f725af666c8f545414326"
hex"1b2e0303ea261450c0505cdcf6d8c5a1fe7c840287ff532d632de4cd4b899b07"
hex"25d247a3eaf394fba18917bc67089efdf773445090ab333538b9db6dd2aa34bc"
hex"0189a235ce7315920cc9633d5dc1c072cad0ebe0e95a07a0a7f6152bb14345c5"
hex"118ec9dfcdb51980db3cdbc0b4917ecc57a03dd0c8586ed23145fb8af86e64f9"
hex"2af16757fe4fb59efbf68b60493d51df19d06df73ff34828b9b0805b3a12512c"
hex"0649e85e611b0ea226cd5195e88f479ca348748e3aceb994208fdeca397d1c93"
hex"0d13a131ca0eb5a309eed385c046002c368bc570ea227bb02cc92be5e30820fd"
hex"2444558ba0ba9ab3e990299dc09f450bae4c4c92829a42c6943c451cc858e346"
hex"24e06233837107b33fc5cb27ac7baf78d48735d71cabebf68bbe8437ec15e57a"
hex"1f5903dfda34ef89110f00cc07959025cf325ee02f81046cc48105d3e5930bfc"
hex"20093ac8cbfca0030d78cc010018beb1b3e689d52956baa0c54ceaf858488e22"
hex"2ee9cc8d4c5e47162bf7386e4325e3a513e6d4f4458f5e01fc343e340124c0fd"
hex"1e2f5897ab3f2279bc761e37a8c20cf48a6bb27fb6da5bf0a5f67fca6ad93e1a"
hex"0e9ae19d75c9f500b45f68de80244090eb66f42dab81886a78645cb1bfb27931"
hex"0f78e982ab46a572920bb2e18383e1427da1df92db1f3665498c719a7af869d2"
hex"22c0107166bb0aa5b0885983712566f8e0b4471e69d88ebdb7d0173345a2cee8"
hex"0d8d1c4837d9de3b2d429fe96aa4f29fce440e52141ae4571cb1f1d7735af86c"
hex"07240e3b2aa1472c3c81dbc49bfb3e866b43f778158a3fd6641a773da5241474"
hex"037cb0fc644b2a88c90ee66cc4ddb962336347ccaecd1f4fa8eb567c04544655"
hex"11badee113262abf691cc75f28c0236812d76537940e970f4488fbce2ccb46e7"
hex"0e0fec7749cda728fb17b5b1ff968bd3b6433dd6dd6cc619e8ab2eae099ffb48"
hex"28f906c82568287d2256b56129e8b83944f9ee180627afbc9d510fdb7b392458"
hex"129e691ecb7b6fe77c01d70bf2628fe69e5f6e962f1029ce626a0d1888624145"
hex"2f8d1c3dddbd8cb59cbec15b623aa1309d12221f7c62d956815c924114ec8677"
hex"27db4f836bee8aa950940cc1732aa52d0e741ae355a8c3621ad068c043f77cff"
hex"2005b28ce7c5532ebf6b7e51d10c344c9a9b00836e4fc37f7eb1176d640c1906"
hex"0aa65efff54d1d497ece96910f6661001fb199d24c3cf997ce1e401788a382ac"
hex"17dbdc878bd81276bd23b35fe31d93f4d7cb65b722e65d58fe039d126524bb4b"
hex"26dadd32b90572e617c96576afcb2fcd9605b1d898b2366fd9a7cd0c23769da9"
hex"2e46b7b8c48234c4466b0be922a9525a8896b2d6cc9651b2f6f291cf2bd72b85"
hex"04523ff71405a30800020b61ac9a1e6b61ca68f9859f6bf1106f2a0fb66d5da3"
hex"05a3e48cdcb56d89222f017078cf35af105ab2b2e2cdb7adc3d71de732d2f220"
hex"08d6aec49dcb622b4b6033438a7b990f6e08a2d41909392a890d6ab2970c4fcb"
hex"2de53850b4466695b93e50172ffcc6ff47c882aa9444bb09652ee9f5a4f43e82"
hex"19963fd677971a8f8f1fe5d09bd27ad0676c59c6b99cc2c46d8a886716e16a0a"
hex"2b0e85311370de1c8442d4216cb8ccff3d36a6765addb8a188408eff04a488a6"
hex"30620acc22c938e923607f077ab953afc8412ab4cd325b812e18b36db9ea03c2"
hex"1a2fd212df4bf20f8e47cfe5c5285a3706f8ab9863ea128054bafa1fe192afc2"
hex"28dad5eeef0e864876e671e4a960e451d5cb11204eb0f7dedb1d1bea322aeaad"
hex"09ce122c5b6d149f0192436aeccf959f73db3968cbe69f6c2dc955c1a8644eff"
hex"00b33c6fe57db259f1f62f8df50692e8d8c36a22c77234e0d81dea745254adbf"
hex"2b5b16738d4e4e8f30d8073c01e34d8a784bc6b41ec8e2afa5c8d2347b145ed4"
hex"0ce970cfdbc28f9bb3195dd2fb274f9895a29a996aadbdaa4cee11b546cfdfdb"
hex"0822416fe28cab89c713f9ab14d28a3d22a7033c1ada634ce7928681369e9b61"
hex"15d6ee8f939ad0609d6eb842084c6ca07a055e83ae2d1a0109498f8b7ee9bbf0"
hex"24cd8f5ffaa9da4f482d9efec43b3e1c77e8eab2f44007269b14614c932ebdd0"
hex"2093e404029042625197d41362d07884031eb192890e18ac0b1e4237afe74020"
hex"06c7641b87a6aff30a7828f5a61b6b79949489013a23ae8f138bb6458a727980"
hex"11945363118e8c1728e09565b5ba8e9c322b281d50c81d9ff94a18612ac41f7e"
hex"1e0557a57f3b98074694b3bc37edf005f0129ba8ab7aeef1346dc1b94cc283ef"
hex"2be1c91a0c0747ed6b472d5a6103ca79844f6fac466e756e51599951b0ad1c8b"
hex"0f4dca5aaa01292e52a8a19a994dfb8ae96163872353ec485ccf1a2c6bf2b0a3"
hex"16be623636b1118ec0511c5c0aa630833c542c80ca87898c8d8a0c9c6432f920"
hex"0dfe1f87f83f760e4779993ebb87b600763a78a1e0022f2a3c083730c09930e2"
hex"185bb62bd0f1e1ec17991ed4246cbcadc9d17af7f85d2583b555b293b85cb3ba"
hex"103959d3005c53566ecf636f2d99b94266ae10f20d7941d94ab52b1e66c99a2a"
hex"24903de01d4c24236f18e0a72f1485b8e8e0eba5385dd2ccf3da36f42f29f29c"
hex"0b5c24e7cd6e5d92ca2e92b79c3cd608a0cbfe8b2940aca50db477bbbf676188"
hex"191656e0acf10df4d56c25255747160742762fc2d37e507e563b9c2b2158231c"
hex"24fda5b8762d28c2cb390432cce54693def5c5d8cf3f1a820bff33763673116e"
hex"0bb80254eea5b1630deb61300db47c2e3e9d43c0ae79ac6d8d8e5dacb30b421c"
hex"0e88460520595dd83aefc1ea925bc7b76faabbd79339a6862c8b8ae500e61ad9"
hex"244cffc3946a184f713d5239638a2e1d795aeee5ee445c9f9aab6409e735b88f"
hex"021554cd4ee080447d929f96556906a5504df942919385bc5e64cedbf2ae394d"
hex"27ace9d675fc4a5fbaa1418f1420ae54e57c8343a69843ac97c5ebcc81782032"
hex"0e5d6c9eda47e171d3f5a2edb52448f00acda78580b066fc588b39aa09638a85"
hex"0a2a0dcb9dd824a85d72255623c47308a71ac9c4b4f6bda9d273b1c1f88b629c"
hex"2d80cf2b46f3ac5285aad169e96b067b01de824253f4156311196ba6e4bc2104"
hex"0cf1b3cc75b68e63af37eb275714561af525bfbb82497cd4730215975d8a3cd6"
hex"1df43394141f318ee9571c1ed93198d282288da8bcb5b33e3c6f1e9269a76304"
hex"1064a0d92da154a1b43895e1833b6bac67e096996e0db5bc1447c30bbdcb5bc3"
hex"0253f837b9e9f89777891e37357c8654e1a5d5ea0262afd58136f1c1c969d395"
hex"0173e90b1dc6b589a510c7364be31128cacd0baf495fbb9161024b880c18e97e"
hex"2a3395c5515973f8ebbdf18b8fb573eb46a4e8fc88c2f159cc6be94c7aa35e0d"
hex"1be4bfc35f47cd93bee0e1adc16a0957f824a9e24f31a32c372e97b6a2f9a71d"
hex"147f33857a0febcfe896dc770f9a2a86a7089b55a396afffe4bb21d5321e1d7a"
hex"1230faf580d4ac8a0a7d8f3fcf457f63ab27cc54c5820739bf6437bc43eaecbb"
hex"2cbf7af588268ced22cad9f5a9254d95c5f47127387655ee36dc94d70d139296"
hex"0825e78b37cc551183bcb25b98363522c0a801206000c6ded60985718b46ab24"
hex"00ad0b22c9addd5f71d90a7578913c0da692d7bb9230c78d6f6273114df69d73"
hex"210957b327089cd3495ba001efc730c8f84d824fdf9448c277d02379b694d0bd"
hex"1a4012ba18c18efb60b94d7fb0fb750ba948a5c73e55ffe464ebf7acbd04fb81"
hex"24a0432f67e42bc4409433b85588fa6d16dc93432fb633ec1170e1de3d258e7e"
hex"287d7479896cec61832a3e7e5e257209609c6af97c315bb08473de27be705f83"
hex"1301c5336b7f37607888212f40b73bd0aea535cc7148be0f9cddeef1f397b8dc"
hex"1c1bd11368695d776b6d4f51d8b9a3ff091dc23b438ad3a8e00f435768543c95"
hex"20ed4fde81fe5b8cde1b1b005cc5a470003b8a12d74d4178d03351cfd620c9a4"
hex"1861979a4209de561feab4faa20b540fafe14a2f47815d1d6f756882735645e3"
hex"0f50fe0714b48545aad0aa47edf4cf85b77edef8420cadbb2ab055537896841d"
hex"009bb5d21aeb5bf32e1a0a2c6d2f7a0044c7bae33fa95f6264135534b5aa1a17"
hex"10398fce470a822d6e5bf4a572fc5aa091e664335a8f0e5f4b82ba80dbd25d8d"
hex"050d8d517b496e2067860366e267a33cceafe24e53584565511927952e43f160"
hex"218634834c0bd7a41a100548c68c54d6d47e30ba6841925ce0afeb3aea683856"
hex"00156ed62144c5a67173008b02d76e28126ca00a2819c0bb3eb4cc92c196f893"
hex"2b0efd5fccfbbd5f77198a0d800e01d63679db7ee5dc4213c4a1e82b47ce07ca"
hex"040540c023f617d52c1ccbd2d9e825d8f60a2f6cc6c7e0230f8c259659cdc082"
hex"11739844b03202e6faab271c897dfa7bef337a5b0672ab13ebe547f572a089fe"
hex"304aeed0c9d0c871f87128dbbb634322c5449164a13028e7f8e46ea7eaf5861a"
hex"1eb1cdadf95c5ae983ef642bfb86f103558afc4571483cb7585a00715580fdd8"
hex"06c4f741b7246e5655a575e85661422ec7b71e79535db2ab86ca6105124a2f14"
hex"28d9f82f7cf626d8bf29d5a074bf2e8a64a11e8b415465ec3366cc0e4af15eb0"
hex"0af3afb40024843ffe9126a492594cff90682e2c4afa7237bc901e70a081e68a"
hex"01e0d9ee7d4bfb5b07b2d9102409de25c281bbbdd10f2bbdb04adf4a2e467df3"
hex"108a7206cd0ab67ebc298481ce73bbff082a5434b01e26d8ec53ea69f7dddf6b"
hex"08619279b0aa0c5e4f7e0ba18b37dfcb3ab7762debd778e1675539e2023fe000"
hex"26df8a6518857f2cf15a8dd27eb05fd4854710b80ae479cc3dbb4963dbb61401"
hex"29ebe07739ab8b1f23d828751d533ea3630788c03835c7ade9de2fc725639be6"
hex"27448ecbcaa51b958aee7c6415c041b815de8940e427fe2152c77639f3c5e7db"
hex"0699e2a03a056f4a0323541d174c4d8c1d71a7b04c664aeea06aaf2f97849623"
hex"1f2c0d82e6d3dbd8f29d81dcba037666a0567564fed3a90a34f4c2a0864fe6a1"
hex"18678798666318a2f6c93fc93d788c258f01c5aa450b65f4927ba6308f7a99ab"
hex"0fae315f1aa96516b51b9a35b0bf04a303290f7a4b0f107434e88c9b897d8ef3"
hex"2dbea8b90191f27ec6c6a71c3b576ccc10b6945a2d651b526b36c86929d7dab3"
hex"195b1cd7777a95a1dccfab7ad95d9815d143fc6d86f974cd07417038811e143f"
hex"157f37337b54b492a344d0bdd2d2dfd3f27a74d529898ae3243bd532983b58d2"
hex"2337c69e87af024d6cb0d8f29c96ee48114d2e7b2c1535ad6b00e178977380bb"
hex"17569028d04252e77d46764676068c2e1d43bee814688c6881424210bee531ef"
hex"156682b6b037656dd8a82fd83ca1924074f752a207b2585ae4c9ea6f4c78c75d"
hex"1ed96542fc65f19260e0a755919c2e24659105c4c9df00ded15f93f442f6887c"
hex"12fadbd7a3c4fe425a3f30f0ddb2f375e471a373f27e43c8a494d9678e8e6093"
hex"1292950805f2f6b9f28b3182436c2a975dd365a59195dc4df585e87395c7c3a4"
hex"236a0085c40b7af8c4448e830057b33fe8df95a33647c37c55b225bd5f8b1c59"
hex"1db855703240e2f49d63e43c62f8c30b2a39b67bea6e9a9481146c046af276d6"
hex"11b6ed9c39e7cc8f66dc7f9b386ba00528af573aea6d008433d39881470fb564"
hex"29fde8616fbc9e483e1222d447832cb7bc58170c7ec86e8f4de9070e07eacaf6"
hex"08aaaf73c42c827990cd0c64687ae8cfa0b373da849a767ef3b63ca08327663a"
hex"0c85a554dd2ecef748e891cbd90386b5737d945603b56c887986f9a306d7de4b"
hex"18564645c2a77acd8cde744455ead6f28819282b59f662f7da89dec13b7623df"
hex"1b44633048278c6435e1449517b0235bc9f4c2cf39aaf34908726c3dd3a07a1b"
hex"29aa41f4a0e91cec6a4481c3280a94398f6ff1b0b07b39ab0e6668dde4383082"
hex"09a6e0f5ddbfbb30481e978e215f67468f31eaf930dca350f0fc53bee83f988b"
hex"04310eb11496a8955d0a91b51aead8dcd1703cdc4b0e7f2f4674ae3e588b595b"
hex"2a10a00f88b3abcfdb5d1c8dc9f8727d16373ae7fd05b239f7e5bc22909682d9"
hex"0901653987feda97752895523e956cffbcaa8d3f088d280cb19cf4d71f010a67"
hex"1d8b1d6227e7d72dbea884042ee1324bd31a5fbb7ed49b79f04e834245a552b5"
hex"157fdd0e905e98e890291c69bdcdf6307771876bb8288809b44e63bdc934710e"
hex"039909b2ef090b39137e7420aa7ef195656037f3482b4fc10e554341d68ec93d"
hex"2294fcb6a8d69542b31f9942a59c4f4503e188912dd1cff39640cc2217e1cc87"
hex"1865202fa3c02e817f2fcf395c446a3eecac5d97950a44ffe1e8d299e064e551"
hex"2aab2c1581a7dde08e01d9efd6c7fdc561b8c7e6fa75020b9534f2d3b35afc0b"
hex"0e550b117eb8b4be6223be3b32b3367819c099e5cee581ef44a2cc483073514b"
hex"0c317541eccfeb5a470e62a4a7183b1b22839e1a1c23bf58b6ee43d1fe87fa10"
hex"0c1bba8cab5dc7f68592841c2f9cee4e068d6791e55f4dd54edf7ecf336cef35"
hex"10f331f64e0bfe4a9226e772e395f992634eeb6219cc239dd5d8e03cbe1f4581"
hex"0bd16714d1d83b871586d6c721608db6150796aa7d942a7d6b7f37e1fe54d591"
hex"0ff184c75453103ce3e832ab21e3f16110827890bdeaef035641417fcb9b2c3c"
hex"142549f5302f25b6f4fd1abb1b586555dec7abb108c3d988222356f8845157a9"
hex"1a934f239cf4d919aa5a54e5706f63ccaedaa2a523aa75b6cb425fccd9b30276"
hex"0f63efea5bb28d9047c8ef3d06ef698f6eb8d69cc2968256b56ba2c6b1aa3250"
hex"07ccc054bd8707ae6a7e1136a7d734ca437bc91640e819bdb1161db6285b8482"
hex"09f695c935d12262fc81ea65c312cab7c604cebf8a7a8e32199912d3fc172f2d"
hex"0c39e4c9610d79d226d090265c7f961ce63aeab2e824e029ce1b89601913496a"
hex"0dc3486866c4ae74c9f7227bb2bc821fe2ea1a265a34e961cfe8e0548f0b2ff6"
hex"29b111d35a7ba7b41a2e65e5412dcceb796b31d0d87b9f1a4d24b028f2377d52"
hex"01ebd6d03eef5c45e78c52247c3282fcf64558e43ff15e1d39533389bd7a86f4"
hex"037518906b748ee732531e22b29338f4a4f42a0f216226011632c4fc7a592872"
hex"08482ad4d100cefeb5679cb8b4f6af5aa6b87f87d0a7815aebb30da0d927d3e6"
hex"13ba71984e13a4480217ff47b1055dbef0ed7333ff8403935f10785b4d212031"
hex"267080070a80b5f94ea5c4363d2d971036e8446f2c055ca49495145eca1ae9fe"
hex"2992670c4c90a20991d63058dd4a885b9ec25f2307e6dfb364be99f0ab596b56"
hex"0e91d00167f0fcdc484e4510cea659d39a58ea6d94188082c301d82be3a5beaa"
hex"06007fd0fb2de248dbc4fe010a14285eb1c67ab1035575cfe2c4a46e7169be02"
hex"24093f309708216779d4be610fbad6c37027359a6cd9af3253023c94bab25009"
hex"27dca5e53ccf2bcfabd9f056b2381845a855bf7947d600e6f85117b69e57ab64"
hex"124efae3d5bf327ab6ba6d4526a495aa613a1c141b4ccbe97dce4d2174af4975"
hex"1a32d049a2624f7c385673c88d7fea82a5c517b7fac655774c395cdce73099b6"
hex"0602b40c9255dbac3b084808ab31e76a1f050751bb6775dbada5d84691d27653"
hex"27ca9346b73ccb979a8d2890fd43bf51eedcd0a78af072f64ee41abb954bacfb"
hex"0b59bbaf1fcc4321f763a03b112189c055a31078afd0954b7d7ccf311615d3d0"
hex"1712fa34ac64c32e7ba17168f04876190ff32077be969a20cf83be9d04ecc5ba"
hex"2287f65a7cb3a473300d133636ba395a1cfe1b9cfbe68f106f114d46d453ac6e"
hex"058d32c610ee7b8e0025aa2f8fa532b3a6a45214fd7df4c35ad5112f545fbde3"
hex"14772040257c0366286283200970b7ee56d048cf3f6725fc8d9651a8234a6594"
hex"149de5e4a643c98e7261b75a27baeb89147605258f470c0291bf22880e6a9006"
hex"12c1e251dddced6445c3dcdcfcccc1c36736068f9e1f7bbc4063895df782b115"
hex"10427a865028d998dcea094cc2f8d0fa2efbd0040d0b118e4415dae71c92cfa3"
hex"1dced774d8572bfb42107f480682ff1c5ef95f657787a06997f53061d44cee6b"
hex"2033fe9a65b025cd7e27764e34562fbc6391cf8d31623f31b68f03d6a1d1404d"
hex"04b8c60cbb003fd65b2886da9263ee92021683e1af25189631d1725df8c16357"
hex"2d5f76b195591eca401fbd5d43e2992245ea9a4009a8ed600fcb0962ea5b845a"
hex"18cd73d9f8a31eab2560b9f00b08cc4517309f7100c34df4c3aeccbb3df8eb49"
hex"244478321b4748aef75677808a6a5d92a6964f298eb5e5337621398b0c1a4355"
hex"0700ca5f97215da057c3a4a16a260471ca887e12ab3a9fbaac6a61c67c38fb9b"
hex"1c8b2eec6c0535832e1ea214b890bcc72682c5bddb39f4ddf34500a5cb9a81aa"
hex"2d3d9f09f802a02b7324b79e9681debd2833f6238b22ae6622ba1a64e744f790"
hex"29e3aef42dc679892840c82352fa28d9140106d6c2ba6ada66fae52bff965eb4"
hex"0eb54e3e94c92cd24f6ec52eab577e80d8c8e9f2d39d6b8d69503967d9809fd2"
hex"1036bd833a94dd6a85559c519bb7a2769b6486b00d34996da228c08994f285b2"
hex"2f7362c30b976680185fcb2d6c1a9fc47ce47e77d3af5b773534e2ce7c2063dc"
hex"0f148ba271ab4c9b17837d44c14d231fe85b7644462249299a68b506bff87f4d"
hex"23eee74e2f9b8ee256ebaa6e03b545afa196f22ef7e96d7255f5e79bbb786c1c"
hex"165a455c205655a47926176b91f2d2c02ac5c00ad29b467bfdbd51b0768b3529"
hex"0d4bbf22a70348d22efdd5235eb6e682385197b4e17330c46c44ca6d5dfc6791"
hex"2841ddb730006e521446f952117b78effc601d10372438c4ba4f6e2608e9a510"
hex"21960d7a065af49c4c06053d32596d990c1a43cac1658dad807ae48de098e417"
hex"2a749e9fc0fea8a55e57cdb05166ad9692c00bf103ac30881c6ea8c6b86c244a"
hex"0792663fbe195bacf4bffe700777c5fb07db9bcf94404ce90d0ed74a50febf9e"
hex"2b4d7bb4c6dae168809b1e8687e2e668d2680f40733b7d6877b27eaaa2021daa"
hex"212f5c9650237c6013810fbf50f8c160395a487a5cd535ddcc85437383d7fd40"
hex"1e42318881baf153d5c6a0f3ae7c933daff9cd10c89c0f7d9c1253e65995e7af"
hex"082ba05d83761cb163b4ca9d55e5dbb43c74bf3f456988438da2b3e62a90097a"
hex"188bb1d3cfb110267f28a328777328ee715c575923e5517216a551b7e4bca464"
hex"26c9def697692dbd245316df1b3d3ebc23d2e7f26282bb8c3c77383b633d1fee"
hex"09e269116a30414bd9701c5e0878caadf29773b5e4c010a7f519d6c8ed4ab64a"
hex"0b0dd617d9c5b993d32b538129fa4404c7371453aec2448ad60caedef2521774"
hex"2955e9b0087cc084f3750b6474cf9ccc1b91b93088093fb9b65512bb41c7fe13"
hex"25742cb05d49c540c0db2fe8cecba3202fa75c3652f8a0632c901284718de2f0"
hex"197e4469bc4e63f957318e61dfc0b47f3612c833faa62fbbc758bea7747a919c"
hex"10434862eebeac7e95316632cb2a81e786f3148d551e82d4b5f3952dac0e84a8"
hex"1a35b2d833ae99e441f064acd0efe3ec75d0180f0dc898edb2ec4e6104c43d91"
hex"21095529dcc976329670baf3bc91051208b4d62984741144c2795189811c35d4"
hex"1cb3ed4bbd682aa625880beac8855c5fea04d41e00eab4f0d06318c229f650e1"
hex"0fdb194388dbc4bbbe4e95fd302d9cf15deba158f7c686da98f0c51b56a9c3bf"
hex"2355c510225e1b58ab2af9314c08bd8adff1ada7c9a457c0c1deb47b814f2c2f"
hex"2c04d7711fd02ba586d4a50ad99a1723e5bf2916b4b5ecba863947a98fbbbb30"
hex"0bbfceff43f6717beb8ca8fcefb59c672661fb46da69df22870a4c52fa4cd0f2"
hex"2bcca13d376d46c173fc2901c265dc09ad688e67b9726845e03944ee966ec01b"
hex"285bd066f7c5357304cec840041d33e776badbda4e0007a505004e070b9520ed"
hex"0794a82f878b218f741d0cb293956b5273b429c885d893d1113d73aa26c1d423"
hex"271b72ec18a3db9d3d0e838edd70c2ce3869f8dfa7a2990839b8dd9e1172e87b"
hex"0a636a0eaaf2172cf943d025179ff1617471d89f89258b34a3bbca00641a9cd8"
hex"1a528d6c2a802448da3ad3d59f777313c16a671482e39b8cb7da9ac35c1ff2d8"
hex"18c053d772d3b5a8a648244ccc209c808ebe141ba2f9d5650d0da14819aadde1"
hex"1048336a6121c302669d43eec43639872901bf281af7a1688aa3d3928ebdd907"
hex"12c4211198d7728995d57f5bcc090cf7beca8045d513deb1b175ebb36796f0e4"
hex"1834db39abc7b5ecd1a514dcb9228530e81361aea5811ca208a650daf968e6d8"
hex"10ec1c14ddd45f0d5cc72b4bb6c9b567381cd3f8ff34d9591c48f845ea50846b"
hex"056e828c137df3632d6225d8c3c7df355ea62f2e0d113a7e36852b6764afb9f1"
hex"1759ab5b4dc7063a18dd2b491a4a3d073bfdf8f4d33df3f339a83e3ba2953d7f"
hex"09876c8f4e48e48b158ea3f41eb7f19716f44512bf7cdaaeb3915798ce22707b"
hex"1a45579944f3cb644003ac2430ac63799964bce8f0125b487e5e84f986f46a83"
hex"14921030ad6e51af6e9a654d191b8562e8acab6542844de111650de2ce37659f"
hex"29baa8a03a66a40d48856ec10f47f554e884258e4eff26ce0f15c6b5171f9581"
hex"2f14a2b03d6b68f4bf5be1acb77702105951d5f13a423c1b21960b0c129fa99d"
hex"1a8dc9e0aba8f76e0f8bf6db5523758d5ec321d0857a2df1134b5dae2faccf3b"
hex"2373925e13c17f70c80783a3664e984c082f251bbe3c4698dff5daf3c70e5fdf"
hex"14c66f792e18c3133a0ec195583065986f5d8f297f5750ed78aee7b7fb6efaa1"
hex"1546abb4feb014cf7206953bcb52e5f16ac8d232723683674bc02854efa9c811"
hex"2dd9d7b31522a6b7fb653afd18e987a926fbd5377b5b0e415cf2614bdf0c2635"
hex"0102b6d8a26892985e76fd744ab01d06b524f57d634fc0b69a5d91355398d6ac"
hex"1ec5b7588982ece0b103edde74a6f327e6ccf694bc534195fe0effc7483f13a1"
hex"2b278acb099ad84fbc96b27d36269ba06a660e2bc9093059a2acb1998cf3f1fe"
hex"129253e64f00669a4cf7480180edd5c242544581499b9a233f0ce088acf1e4db"
hex"14f35ce5d343461157dbe0adb07355d95d2cd5aa6dba222b6a702af1e325d2bc"
hex"2d106ec5d71809dff7aec68762661bdfd5dbfe456cba5a7c150c73da2510f752"
hex"16ed7e6f631af32c7e9c7884b0ab0cf71a834ddc4c825748eb5d35451d809240"
hex"2dd68235d74c633a111bd167dec9a6371b137ae89530106a928c87743b38be3d"
hex"0076cc22cae0c2544d7e6d49cb00182253dab5dfcf6cbdb378f56b0714b9d4bf"
hex"2af75f56bee1cdbf00f1a0af44ee6ca3d7f8b3b42d38f87bf1da869240dc6477"
hex"092f4b09a0af31220825e29d275eeb08977e8d3a6a934cc16a6d562b2eca001a"
hex"04cb8d5ffe9fe85b21a785e261721288e9b5b75b400545a31d0d53270608b104"
hex"08287f21c644121d27ec9aa9f50ccbce17e7ebe37a9858da78ca1d207bd9d637"
hex"08d64375d1c8b872172ed0e50612b60c4b049e807f23d6fa8f4e61e06d52047a"
hex"034d11c3fb63ed48fc75af072a1084b3d0982b796c9dbb70c295e4c938688dd6"
hex"03457e18852f8480e869f8aa0665890d85a78c5458b77f682cbde6b7954b55d8"
hex"2cdc590f35d097cd61fc65b0dbaac9cd05916c807ec0e318de09c55d6facb637"
hex"0f2b077d67767da3df753109cb25329348253b3bb8a474b8f2383d269e7af7d3"
hex"1188362ee1c47b51ae57ee87cdc133d212b205f43ad871011e82684b3251a168"
hex"17b80922192c7ef6e95042838827e749bc017d1a96c6e69f4d945f6a40c80678"
hex"09380df1270bf5638a0dd4f2c7b7af4a5798b4280a4c98abd97c99272b34488d"
hex"055c100b6e332bb5d2bf6ba8f3f5945bd877926df3eaab055c5d42be090db0bf"
hex"02cc36716e8608d8ddd908e019707e77d50ecaae8f83a61fac66303fe0d98038"
hex"1913d591367d4749326ea822b20c1f015974fcd5ec6d659aedeac7b56f6fb789"
hex"1706e619141f6b4a93840023bb2342e759da6438e07ed974a5f1e3d506144c96"
hex"0bbe067b718cb861fe927716cba85cfc466eed0e9d2c1067bc7f9e356bc5d23c"
hex"1094541933220c2bef5ec7afe91782ec245208d58f93a08ec25eb59710a73623"
hex"03daf04d7a256119a10ba5f6653564dff54f8eb78577360ac477abab5ce87bf7"
hex"0cce5000e4686fab8ca621f1c65dda94eb8b5892b1aff79a9a5eb0a2e65efd53"
hex"14e0969768884cab782cafd4b81555a818559c4835fb6821ec46fd08ea418ac6"
hex"1ff343732becbc72450b2faedef7112b951edf2ee03bebe4b71365755e6d5518"
hex"10e06fbbc2176bff93433750bcbfec05aea120f193a1e4c5bf5993e098916f96";
function getPts(uint256 merkleTreeDepth) internal pure returns (uint256[SET_SIZE] memory pts) {
bytes memory ptBytes = VK_POINT_BYTES;
uint256 byteOffset = 32 + (merkleTreeDepth - 1) * SET_SIZE * 32;
for (uint256 idx = 0; idx < SET_SIZE; ++idx) {
// solhint-disable-next-line no-inline-assembly
assembly {
let val := mload(add(ptBytes, add(byteOffset, mul(idx, 32))))
let storedAt := add(pts, mul(idx, 32))
mstore(storedAt, val)
}
}
}
function checkInvariant(uint8 maxDepth) internal pure {
uint256 expected = maxDepth * SET_SIZE * 32;
if (VK_POINT_BYTES.length != expected) {
revert Semaphore__VKPtBytesMaxDepthInvariantViolated(VK_POINT_BYTES.length, expected);
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/contracts",
"version": "4.1.0",
"version": "4.5.0",
"description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
"license": "MIT",
"files": [

View File

@@ -48,6 +48,22 @@ const hardhatConfig: HardhatUserConfig = {
apiURL: "https://api-sepolia-optimistic.etherscan.io/api",
browserURL: "https://sepolia-optimistic.etherscan.io"
}
},
{
network: "linea-sepolia",
chainId: 59141,
urls: {
apiURL: "https://api-sepolia.lineascan.build/api",
browserURL: "https://sepolia.lineascan.build"
}
},
{
network: "linea",
chainId: 59144,
urls: {
apiURL: "https://api.lineascan.build/api",
browserURL: "https://lineascan.build"
}
}
]
},

View File

@@ -3,8 +3,8 @@ import { task, types } from "hardhat/config"
import { deploy, saveDeployedContracts } from "../scripts/utils"
task("deploy", "Deploy a Semaphore contract")
.addOptionalParam<boolean>("verifier", "Verifier contract address", undefined, types.string)
.addOptionalParam<boolean>("poseidon", "Poseidon library address", undefined, types.string)
.addOptionalParam<string>("verifier", "Verifier contract address", undefined, types.string)
.addOptionalParam<string>("poseidon", "Poseidon library address", undefined, types.string)
.addOptionalParam<boolean>("logs", "Print the logs", true, types.boolean)
.setAction(
async (

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/core",
"version": "4.1.0",
"version": "4.5.0",
"description": "Core library for the essential Semaphore features.",
"type": "module",
"license": "MIT",
@@ -42,8 +42,8 @@
"access": "public"
},
"dependencies": {
"@semaphore-protocol/group": "4.1.0",
"@semaphore-protocol/identity": "4.1.0",
"@semaphore-protocol/proof": "4.1.0"
"@semaphore-protocol/group": "4.5.0",
"@semaphore-protocol/identity": "4.5.0",
"@semaphore-protocol/proof": "4.5.0"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/data",
"version": "4.1.0",
"version": "4.5.0",
"description": "A library for querying Semaphore smart contract.",
"type": "module",
"license": "MIT",
@@ -37,7 +37,7 @@
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/utils": "4.5.0",
"axios": "1.6.6",
"ethers": "6.11.0"
}

View File

@@ -12,5 +12,5 @@ export default function getURL(supportedNetwork: SupportedNetwork): string {
throw new TypeError(`Network '${supportedNetwork}' is not supported`)
}
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.0.0-beta.17`
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.0.0`
}

View File

@@ -7,6 +7,10 @@ export type EthersNetwork =
| "arbitrum-sepolia"
| "optimism"
| "optimism-sepolia"
| "base"
| "base-sepolia"
| "linea"
| "linea-sepolia"
export type GroupOptions = {
members?: boolean

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/group",
"version": "4.1.0",
"version": "4.5.0",
"description": "A library to create and manage Semaphore groups.",
"type": "module",
"license": "MIT",
@@ -30,16 +30,14 @@
"access": "public"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"poseidon-lite": "^0.2.0",
"rimraf": "^5.0.5",
"rollup": "^4.12.0",
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@zk-kit/lean-imt": "2.1.0",
"@zk-kit/utils": "1.0.0"
"@zk-kit/lean-imt": "2.2.1",
"@zk-kit/utils": "1.2.1",
"poseidon-lite": "0.3.0"
}
}

View File

@@ -1,5 +1,3 @@
import commonjs from "@rollup/plugin-commonjs"
import { nodeResolve } from "@rollup/plugin-node-resolve"
import typescript from "@rollup/plugin-typescript"
import * as fs from "fs"
import cleanup from "rollup-plugin-cleanup"
@@ -20,13 +18,11 @@ export default {
{ file: pkg.exports.require, format: "cjs", banner, exports: "auto" },
{ file: pkg.exports.default, format: "es", banner }
],
external: Object.keys(pkg.dependencies),
external: [...Object.keys(pkg.dependencies), "poseidon-lite/poseidon2"],
plugins: [
typescript({
tsconfig: "./build.tsconfig.json"
}),
commonjs(),
nodeResolve(),
cleanup({ comments: "jsdoc" })
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/hardhat",
"version": "4.1.0",
"version": "4.5.0",
"description": "A Hardhat plugin to deploy Semaphore contracts.",
"type": "module",
"license": "MIT",
@@ -41,7 +41,7 @@
},
"dependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.0",
"@semaphore-protocol/contracts": "4.1.0",
"@semaphore-protocol/contracts": "4.5.0",
"ethers": "^6.4.0",
"hardhat-dependency-compiler": "^1.1.3"
}

View File

@@ -129,3 +129,11 @@ const signature = identity.signMessage(message)
Identity.verifySignature(message, signature, identity.publicKey)
```
\# **Identity.generateCommitment**(publicKey: _Point_): _bigint_
```typescript
import { Identity } from "@semaphore-protocol/identity"
Identity.generateCommitment(identity.publicKey)
```

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/identity",
"version": "4.1.0",
"version": "4.5.0",
"description": "A library to create Semaphore identities.",
"type": "module",
"license": "MIT",
@@ -31,17 +31,15 @@
},
"devDependencies": {
"@rollup/plugin-alias": "^5.1.0",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"rimraf": "^5.0.5",
"rollup": "^4.12.0",
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@zk-kit/baby-jubjub": "1.0.1",
"@zk-kit/eddsa-poseidon": "1.0.2",
"@zk-kit/utils": "1.2.0",
"poseidon-lite": "0.2.0"
"@zk-kit/baby-jubjub": "1.0.3",
"@zk-kit/eddsa-poseidon": "1.0.4",
"@zk-kit/utils": "1.2.1",
"poseidon-lite": "0.3.0"
}
}

View File

@@ -1,5 +1,3 @@
import commonjs from "@rollup/plugin-commonjs"
import { nodeResolve } from "@rollup/plugin-node-resolve"
import typescript from "@rollup/plugin-typescript"
import * as fs from "fs"
import cleanup from "rollup-plugin-cleanup"
@@ -20,13 +18,16 @@ export default {
{ file: pkg.exports.require, format: "cjs", banner, exports: "auto" },
{ file: pkg.exports.default, format: "es", banner }
],
external: Object.keys(pkg.dependencies),
external: [
...Object.keys(pkg.dependencies),
"poseidon-lite/poseidon2",
"@zk-kit/utils/type-checks",
"@zk-kit/utils/conversions"
],
plugins: [
typescript({
tsconfig: "./build.tsconfig.json"
}),
commonjs(),
nodeResolve({ preferBuiltins: false }),
cleanup({ comments: "jsdoc" })
]
}

View File

@@ -1,10 +1,13 @@
import type { Point } from "@zk-kit/baby-jubjub"
import { EdDSAPoseidon, Signature, signMessage, verifySignature } from "@zk-kit/eddsa-poseidon"
import { EdDSAPoseidon, type Signature, signMessage, verifySignature } from "@zk-kit/eddsa-poseidon"
import type { BigNumberish } from "@zk-kit/utils"
import { base64ToBuffer, bufferToBase64, textToBase64 } from "@zk-kit/utils/conversions"
import { isString } from "@zk-kit/utils/type-checks"
import { poseidon2 } from "poseidon-lite/poseidon2"
export type { Point }
export type { Signature }
/**
* The Semaphore identity is essentially an {@link https://www.rfc-editor.org/rfc/rfc8032 | EdDSA}
* public/private key pair. The {@link https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/eddsa-poseidon | EdDSA implementation}
@@ -138,4 +141,20 @@ export class Identity {
static verifySignature(message: BigNumberish, signature: Signature, publicKey: Point): boolean {
return verifySignature(message, signature, publicKey)
}
/**
* Generates the commitment from the given public key.
* This static method is particularly useful after signature verification,
* as it allows retrieval of the corresponding commitment associated with the public key.
*
* @example
* const identity = new Identity()
* Identity.generateCommitment(identity.publicKey)
*
* @param publicKey The public key to generate the commitment.
* @returns The Semaphore identity commitment.
*/
static generateCommitment(publicKey: Point): bigint {
return poseidon2(publicKey)
}
}

View File

@@ -138,4 +138,14 @@ describe("Identity", () => {
expect(Identity.verifySignature("message", signature, identity.publicKey)).toBeTruthy()
})
})
describe("# generateCommitment", () => {
it("Should generate the identity commitment from the public key", () => {
const identity = new Identity(privateKeyText)
const commitment = Identity.generateCommitment(identity.publicKey)
expect(identity.commitment).toBe(commitment)
})
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/proof",
"version": "4.1.0",
"version": "4.5.0",
"description": "A library to generate and verify Semaphore proofs.",
"type": "module",
"license": "MIT",
@@ -42,19 +42,18 @@
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-typescript": "^11.1.6",
"@types/snarkjs": "^0",
"poseidon-lite": "^0.2.0",
"rimraf": "^5.0.5",
"rollup": "^4.12.0",
"rollup-plugin-cleanup": "^3.2.1"
},
"peerDependencies": {
"@semaphore-protocol/group": "4.1.0",
"@semaphore-protocol/identity": "4.1.0"
"@semaphore-protocol/group": "4.5.0",
"@semaphore-protocol/identity": "4.5.0"
},
"dependencies": {
"@semaphore-protocol/utils": "4.1.0",
"@semaphore-protocol/utils": "4.5.0",
"@zk-kit/artifacts": "1.8.0",
"@zk-kit/utils": "1.0.0",
"@zk-kit/utils": "1.2.1",
"ethers": "6.10.0",
"snarkjs": "0.7.4"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/utils",
"version": "4.1.0",
"version": "4.5.0",
"description": "A library to provide utility functions to the other Semaphore packages.",
"type": "module",
"license": "MIT",

View File

@@ -138,5 +138,85 @@
"startBlock": 126057798
}
]
},
{
"network": "base-sepolia",
"contracts": [
{
"name": "SemaphoreVerifier",
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
"startBlock": 16008294
},
{
"name": "PoseidonT3",
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
"startBlock": 16008294
},
{
"name": "Semaphore",
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
"startBlock": 16008294
}
]
},
{
"network": "linea-sepolia",
"contracts": [
{
"name": "SemaphoreVerifier",
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
"startBlock": 3928632
},
{
"name": "PoseidonT3",
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
"startBlock": 3928632
},
{
"name": "Semaphore",
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
"startBlock": 3928632
}
]
},
{
"network": "base",
"contracts": [
{
"name": "SemaphoreVerifier",
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
"startBlock": 20553357
},
{
"name": "PoseidonT3",
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
"startBlock": 20553357
},
{
"name": "Semaphore",
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
"startBlock": 20553357
}
]
},
{
"network": "linea",
"contracts": [
{
"name": "SemaphoreVerifier",
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
"startBlock": 10235849
},
{
"name": "PoseidonT3",
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
"startBlock": 10235849
},
{
"name": "Semaphore",
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
"startBlock": 10235849
}
]
}
]

View File

@@ -40,5 +40,29 @@ export default {
url: "https://polygon-rpc.com",
chainId: 137,
explorer: "https://polygonscan.com"
},
"base-sepolia": {
name: "Base Sepolia",
url: "https://sepolia.base.org",
chainId: 84532,
explorer: "https://sepolia.basescan.org"
},
base: {
name: "Base",
url: "https://mainnet.base.org",
chainId: 8453,
explorer: "https://basescan.org"
},
"linea-sepolia": {
name: "Linea Sepolia",
url: "https://rpc.sepolia.linea.build",
chainId: 59141,
explorer: "https://sepolia.lineascan.build"
},
linea: {
name: "Linea",
url: "https://rpc.linea.build",
chainId: 59144,
explorer: "https://lineascan.build"
}
}

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import { readdirSync, rmSync } from "fs"
const folderName = "apps"

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import { rmSync } from "fs"
const folderName = "packages"

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import { readdirSync, rmSync } from "fs"
const folderName = "packages"

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import compare from "semver/functions/compare"
import { execSync } from "child_process"
import contractsPkgJson from "@semaphore-protocol/contracts/package.json"

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import { readFileSync, readdirSync, writeFileSync } from "node:fs"
const folderName = "packages"

View File

@@ -1,4 +1,4 @@
#!node_modules/.bin/ts-node
#!/usr/bin/env ts-node
import { execSync } from "child_process"
async function main() {

271
yarn.lock
View File

@@ -4861,7 +4861,7 @@ __metadata:
languageName: node
linkType: hard
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15":
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14":
version: 1.4.15
resolution: "@jridgewell/sourcemap-codec@npm:1.4.15"
checksum: 10/89960ac087781b961ad918978975bcdf2051cd1741880469783c42de64239703eab9db5230d776d8e6a09d73bb5e4cb964e07d93ee6e2e7aea5a7d726e865c09
@@ -5389,8 +5389,8 @@ __metadata:
linkType: hard
"@nomicfoundation/hardhat-verify@npm:^2.0.8":
version: 2.0.8
resolution: "@nomicfoundation/hardhat-verify@npm:2.0.8"
version: 2.0.11
resolution: "@nomicfoundation/hardhat-verify@npm:2.0.11"
dependencies:
"@ethersproject/abi": "npm:^5.1.2"
"@ethersproject/address": "npm:^5.0.2"
@@ -5403,7 +5403,7 @@ __metadata:
undici: "npm:^5.14.0"
peerDependencies:
hardhat: ^2.0.4
checksum: 10/f49d6615a45d063e8d361ea2029c80c351d4377925de6c229095619384353d3fa9463751beceae0d6ceaf26f60a99797a19abd16ae22258fba37aee26ee5576e
checksum: 10/edad30efeb0ab7c26fd0c5fd3f1d161733d51276435f77d9c58edaa4307171be40e8c65a24a8fb11481e1032e4eb72ac99cd11c6eaa0bbfabb493455e387e2e9
languageName: node
linkType: hard
@@ -5948,25 +5948,6 @@ __metadata:
languageName: node
linkType: hard
"@rollup/plugin-commonjs@npm:^25.0.7":
version: 25.0.7
resolution: "@rollup/plugin-commonjs@npm:25.0.7"
dependencies:
"@rollup/pluginutils": "npm:^5.0.1"
commondir: "npm:^1.0.1"
estree-walker: "npm:^2.0.2"
glob: "npm:^8.0.3"
is-reference: "npm:1.2.1"
magic-string: "npm:^0.30.3"
peerDependencies:
rollup: ^2.68.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
checksum: 10/89b108e245d1af6e7878ac949bfcd44e48f7d0c1eda0cb0b7e89c231ae73de455ffe2ac65eb03a398da4e8c300ce404f997fe66f8dde3d4d4794ffd2c1241fc3
languageName: node
linkType: hard
"@rollup/plugin-json@npm:^6.1.0":
version: 6.1.0
resolution: "@rollup/plugin-json@npm:6.1.0"
@@ -5997,25 +5978,6 @@ __metadata:
languageName: node
linkType: hard
"@rollup/plugin-node-resolve@npm:^15.2.3":
version: 15.2.3
resolution: "@rollup/plugin-node-resolve@npm:15.2.3"
dependencies:
"@rollup/pluginutils": "npm:^5.0.1"
"@types/resolve": "npm:1.20.2"
deepmerge: "npm:^4.2.2"
is-builtin-module: "npm:^3.2.1"
is-module: "npm:^1.0.0"
resolve: "npm:^1.22.1"
peerDependencies:
rollup: ^2.78.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
checksum: 10/d36a6792fbe9d8673d3a7c7dc88920be669ac54fba02ac0093d3c00fc9463fce2e87da1906a2651016742709c3d202b367fb49a62acd0d98f18409343f27b8b4
languageName: node
linkType: hard
"@rollup/plugin-replace@npm:^2.4.1":
version: 2.4.2
resolution: "@rollup/plugin-replace@npm:2.4.2"
@@ -6060,7 +6022,7 @@ __metadata:
languageName: node
linkType: hard
"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.1.0":
"@rollup/pluginutils@npm:^5.1.0":
version: 5.1.0
resolution: "@rollup/pluginutils@npm:5.1.0"
dependencies:
@@ -6250,12 +6212,12 @@ __metadata:
dependencies:
"@semaphore-protocol/core": "workspace:^"
"@types/mocha": "npm:^10.0.6"
"@zk-kit/baby-jubjub": "npm:1.0.1"
"@zk-kit/baby-jubjub": "npm:1.0.3"
"@zk-kit/binary-merkle-root.circom": "npm:1.0.0"
circomkit: "npm:^0.0.19"
circomkit: "npm:0.0.19"
circomlib: "npm:2.0.5"
mocha: "npm:^10.2.0"
poseidon-lite: "npm:^0.2.0"
poseidon-lite: "npm:^0.3.0"
languageName: unknown
linkType: soft
@@ -6268,10 +6230,10 @@ __metadata:
"@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0"
"@nomicfoundation/hardhat-toolbox": "npm:^4.0.0"
"@nomicfoundation/hardhat-verify": "npm:^2.0.0"
"@semaphore-protocol/contracts": "npm:4.1.0"
"@semaphore-protocol/core": "npm:4.1.0"
"@semaphore-protocol/hardhat": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/contracts": "npm:4.5.0"
"@semaphore-protocol/core": "npm:4.5.0"
"@semaphore-protocol/hardhat": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@typechain/ethers-v6": "npm:^0.5.0"
"@typechain/hardhat": "npm:^9.0.0"
"@types/chai": "npm:^4.2.0"
@@ -6321,8 +6283,8 @@ __metadata:
resolution: "@semaphore-protocol/cli@workspace:packages/cli"
dependencies:
"@rollup/plugin-typescript": "npm:^11.1.6"
"@semaphore-protocol/data": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/data": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@types/figlet": "npm:^1.5.8"
"@types/inquirer": "npm:^9.0.7"
"@types/pacote": "npm:^11.1.8"
@@ -6346,7 +6308,7 @@ __metadata:
languageName: unknown
linkType: soft
"@semaphore-protocol/contracts@npm:4.1.0, @semaphore-protocol/contracts@workspace:packages/contracts/contracts":
"@semaphore-protocol/contracts@npm:4.5.0, @semaphore-protocol/contracts@workspace:packages/contracts/contracts":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/contracts@workspace:packages/contracts/contracts"
dependencies:
@@ -6354,23 +6316,23 @@ __metadata:
languageName: unknown
linkType: soft
"@semaphore-protocol/core@npm:4.1.0, @semaphore-protocol/core@workspace:^, @semaphore-protocol/core@workspace:packages/core":
"@semaphore-protocol/core@npm:4.5.0, @semaphore-protocol/core@workspace:^, @semaphore-protocol/core@workspace:packages/core":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/core@workspace:packages/core"
dependencies:
"@semaphore-protocol/group": "npm:4.1.0"
"@semaphore-protocol/identity": "npm:4.1.0"
"@semaphore-protocol/proof": "npm:4.1.0"
"@semaphore-protocol/group": "npm:4.5.0"
"@semaphore-protocol/identity": "npm:4.5.0"
"@semaphore-protocol/proof": "npm:4.5.0"
languageName: unknown
linkType: soft
"@semaphore-protocol/data@npm:4.1.0, @semaphore-protocol/data@workspace:packages/data":
"@semaphore-protocol/data@npm:4.5.0, @semaphore-protocol/data@workspace:packages/data":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/data@workspace:packages/data"
dependencies:
"@rollup/plugin-json": "npm:^6.1.0"
"@rollup/plugin-typescript": "npm:^11.1.6"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.5.0"
axios: "npm:1.6.6"
ethers: "npm:6.11.0"
rimraf: "npm:^5.0.5"
@@ -6379,29 +6341,27 @@ __metadata:
languageName: unknown
linkType: soft
"@semaphore-protocol/group@npm:4.1.0, @semaphore-protocol/group@workspace:packages/group":
"@semaphore-protocol/group@npm:4.5.0, @semaphore-protocol/group@workspace:packages/group":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/group@workspace:packages/group"
dependencies:
"@rollup/plugin-commonjs": "npm:^25.0.7"
"@rollup/plugin-node-resolve": "npm:^15.2.3"
"@rollup/plugin-typescript": "npm:^11.1.6"
"@zk-kit/lean-imt": "npm:2.1.0"
"@zk-kit/utils": "npm:1.0.0"
poseidon-lite: "npm:^0.2.0"
"@zk-kit/lean-imt": "npm:2.2.1"
"@zk-kit/utils": "npm:1.2.1"
poseidon-lite: "npm:0.3.0"
rimraf: "npm:^5.0.5"
rollup: "npm:^4.12.0"
rollup-plugin-cleanup: "npm:^3.2.1"
languageName: unknown
linkType: soft
"@semaphore-protocol/hardhat@npm:4.1.0, @semaphore-protocol/hardhat@workspace:packages/hardhat":
"@semaphore-protocol/hardhat@npm:4.5.0, @semaphore-protocol/hardhat@workspace:packages/hardhat":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/hardhat@workspace:packages/hardhat"
dependencies:
"@nomicfoundation/hardhat-ethers": "npm:^3.0.0"
"@rollup/plugin-typescript": "npm:^11.1.6"
"@semaphore-protocol/contracts": "npm:4.1.0"
"@semaphore-protocol/contracts": "npm:4.5.0"
ethers: "npm:^6.4.0"
hardhat: "npm:^2.19.4"
hardhat-dependency-compiler: "npm:^1.1.3"
@@ -6413,48 +6373,45 @@ __metadata:
languageName: unknown
linkType: soft
"@semaphore-protocol/identity@npm:4.1.0, @semaphore-protocol/identity@workspace:packages/identity":
"@semaphore-protocol/identity@npm:4.5.0, @semaphore-protocol/identity@workspace:packages/identity":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/identity@workspace:packages/identity"
dependencies:
"@rollup/plugin-alias": "npm:^5.1.0"
"@rollup/plugin-commonjs": "npm:^25.0.7"
"@rollup/plugin-node-resolve": "npm:^15.2.3"
"@rollup/plugin-typescript": "npm:^11.1.6"
"@zk-kit/baby-jubjub": "npm:1.0.1"
"@zk-kit/eddsa-poseidon": "npm:1.0.2"
"@zk-kit/utils": "npm:1.2.0"
poseidon-lite: "npm:0.2.0"
"@zk-kit/baby-jubjub": "npm:1.0.3"
"@zk-kit/eddsa-poseidon": "npm:1.0.4"
"@zk-kit/utils": "npm:1.2.1"
poseidon-lite: "npm:0.3.0"
rimraf: "npm:^5.0.5"
rollup: "npm:^4.12.0"
rollup-plugin-cleanup: "npm:^3.2.1"
languageName: unknown
linkType: soft
"@semaphore-protocol/proof@npm:4.1.0, @semaphore-protocol/proof@workspace:packages/proof":
"@semaphore-protocol/proof@npm:4.5.0, @semaphore-protocol/proof@workspace:packages/proof":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/proof@workspace:packages/proof"
dependencies:
"@rollup/plugin-alias": "npm:^5.1.0"
"@rollup/plugin-json": "npm:^6.1.0"
"@rollup/plugin-typescript": "npm:^11.1.6"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@types/snarkjs": "npm:^0"
"@zk-kit/artifacts": "npm:1.8.0"
"@zk-kit/utils": "npm:1.0.0"
"@zk-kit/utils": "npm:1.2.1"
ethers: "npm:6.10.0"
poseidon-lite: "npm:^0.2.0"
rimraf: "npm:^5.0.5"
rollup: "npm:^4.12.0"
rollup-plugin-cleanup: "npm:^3.2.1"
snarkjs: "npm:0.7.4"
peerDependencies:
"@semaphore-protocol/group": 4.1.0
"@semaphore-protocol/identity": 4.1.0
"@semaphore-protocol/group": 4.5.0
"@semaphore-protocol/identity": 4.5.0
languageName: unknown
linkType: soft
"@semaphore-protocol/utils@npm:4.1.0, @semaphore-protocol/utils@workspace:packages/utils":
"@semaphore-protocol/utils@npm:4.5.0, @semaphore-protocol/utils@workspace:packages/utils":
version: 0.0.0-use.local
resolution: "@semaphore-protocol/utils@workspace:packages/utils"
dependencies:
@@ -7840,13 +7797,6 @@ __metadata:
languageName: node
linkType: hard
"@types/resolve@npm:1.20.2":
version: 1.20.2
resolution: "@types/resolve@npm:1.20.2"
checksum: 10/1bff0d3875e7e1557b6c030c465beca9bf3b1173ebc6937cac547654b0af3bb3ff0f16470e9c4d7c5dc308ad9ac8627c38dbff24ef698b66673ff5bd4ead7f7e
languageName: node
linkType: hard
"@types/retry@npm:0.12.0":
version: 0.12.0
resolution: "@types/retry@npm:0.12.0"
@@ -8506,12 +8456,12 @@ __metadata:
languageName: node
linkType: hard
"@zk-kit/baby-jubjub@npm:1.0.1":
version: 1.0.1
resolution: "@zk-kit/baby-jubjub@npm:1.0.1"
"@zk-kit/baby-jubjub@npm:1.0.3":
version: 1.0.3
resolution: "@zk-kit/baby-jubjub@npm:1.0.3"
dependencies:
"@zk-kit/utils": "npm:1.0.0"
checksum: 10/d9b97b773351c0524cbac3e4cb5721762865198483ea91ffdc7cd05bc4a7c4f3d1ec0b639a04cdcad4e71c60eed82bb1e32060531e2e7b11df6c1172024e03d1
"@zk-kit/utils": "npm:1.2.1"
checksum: 10/ae64d27f43ed53df15eebfb3468dadc202a587201a711b8716f1b855ea3b83e01e7eb5769eaa5c030979099c353396a0b1bf12dfa9c7575adce402ca64989e12
languageName: node
linkType: hard
@@ -8524,14 +8474,15 @@ __metadata:
languageName: node
linkType: hard
"@zk-kit/eddsa-poseidon@npm:1.0.2":
version: 1.0.2
resolution: "@zk-kit/eddsa-poseidon@npm:1.0.2"
"@zk-kit/eddsa-poseidon@npm:1.0.4":
version: 1.0.4
resolution: "@zk-kit/eddsa-poseidon@npm:1.0.4"
dependencies:
"@zk-kit/baby-jubjub": "npm:1.0.1"
"@zk-kit/utils": "npm:1.0.0"
"@zk-kit/baby-jubjub": "npm:1.0.3"
"@zk-kit/utils": "npm:1.2.1"
buffer: "npm:6.0.3"
checksum: 10/4b4e984a96c5dbc95a8cf36ceb8b3712e37291c1473d01b0e22c15a33311e9cf88c86175d878dacda1852cc905cd2074aaa76defeaed33490be3964ca7a53372
poseidon-lite: "npm:0.3.0"
checksum: 10/f8c9603b8985813ad3ad09130306c529a754fa97f952a50ccf2762227c1e256cfce1c9f2b8bf5ed570d82a443a86ced56ce3f6fc30b57501c5e2a584be8f3b03
languageName: node
linkType: hard
@@ -8544,30 +8495,21 @@ __metadata:
languageName: node
linkType: hard
"@zk-kit/lean-imt@npm:2.1.0":
version: 2.1.0
resolution: "@zk-kit/lean-imt@npm:2.1.0"
"@zk-kit/lean-imt@npm:2.2.1":
version: 2.2.1
resolution: "@zk-kit/lean-imt@npm:2.2.1"
dependencies:
"@zk-kit/utils": "npm:1.2.0"
checksum: 10/897f88204c9ee548a2a977ef1efac8e4c0d2efdf284c88f759fdefd53b2c51a36b536130eb3241e68bd14e5039bcb8d6d788e7fca46fe442cfa3eceeb9c0eddf
"@zk-kit/utils": "npm:1.2.1"
checksum: 10/f57ba0ab15ff38609c352862b21023d370bd250c37c7ef15d4ee7724c8179a7fdd6647ac8a555e6cf523032d1c769fb9eae6de5364a97574224ff7de1a34f8a8
languageName: node
linkType: hard
"@zk-kit/utils@npm:1.0.0":
version: 1.0.0
resolution: "@zk-kit/utils@npm:1.0.0"
"@zk-kit/utils@npm:1.2.1":
version: 1.2.1
resolution: "@zk-kit/utils@npm:1.2.1"
dependencies:
buffer: "npm:^6.0.3"
checksum: 10/a471025ca4c69a825bebf2c68a0d83c55c345c8843f28eeb958f1e2aa549aaa982939c1d6d819dda337601163064f382e450d09103ba4d9a0525281a0a23696b
languageName: node
linkType: hard
"@zk-kit/utils@npm:1.2.0":
version: 1.2.0
resolution: "@zk-kit/utils@npm:1.2.0"
dependencies:
buffer: "npm:^6.0.3"
checksum: 10/4c0b37d64b28a6cc33c901a0c59325b1fe9c31e6519eaefe4aa6028ae9cb85e97f047976942875face030a1835d5c955ea546d7dc4fcf9d35df79192ee2502f3
checksum: 10/05cb209adadad753ae9ca9be7a1664fb4c3259a703f64e8b0af637e5fa4b2a9099c21b80a30df62cfe826b165941e1dfe0e95decde5a4eafd53328692cb0a4b8
languageName: node
linkType: hard
@@ -10034,7 +9976,7 @@ __metadata:
languageName: node
linkType: hard
"builtin-modules@npm:^3.1.0, builtin-modules@npm:^3.3.0":
"builtin-modules@npm:^3.1.0":
version: 3.3.0
resolution: "builtin-modules@npm:3.3.0"
checksum: 10/62e063ab40c0c1efccbfa9ffa31873e4f9d57408cb396a2649981a0ecbce56aabc93c28feaccbc5658c95aab2703ad1d11980e62ec2e5e72637404e1eb60f39e
@@ -10292,7 +10234,7 @@ __metadata:
languageName: node
linkType: hard
"chai@npm:^4.2.0, chai@npm:^4.3.6, chai@npm:^4.3.7":
"chai@npm:^4.2.0, chai@npm:^4.3.6":
version: 4.4.1
resolution: "chai@npm:4.4.1"
dependencies:
@@ -10307,6 +10249,21 @@ __metadata:
languageName: node
linkType: hard
"chai@npm:^4.3.7":
version: 4.5.0
resolution: "chai@npm:4.5.0"
dependencies:
assertion-error: "npm:^1.1.0"
check-error: "npm:^1.0.3"
deep-eql: "npm:^4.1.3"
get-func-name: "npm:^2.0.2"
loupe: "npm:^2.3.6"
pathval: "npm:^1.1.1"
type-detect: "npm:^4.1.0"
checksum: 10/cde341aee15b0a51559c7cfc20788dcfb4d586a498cfb93b937bb568fd45c777b73b1461274be6092b6bf868adb4e3a63f3fec13c89f7d8fb194f84c6fa42d5f
languageName: node
linkType: hard
"chalk@npm:3.0.0":
version: 3.0.0
resolution: "chalk@npm:3.0.0"
@@ -10650,7 +10607,7 @@ __metadata:
languageName: node
linkType: hard
"circomkit@npm:^0.0.19":
"circomkit@npm:0.0.19":
version: 0.0.19
resolution: "circomkit@npm:0.0.19"
dependencies:
@@ -16583,15 +16540,6 @@ __metadata:
languageName: node
linkType: hard
"is-builtin-module@npm:^3.2.1":
version: 3.2.1
resolution: "is-builtin-module@npm:3.2.1"
dependencies:
builtin-modules: "npm:^3.3.0"
checksum: 10/e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88
languageName: node
linkType: hard
"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7":
version: 1.2.7
resolution: "is-callable@npm:1.2.7"
@@ -16947,15 +16895,6 @@ __metadata:
languageName: node
linkType: hard
"is-reference@npm:1.2.1":
version: 1.2.1
resolution: "is-reference@npm:1.2.1"
dependencies:
"@types/estree": "npm:*"
checksum: 10/e7b48149f8abda2c10849ea51965904d6a714193d68942ad74e30522231045acf06cbfae5a4be2702fede5d232e61bf50b3183acdc056e6e3afe07fcf4f4b2bc
languageName: node
linkType: hard
"is-reference@npm:^3.0.0":
version: 3.0.2
resolution: "is-reference@npm:3.0.2"
@@ -18723,15 +18662,6 @@ __metadata:
languageName: node
linkType: hard
"magic-string@npm:^0.30.3":
version: 0.30.10
resolution: "magic-string@npm:0.30.10"
dependencies:
"@jridgewell/sourcemap-codec": "npm:^1.4.15"
checksum: 10/9f8bf6363a14c98a9d9f32ef833b194702a5c98fb931b05ac511b76f0b06fd30ed92beda6ca3261d2d52d21e39e891ef1136fbd032023f6cbb02d0b7d5767201
languageName: node
linkType: hard
"make-dir@npm:^1.0.0":
version: 1.3.0
resolution: "make-dir@npm:1.3.0"
@@ -20135,10 +20065,10 @@ __metadata:
"@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0"
"@nomicfoundation/hardhat-toolbox": "npm:^4.0.0"
"@nomicfoundation/hardhat-verify": "npm:^2.0.0"
"@semaphore-protocol/contracts": "npm:4.1.0"
"@semaphore-protocol/core": "npm:4.1.0"
"@semaphore-protocol/hardhat": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/contracts": "npm:4.5.0"
"@semaphore-protocol/core": "npm:4.5.0"
"@semaphore-protocol/hardhat": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@typechain/ethers-v6": "npm:^0.5.0"
"@typechain/hardhat": "npm:^9.0.0"
"@types/chai": "npm:^4.2.0"
@@ -20171,9 +20101,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "monorepo-ethers-web-app@workspace:packages/cli-template-monorepo-ethers/apps/web-app"
dependencies:
"@semaphore-protocol/core": "npm:4.1.0"
"@semaphore-protocol/data": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/core": "npm:4.5.0"
"@semaphore-protocol/data": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@types/node": "npm:^20"
"@types/react": "npm:^18"
"@types/react-dom": "npm:^18"
@@ -20198,10 +20128,10 @@ __metadata:
"@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0"
"@nomicfoundation/hardhat-toolbox": "npm:^4.0.0"
"@nomicfoundation/hardhat-verify": "npm:^2.0.0"
"@semaphore-protocol/contracts": "npm:4.1.0"
"@semaphore-protocol/core": "npm:4.1.0"
"@semaphore-protocol/hardhat": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/contracts": "npm:4.5.0"
"@semaphore-protocol/core": "npm:4.5.0"
"@semaphore-protocol/hardhat": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@typechain/ethers-v6": "npm:^0.5.0"
"@typechain/hardhat": "npm:^9.0.0"
"@types/chai": "npm:^4.2.0"
@@ -20234,9 +20164,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "monorepo-subgraph-web-app@workspace:packages/cli-template-monorepo-subgraph/apps/web-app"
dependencies:
"@semaphore-protocol/core": "npm:4.1.0"
"@semaphore-protocol/data": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/core": "npm:4.5.0"
"@semaphore-protocol/data": "npm:4.5.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@types/node": "npm:^20"
"@types/react": "npm:^18"
"@types/react-dom": "npm:^18"
@@ -21824,10 +21754,10 @@ __metadata:
languageName: node
linkType: hard
"poseidon-lite@npm:0.2.0, poseidon-lite@npm:^0.2.0":
version: 0.2.0
resolution: "poseidon-lite@npm:0.2.0"
checksum: 10/63c7668b480ee3d57aaca0eda7e56d563ab2bfcc40bbce0e4bccdc9deed4c0d68255749356e328b622ce8715b1f1ba689fe1a86ca78eb1056a51a18daa252ee1
"poseidon-lite@npm:0.3.0, poseidon-lite@npm:^0.3.0":
version: 0.3.0
resolution: "poseidon-lite@npm:0.3.0"
checksum: 10/1e7294f7fed91e1cdc3aee7bd0380461bfdba74ba34d100c2fc4e3d5434d09af0644f6c889b749b9511fd3867216a1aa6d575f070b716c6756b1f56c0067b71d
languageName: node
linkType: hard
@@ -24650,7 +24580,7 @@ __metadata:
"@docusaurus/preset-classic": "npm:3.1.1"
"@docusaurus/tsconfig": "npm:3.1.1"
"@mdx-js/react": "npm:^3.0.0"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/utils": "npm:4.5.0"
"@svgr/webpack": "npm:^5.5.0"
"@types/react": "npm:^18.2.29"
clsx: "npm:^1.2.1"
@@ -24717,7 +24647,7 @@ __metadata:
dependencies:
"@graphprotocol/graph-cli": "npm:0.78.0"
"@graphprotocol/graph-ts": "npm:0.35.1"
"@semaphore-protocol/utils": "npm:4.1.0"
"@semaphore-protocol/utils": "workspace:packages/utils"
"@types/mustache": "npm:^4.2.2"
matchstick-as: "npm:0.5.0"
mustache: "npm:^4.2.0"
@@ -26763,6 +26693,13 @@ __metadata:
languageName: node
linkType: hard
"type-detect@npm:^4.1.0":
version: 4.1.0
resolution: "type-detect@npm:4.1.0"
checksum: 10/e363bf0352427a79301f26a7795a27718624c49c576965076624eb5495d87515030b207217845f7018093adcbe169b2d119bb9b7f1a31a92bfbb1ab9639ca8dd
languageName: node
linkType: hard
"type-fest@npm:^0.16.0":
version: 0.16.0
resolution: "type-fest@npm:0.16.0"