mirror of
https://github.com/semaphore-protocol/semaphore.git
synced 2026-01-13 00:28:00 -05:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd04b0c5c7 | ||
|
|
b6a7a9883b | ||
|
|
fc1fe4d086 | ||
|
|
feb8c9c97d | ||
|
|
b56e9690a8 | ||
|
|
c973bab503 | ||
|
|
27aee4bf43 | ||
|
|
ea62310df6 | ||
|
|
6bc415f4d5 | ||
|
|
18f77ac0bb | ||
|
|
f3c4cf27e2 | ||
|
|
57132a38df | ||
|
|
6ef16976f7 | ||
|
|
2849ca1d24 | ||
|
|
d05d783852 | ||
|
|
993e46a427 | ||
|
|
f984c1e864 | ||
|
|
5c9d1737d3 | ||
|
|
1318b0e74b | ||
|
|
c0fcc94e82 | ||
|
|
e70ae1151b | ||
|
|
fd38539908 | ||
|
|
8bd45d8c46 | ||
|
|
534e69683a | ||
|
|
a0a3b9380b | ||
|
|
bc9f7df1da | ||
|
|
571ffdab0e | ||
|
|
773696f40c | ||
|
|
f679583498 | ||
|
|
05926d0ef7 | ||
|
|
eef277281d | ||
|
|
b96467f3d4 | ||
|
|
e530412f27 | ||
|
|
4df7693367 | ||
|
|
0ca80ca716 | ||
|
|
ed8141e873 | ||
|
|
0f4aca3ded | ||
|
|
6e2ef756bc | ||
|
|
c2dce437b4 | ||
|
|
8b91d75c6f | ||
|
|
abfcf9f006 |
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@@ -29,10 +29,12 @@
|
||||
|
||||
<!-- Please check if the PR fulfills these requirements. -->
|
||||
|
||||
- [ ] My code follows the style guidelines of this project
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] My changes generate no new warnings
|
||||
- [ ] I have run `yarn format` and `yarn lint` without getting any errors
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
|
||||
> [!IMPORTANT]
|
||||
> We do not accept pull requests for minor grammatical fixes (e.g., correcting typos, rewording sentences) or for fixing broken links, unless they significantly improve clarity or functionality. These contributions, while appreciated, are not a priority for merging. If you notice any of these issues, please create a [GitHub Issue](https://github.com/semaphore-protocol/semaphore/issues/new?template=BLANK_ISSUE) to report them so they can be properly tracked and addressed.
|
||||
|
||||
2
.github/workflows/production.yml
vendored
2
.github/workflows/production.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
run: yarn lint
|
||||
|
||||
test-subgraph:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04 # Context: https://github.com/graphprotocol/graph-tooling/issues/1546#issuecomment-2589680195
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
2
.github/workflows/pull-requests.yml
vendored
2
.github/workflows/pull-requests.yml
vendored
@@ -75,7 +75,7 @@ jobs:
|
||||
run: yarn run eslint ${{ steps.changed-files.outputs.to_lint_all_changed_files }} --ext .cjs,.js,.jsx,.ts,.tsx
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04 # Context: https://github.com/graphprotocol/graph-tooling/issues/1546#issuecomment-2589680195
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -22,7 +22,7 @@ Pull requests are great if you want to add a feature or fix a bug. Here's a quic
|
||||
|
||||
3. Add a test for your change. Only refactoring and documentation changes require no new tests.
|
||||
|
||||
4. Make sure to check out the [Style Guide](/CONTRIBUTING#style-guide) and ensure that your code complies with the rules.
|
||||
4. Make sure to check out the [Style Guide](/CONTRIBUTING.md#style-guide) and ensure that your code complies with the rules.
|
||||
|
||||
5. Make the test pass.
|
||||
|
||||
@@ -30,6 +30,9 @@ Pull requests are great if you want to add a feature or fix a bug. Here's a quic
|
||||
|
||||
7. Push to your fork and submit a pull request on our `main` branch. Please provide us with some explanation of why you made the changes you made. For new features make sure to explain a standard use case to us.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> We do not accept pull requests for minor grammatical fixes (e.g., correcting typos, rewording sentences) or for fixing broken links, unless they significantly improve clarity or functionality. These contributions, while appreciated, are not a priority for merging. If you notice any of these issues, please create a [GitHub Issue](https://github.com/semaphore-protocol/semaphore/issues/new?template=BLANK_ISSUE) to report them so they can be properly tracked and addressed.
|
||||
|
||||
## CI (Github Actions) Tests
|
||||
|
||||
We use GitHub Actions to test each PR before it is merged.
|
||||
|
||||
24
README.md
24
README.md
@@ -281,7 +281,7 @@ Install the dependencies:
|
||||
cd semaphore && yarn
|
||||
```
|
||||
|
||||
And build the repositiory:
|
||||
And build the repository:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
@@ -373,12 +373,28 @@ The output will be placed on the `docs` folder.
|
||||
|
||||
### Releases
|
||||
|
||||
Bump a new version with:
|
||||
Steps:
|
||||
|
||||
1. Bump a new version with:
|
||||
|
||||
```bash
|
||||
yarn version:bump <version>
|
||||
# e.g. yarn version:bump 2.0.0
|
||||
```
|
||||
|
||||
It will create a commit and a git tag that will need to be pushed on the main branch. A workflow will be triggered and will
|
||||
publish the Semaphore packages on [npm](https://www.npmjs.com/) and release a new version on Github with its changelogs automatically.
|
||||
This step creates a commit and a git tag.
|
||||
|
||||
2. Push the changes to main:
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. Push the new git tag:
|
||||
|
||||
```bash
|
||||
git push origin <version>
|
||||
# e.g. git push origin v2.0.0
|
||||
```
|
||||
|
||||
After pushing the new git tag, a workflow will be triggered to publish the Semaphore packages on [npm](https://www.npmjs.com/) and release a new version on GitHub with its changelogs automatically.
|
||||
|
||||
@@ -390,8 +390,5 @@
|
||||
},
|
||||
"footer.right.connect.link2": {
|
||||
"message": "X (Twitter)"
|
||||
},
|
||||
"footer.copyright": {
|
||||
"message": "Copyright © 2024 Ethereum Foundation"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,8 +390,5 @@
|
||||
},
|
||||
"footer.right.connect.link2": {
|
||||
"message": "X (Twitter)"
|
||||
},
|
||||
"footer.copyright": {
|
||||
"message": "Copyright © 2024 Ethereum Foundation"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ Para utilizar los contratos e interfaces Semaphore en su proyecto, instale el pa
|
||||
|
||||
Semaphore ofrece los siguientes contratos base:
|
||||
|
||||
- [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/base/SemaphoreVerifier.sol): contiene una función para verificar pruebas Semaphore;
|
||||
- [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/base/SemaphoreVerifier.sol): contiene una función para verificar pruebas Semaphore;
|
||||
- [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/base/SemaphoreGroups.sol): contiene las funciones para crear grupos y añadir/remover/actualizar miembros.
|
||||
|
||||
Los contratos base están relacionados de forma muy cercana al protocolo.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@docusaurus/core": "3.5.2",
|
||||
"@docusaurus/preset-classic": "3.5.2",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"clsx": "^1.2.1",
|
||||
"docusaurus-plugin-sass": "^0.2.5",
|
||||
|
||||
@@ -54,11 +54,7 @@ function Footer() {
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
<p>
|
||||
{translate({
|
||||
id: "footer.copyright"
|
||||
})}
|
||||
</p>
|
||||
<p>Copyright © {new Date().getFullYear()} Ethereum Foundation</p>
|
||||
|
||||
<Logo
|
||||
style={{ marginRight: -8 }}
|
||||
|
||||
@@ -14,7 +14,7 @@ The public [Semaphore identity](#identity) value used in [Semaphore groups](#gro
|
||||
|
||||
## Group
|
||||
|
||||
A group is a [Merkle tree](#merkle-tree) in which each leaf is an [identity commitment](#identity-commitment) for a user. Semaphore uses the [LeanIMT](https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html) implementation, which is an optimized binary incremental Merkle tree. The tree nodes are calculated using [Poseidon](https://www.poseidon-hash.info).
|
||||
A group is a [Merkle tree](#merkle-tree) in which each leaf is an [identity commitment](#identity-commitment) for a user. Semaphore uses the [LeanIMT](https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html) implementation, which is an optimized binary incremental Merkle tree. The tree nodes are calculated using [Poseidon](https://www.poseidon-hash.info).
|
||||
|
||||
## Merkle tree
|
||||
|
||||
|
||||
@@ -87,6 +87,11 @@ You may choose to delegate such functionality to existing wallets such as Metama
|
||||
3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask.
|
||||
:::
|
||||
|
||||
:::warning Privacy risk
|
||||
If a user signs the **same message** on multiple websites using MetaMask, all those websites will be able to **generate the same Semaphore identity**. This undermines anonymity and may allow third parties to **link identities across platforms** or even **gain control over a user's identity**.\
|
||||
To mitigate this, encourage users to sign **unique messages per application** or implement safeguards that detect and warn about reuse.
|
||||
:::
|
||||
|
||||
## Sign and verify messages
|
||||
|
||||
Semaphore V4 uses asymmetric cryptography and in particular EdDSA to generate the identity keys. It is therefore also possible to sign messages and verify their signatures.
|
||||
|
||||
@@ -11,6 +11,8 @@ slug: /
|
||||
Additionally, it provides a simple mechanism to prevent double-signaling.
|
||||
Use cases include private voting, whistleblowing, anonymous DAOs and mixers.
|
||||
|
||||
For in-depth technical details about Semaphore, refer to the [Semaphore V4 Specification](https://github.com/zkspecs/zkspecs/blob/main/specs/3/README.md).
|
||||
|
||||
## Features
|
||||
|
||||
With Semaphore, you can allow your users to do the following:
|
||||
@@ -33,7 +35,7 @@ Semaphore is designed to be a simple and generic _privacy layer_ for decentraliz
|
||||
|
||||
## About the code
|
||||
|
||||
The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/semaphore.circom).
|
||||
The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/src/semaphore.circom).
|
||||
In addition to circuits,
|
||||
Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts)
|
||||
and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/main#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort.
|
||||
|
||||
@@ -47,6 +47,7 @@ You can access any subgraph supported by Semaphore with the following URL: `http
|
||||
Supported networks:
|
||||
|
||||
- `sepolia`
|
||||
- `ethereum`
|
||||
- `optimism`
|
||||
- `optimism-sepolia`
|
||||
- `arbitrum`
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"codegen:sepolia": "yarn codegen sepolia",
|
||||
"build": "graph build",
|
||||
"build:sepolia": "yarn codegen:sepolia && graph build",
|
||||
"auth": "graph auth --studio",
|
||||
"deploy": "graph deploy --studio ${0}",
|
||||
"auth": "graph auth",
|
||||
"deploy": "graph deploy ${0}",
|
||||
"start-ipfs": "node scripts/start-ipfs.js",
|
||||
"create-local": "graph create --node http://localhost:8020/ semaphore",
|
||||
"remove-local": "graph remove --node http://localhost:8020/ semaphore",
|
||||
@@ -18,13 +18,13 @@
|
||||
"test": "graph test Semaphore -v 0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@graphprotocol/graph-cli": "0.78.0",
|
||||
"@graphprotocol/graph-ts": "0.35.1",
|
||||
"@graphprotocol/graph-cli": "0.95.0",
|
||||
"@graphprotocol/graph-ts": "0.37.0",
|
||||
"@semaphore-protocol/utils": "workspace:packages/utils"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mustache": "^4.2.2",
|
||||
"matchstick-as": "0.5.0",
|
||||
"@types/mustache": "^4.2.5",
|
||||
"matchstick-as": "0.6.0",
|
||||
"mustache": "^4.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ function mapNetwork(n) {
|
||||
return "arbitrum-one"
|
||||
}
|
||||
|
||||
if (n === "ethereum") {
|
||||
return "mainnet"
|
||||
}
|
||||
|
||||
return network
|
||||
}
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ export default function Home() {
|
||||
<VStack mb="32" spacing="32">
|
||||
<VStack w="full" maxW="1110px">
|
||||
<Heading fontSize={{ base: "30px", md: "44px" }} pb="90px">
|
||||
2024 Roadmap
|
||||
2024-2025 Roadmap
|
||||
</Heading>
|
||||
|
||||
<HStack display={{ base: "none", md: "flex" }} w="full" mt="60px">
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function Footer() {
|
||||
</Link>
|
||||
|
||||
<Text fontSize={{ base: "12px", md: "14px" }} color="text.500" pt="2">
|
||||
Copyright © 2024 Ethereum Foundation
|
||||
Copyright © {new Date().getFullYear()} Ethereum Foundation
|
||||
</Text>
|
||||
</VStack>
|
||||
</VStack>
|
||||
|
||||
@@ -40,5 +40,19 @@
|
||||
"date": "2024-01-01",
|
||||
"authors": ["Vivek Bhupatiraju"],
|
||||
"url": "https://vivs.wiki/Semaphore"
|
||||
},
|
||||
{
|
||||
"title": "Getting Started with Semaphore: Building Privacy-Preserving dApps on Ethereum",
|
||||
"minRead": 7,
|
||||
"date": "2024-12-09",
|
||||
"authors": ["glasswing"],
|
||||
"url": "https://mirror.xyz/0xBE98D44c29D179588b7E717Db8898529e5cD770F/5Xlv1jzwJKfKgP-m257kjivBlUIM_cwTzsmpf9F0Su8"
|
||||
},
|
||||
{
|
||||
"title": "Semaphore V4 Specification",
|
||||
"minRead": 10,
|
||||
"date": "2025-03-01",
|
||||
"authors": ["Semaphore Team"],
|
||||
"url": "https://github.com/zkspecs/zkspecs/blob/main/specs/3/README.md"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
[
|
||||
{
|
||||
"name": "DIF - Decentralized Identity Foundation",
|
||||
"date": "Oct 1 - Nov 4, 2024",
|
||||
"description": "Semaphore team will deliver a talk and sponsor prizes for the online hackathon.",
|
||||
"link": "https://identity.foundation/"
|
||||
"name": "ETHDam",
|
||||
"date": "May 9-11, 2025",
|
||||
"description": "Semaphore team will deliver an in-person talk.",
|
||||
"link": "https://www.ethdam.com/"
|
||||
},
|
||||
{
|
||||
"name": "Devcon",
|
||||
"date": "Nov 12-15, 2024",
|
||||
"name": "ZuBerlin",
|
||||
"date": "June 14-22, 2025",
|
||||
"description": "Semaphore team will deliver an in-person talk.",
|
||||
"link": "https://zuberlin.city/"
|
||||
},
|
||||
{
|
||||
"name": "Devconnect",
|
||||
"date": "Nov 17-22, 2025",
|
||||
"description": "Semaphore team will deliver an in-person talk and run workshops.",
|
||||
"link": "https://devcon.org/en/"
|
||||
},
|
||||
{
|
||||
"name": "ETHIndia",
|
||||
"date": "Dec 6-8, 2024",
|
||||
"description": "Semaphore team will deliver an in-person talk on Semaphore and Bandada.",
|
||||
"link": "https://ethindia.co"
|
||||
"link": "https://devconnect.org/"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -565,5 +565,26 @@
|
||||
"links": {
|
||||
"github": "https://github.com/evgongora/VeilEscrow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Obscurus",
|
||||
"categories": ["Voting", "Privacy"],
|
||||
"tagline": "An anonymity layer for Safe Wallet owners, built using Semaphore and Zodiac.",
|
||||
"pse": false,
|
||||
"icon": "",
|
||||
"links": {
|
||||
"github": "https://github.com/quartz-technology/obscurus"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Semaphore Modular Smart Account Modules",
|
||||
"categories": ["Wallet", "Privacy"],
|
||||
"tagline": "Anonymous multi-sig wallet with Semaphore",
|
||||
"pse": false,
|
||||
"icon": "",
|
||||
"links": {
|
||||
"github": "https://github.com/jimmychu0807/semaphore-msa-modules",
|
||||
"website": "https://semaphore-msa-modules.jimmychu0807.hk"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -23,16 +23,24 @@
|
||||
"name": "Support more Testnets/Mainnets",
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"name": "Documentation improvements",
|
||||
"done": false
|
||||
},
|
||||
{
|
||||
"name": "New Explorer",
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"name": "Semaphore V4 Specification",
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"name": "Semaphore Rust Implementation",
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"name": "Semaphore Noir Implementation",
|
||||
"done": false
|
||||
},
|
||||
{
|
||||
"name": "RLN extension",
|
||||
"name": "Scaling Semaphore with PIR",
|
||||
"done": false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -118,5 +118,13 @@
|
||||
"speakers": ["Vivian Plasencia"],
|
||||
"url": "https://youtu.be/ux5Xy_lpiYk",
|
||||
"thumbnail": "https://img.youtube.com/vi/ux5Xy_lpiYk/0.jpg"
|
||||
},
|
||||
{
|
||||
"title": "Scaling Semaphore",
|
||||
"eventName": "ETHDam",
|
||||
"date": "2025-05-10",
|
||||
"speakers": ["Vivian Plasencia"],
|
||||
"url": "https://youtu.be/IkYtKSQLR-A",
|
||||
"thumbnail": "https://img.youtube.com/vi/IkYtKSQLR-A/0.jpg"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
"scripts": {
|
||||
"build": "yarn build:libraries && yarn build:subgraph && yarn build:website && yarn build:docs",
|
||||
"build:libraries": "yarn workspaces foreach -Apt --no-private run build",
|
||||
"clean:subgraph": "rimraf apps/subgraph/node_modules",
|
||||
"build:subgraph": "yarn clean:subgraph && yarn workspace semaphore-subgraph build:sepolia",
|
||||
"build:subgraph": "yarn workspace semaphore-subgraph build:sepolia",
|
||||
"build:website": "yarn workspace semaphore-website build",
|
||||
"build:docs": "yarn workspace semaphore-docs build",
|
||||
"compile:contracts": "yarn workspace semaphore-contracts compile",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/circuits",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore Circom circuits to generate zero-knowledge proofs.",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
||||
@@ -56,7 +56,7 @@ template Semaphore(MAX_DEPTH) {
|
||||
// Proof of membership verification.
|
||||
// The Merkle root passed as output must be equal to that calculated within
|
||||
// the circuit through the inputs of the Merkle proof.
|
||||
// See https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/circuits/circom/binary-merkle-root.circom
|
||||
// See https://github.com/privacy-scaling-explorations/zk-kit.circom/blob/main/packages/binary-merkle-root/src/binary-merkle-root.circom
|
||||
// to know more about how the 'BinaryMerkleRoot' template works.
|
||||
merkleRoot <== BinaryMerkleRoot(MAX_DEPTH)(identityCommitment, merkleProofLength, merkleProofIndices, merkleProofSiblings);
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-contracts-foundry",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore Foundry template.",
|
||||
"license": "Unlicense",
|
||||
"devDependencies": {
|
||||
"@semaphore-protocol/contracts": "4.8.2",
|
||||
"@zk-kit/lean-imt.sol": "2.0.0",
|
||||
"@semaphore-protocol/contracts": "4.12.0",
|
||||
"@zk-kit/lean-imt.sol": "2.0.1",
|
||||
"forge-std": "github:foundry-rs/forge-std#v1.9.4",
|
||||
"poseidon-solidity": "0.0.5",
|
||||
"prettier": "^3.2.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-contracts-hardhat",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore Hardhat template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
@@ -42,9 +42,9 @@
|
||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.0",
|
||||
"@semaphore-protocol/core": "4.8.2",
|
||||
"@semaphore-protocol/hardhat": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/core": "4.12.0",
|
||||
"@semaphore-protocol/hardhat": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"@typechain/ethers-v6": "^0.5.0",
|
||||
"@typechain/hardhat": "^9.0.0",
|
||||
"@types/chai": "^4.2.0",
|
||||
@@ -72,7 +72,7 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/contracts": "4.8.2"
|
||||
"@semaphore-protocol/contracts": "4.12.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -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.8.2",
|
||||
"@semaphore-protocol/hardhat": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/core": "4.12.0",
|
||||
"@semaphore-protocol/hardhat": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.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.8.2"
|
||||
"@semaphore-protocol/contracts": "4.12.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/core": "4.8.2",
|
||||
"@semaphore-protocol/data": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/core": "4.12.0",
|
||||
"@semaphore-protocol/data": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"ethers": "^6.13.4",
|
||||
"next": "14.1.0",
|
||||
"next-pwa": "^5.6.0",
|
||||
|
||||
@@ -114,7 +114,7 @@ export default function GroupsPage() {
|
||||
</a>{" "}
|
||||
are{" "}
|
||||
<a
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener nofollow"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-monorepo-ethers",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore Hardhat + Next.js + SemaphoreEthers template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
|
||||
@@ -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.8.2",
|
||||
"@semaphore-protocol/hardhat": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/core": "4.12.0",
|
||||
"@semaphore-protocol/hardhat": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.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.8.2"
|
||||
"@semaphore-protocol/contracts": "4.12.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/core": "4.8.2",
|
||||
"@semaphore-protocol/data": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/core": "4.12.0",
|
||||
"@semaphore-protocol/data": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"ethers": "^6.13.4",
|
||||
"next": "14.1.0",
|
||||
"next-pwa": "^5.6.0",
|
||||
|
||||
@@ -114,7 +114,7 @@ export default function GroupsPage() {
|
||||
</a>{" "}
|
||||
are{" "}
|
||||
<a
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener nofollow"
|
||||
>
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function GroupsPage() {
|
||||
</a>{" "}
|
||||
are{" "}
|
||||
<a
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html"
|
||||
href="https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener nofollow"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-monorepo-subgraph",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore Hardhat + Next.js + SemaphoreSubgraph template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli",
|
||||
"type": "module",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.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.8.2",
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/data": "4.12.0",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"axios": "^1.6.7",
|
||||
"boxen": "^7.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/contracts",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
@@ -30,6 +30,6 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zk-kit/lean-imt.sol": "2.0.0"
|
||||
"@zk-kit/lean-imt.sol": "2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,6 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zk-kit/lean-imt.sol": "2.0.0"
|
||||
"@zk-kit/lean-imt.sol": "2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/core",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "Core library for the essential Semaphore features.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -42,8 +42,8 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/group": "4.8.2",
|
||||
"@semaphore-protocol/identity": "4.8.2",
|
||||
"@semaphore-protocol/proof": "4.8.2"
|
||||
"@semaphore-protocol/group": "4.12.0",
|
||||
"@semaphore-protocol/identity": "4.12.0",
|
||||
"@semaphore-protocol/proof": "4.12.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
| This library provides tools for querying and interacting with the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) smart contract. It supports both the Semaphore subgraph and direct Ethereum network connections via Ethers. Designed for use in both Node.js and browser environments, it facilitates the management of group data and verification processes within the Semaphore protocol. |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| This library provides tools for querying and interacting with the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) smart contract. It supports the Semaphore subgraph and direct Ethereum network connections via Ethers or Viem. Designed for use in both Node.js and browser environments, it facilitates the management of group data and verification processes within the Semaphore protocol. |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
## 🛠 Install
|
||||
|
||||
@@ -173,10 +173,10 @@ const admin = await semaphoreEthers.getGroupAdmin("42")
|
||||
const members = await semaphoreEthers.getGroupMembers("42")
|
||||
```
|
||||
|
||||
**Fetch Verified Proofs**
|
||||
**Fetch Validated Proofs**
|
||||
|
||||
```typescript
|
||||
const verifiedProofs = await semaphoreEthers.getGroupVerifiedProofs("42")
|
||||
const verifiedProofs = await semaphoreEthers.getGroupValidatedProofs("42")
|
||||
```
|
||||
|
||||
**Check Group Membership**
|
||||
@@ -187,3 +187,59 @@ const isMember = await semaphoreEthers.isGroupMember(
|
||||
"16948514235341957898454876473214737047419402240398321289450170535251226167324"
|
||||
)
|
||||
```
|
||||
|
||||
### Using Viem for Direct Blockchain Interaction
|
||||
|
||||
**Initialize a Semaphore Viem instance**
|
||||
|
||||
```typescript
|
||||
import { SemaphoreViem } from "@semaphore-protocol/data"
|
||||
|
||||
const semaphoreViem = new SemaphoreViem()
|
||||
|
||||
// or:
|
||||
const semaphoreViemOnSepolia = new SemaphoreViem("sepolia", {
|
||||
address: "semaphore-address",
|
||||
startBlock: 0n
|
||||
})
|
||||
|
||||
// or:
|
||||
const localViemInstance = new SemaphoreViem("http://localhost:8545", {
|
||||
address: "semaphore-address"
|
||||
})
|
||||
```
|
||||
|
||||
With your SemaphoreViem instance, you can:
|
||||
|
||||
**Fetch Group IDs**
|
||||
|
||||
```typescript
|
||||
const groupIds = await semaphoreViem.getGroupIds()
|
||||
```
|
||||
|
||||
**Fetch Group Details**
|
||||
|
||||
```typescript
|
||||
const group = await semaphoreViem.getGroup("42")
|
||||
```
|
||||
|
||||
**Fetch Group Members**
|
||||
|
||||
```typescript
|
||||
const members = await semaphoreViem.getGroupMembers("42")
|
||||
```
|
||||
|
||||
**Fetch Validated Proofs**
|
||||
|
||||
```typescript
|
||||
const validatedProofs = await semaphoreViem.getGroupValidatedProofs("42")
|
||||
```
|
||||
|
||||
**Check Group Membership**
|
||||
|
||||
```typescript
|
||||
const isMember = await semaphoreViem.isGroupMember(
|
||||
"42",
|
||||
"16948514235341957898454876473214737047419402240398321289450170535251226167324"
|
||||
)
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/data",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "A library for querying Semaphore smart contract.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -37,8 +37,10 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"@zk-kit/utils": "1.3.0",
|
||||
"axios": "1.6.6",
|
||||
"ethers": "6.13.4"
|
||||
"ethers": "6.13.4",
|
||||
"viem": "2.23.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Validates the type of a given parameter against an expected type.
|
||||
* Throws a {@link TypeError} if the validation fails.
|
||||
* This function is useful for ensuring that function arguments conform to expected types at runtime.
|
||||
* @param value The value of the parameter to check.
|
||||
* @param name The name of the parameter, used in the error message for easier debugging.
|
||||
* @param type The expected JavaScript type as a string (e.g., 'string', 'number', 'object').
|
||||
* @throws {TypeError} Throws an error if the type of `value` does not match the `type`.
|
||||
*/
|
||||
export default function checkParameter(value: any, name: string, type: string) {
|
||||
if (typeof value !== type) {
|
||||
throw new TypeError(`Parameter '${name}' is not ${type === "object" ? "an" : "a"} ${type}`)
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
Provider
|
||||
} from "ethers/providers"
|
||||
import { SemaphoreABI } from "@semaphore-protocol/utils/constants"
|
||||
import { requireString } from "@zk-kit/utils/error-handlers"
|
||||
import { EthersNetwork, EthersOptions, GroupResponse } from "./types"
|
||||
import checkParameter from "./checkParameter"
|
||||
import getEvents from "./getEvents"
|
||||
|
||||
/**
|
||||
@@ -40,16 +40,16 @@ export default class SemaphoreEthers {
|
||||
* @param options Configuration options for the ethers provider and the Semaphore contract.
|
||||
*/
|
||||
constructor(networkOrEthereumURL: EthersNetwork | string = defaultNetwork, options: EthersOptions = {}) {
|
||||
checkParameter(networkOrEthereumURL, "networkOrEthereumURL", "string")
|
||||
requireString(networkOrEthereumURL, "networkOrEthereumURL")
|
||||
|
||||
if (options.provider) {
|
||||
checkParameter(options.provider, "provider", "string")
|
||||
requireString(options.provider, "provider")
|
||||
} else if (!networkOrEthereumURL.startsWith("http")) {
|
||||
options.provider = "infura"
|
||||
}
|
||||
|
||||
if (options.apiKey) {
|
||||
checkParameter(options.apiKey, "apiKey", "string")
|
||||
requireString(options.apiKey, "apiKey")
|
||||
}
|
||||
|
||||
if (isSupportedNetwork(networkOrEthereumURL)) {
|
||||
@@ -140,7 +140,7 @@ export default class SemaphoreEthers {
|
||||
* @returns A promise that resolves to a GroupResponse object.
|
||||
*/
|
||||
async getGroup(groupId: string): Promise<GroupResponse> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.getGroupAdmin(groupId)
|
||||
|
||||
@@ -172,7 +172,7 @@ export default class SemaphoreEthers {
|
||||
* @returns A promise that resolves to an array of member identity commitments as strings.
|
||||
*/
|
||||
async getGroupMembers(groupId: string): Promise<string[]> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.getGroupAdmin(groupId)
|
||||
|
||||
@@ -257,7 +257,7 @@ export default class SemaphoreEthers {
|
||||
* @returns A promise that resolves to an array of validated proofs.
|
||||
*/
|
||||
async getGroupValidatedProofs(groupId: string): Promise<any> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.getGroupAdmin(groupId)
|
||||
|
||||
@@ -290,8 +290,8 @@ export default class SemaphoreEthers {
|
||||
* @returns A promise that resolves to true if the member is part of the group, otherwise false.
|
||||
*/
|
||||
async isGroupMember(groupId: string, member: string): Promise<boolean> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
checkParameter(member, "member", "string")
|
||||
requireString(groupId, "groupId")
|
||||
requireString(member, "member")
|
||||
|
||||
return this._contract.hasMember(groupId, member)
|
||||
}
|
||||
|
||||
@@ -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.2.0`
|
||||
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.3.0`
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import SemaphoreEthers from "./ethers"
|
||||
import SemaphoreSubgraph from "./subgraph"
|
||||
import SemaphoreViem from "./viem"
|
||||
|
||||
export * from "./types"
|
||||
export { SemaphoreSubgraph, SemaphoreEthers }
|
||||
export { SemaphoreSubgraph, SemaphoreEthers, SemaphoreViem }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defaultNetwork, SupportedNetwork } from "@semaphore-protocol/utils/networks"
|
||||
import { AxiosRequestConfig } from "axios"
|
||||
import checkParameter from "./checkParameter"
|
||||
import { requireString, requireObject, requireBoolean } from "@zk-kit/utils/error-handlers"
|
||||
import getURL from "./getURL"
|
||||
import request from "./request"
|
||||
import { GroupOptions, GroupResponse } from "./types"
|
||||
@@ -10,7 +10,7 @@ import { jsDateToGraphqlDate } from "./utils"
|
||||
* The SemaphoreSubgraph class provides an interface to interact with the Semaphore smart contract
|
||||
* via subgraph queries. It enables operations such as retrieving lists of group members and validated proofs,
|
||||
* as well as checking membership within groups.
|
||||
* Each group in Semaphore is represented as a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
|
||||
* Each group in Semaphore is represented as a {@link https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html | LeanIMT}
|
||||
* (Lean Incremental Merkle Tree). This class supports interaction through either a
|
||||
* {@link SupportedNetwork} or a direct URL to the subgraph. The subgraphs themselves are hosted on
|
||||
* {@link https://thegraph.com/ | The Graph} protocol, facilitating efficient and decentralized query processing.
|
||||
@@ -24,7 +24,7 @@ export default class SemaphoreSubgraph {
|
||||
* @param networkOrSubgraphURL Either a supported network identifier or a direct URL to the subgraph.
|
||||
*/
|
||||
constructor(networkOrSubgraphURL: SupportedNetwork | string = defaultNetwork) {
|
||||
checkParameter(networkOrSubgraphURL, "networkOrSubgraphURL", "string")
|
||||
requireString(networkOrSubgraphURL, "networkOrSubgraphURL")
|
||||
|
||||
if (typeof networkOrSubgraphURL === "string" && networkOrSubgraphURL.startsWith("http")) {
|
||||
this._url = networkOrSubgraphURL
|
||||
@@ -73,12 +73,12 @@ export default class SemaphoreSubgraph {
|
||||
* @returns A promise that resolves to an array of group details.
|
||||
*/
|
||||
async getGroups(options: GroupOptions = {}): Promise<GroupResponse[]> {
|
||||
checkParameter(options, "options", "object")
|
||||
requireObject(options, "options")
|
||||
|
||||
const { members = false, validatedProofs = false } = options
|
||||
|
||||
checkParameter(members, "members", "boolean")
|
||||
checkParameter(validatedProofs, "validatedProofs", "boolean")
|
||||
requireBoolean(members, "members")
|
||||
requireBoolean(validatedProofs, "validatedProofs")
|
||||
|
||||
let filtersQuery = ""
|
||||
|
||||
@@ -164,13 +164,13 @@ export default class SemaphoreSubgraph {
|
||||
* @returns A promise that resolves to the details of the specified group.
|
||||
*/
|
||||
async getGroup(groupId: string, options: Omit<GroupOptions, "filters"> = {}): Promise<GroupResponse> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
checkParameter(options, "options", "object")
|
||||
requireString(groupId, "groupId")
|
||||
requireObject(options, "options")
|
||||
|
||||
const { members = false, validatedProofs = false } = options
|
||||
|
||||
checkParameter(members, "members", "boolean")
|
||||
checkParameter(validatedProofs, "validatedProofs", "boolean")
|
||||
requireBoolean(members, "members")
|
||||
requireBoolean(validatedProofs, "validatedProofs")
|
||||
|
||||
const config: AxiosRequestConfig = {
|
||||
method: "post",
|
||||
@@ -247,8 +247,8 @@ export default class SemaphoreSubgraph {
|
||||
* @returns A promise that resolves to true if the member is part of the group, otherwise false.
|
||||
*/
|
||||
async isGroupMember(groupId: string, member: string): Promise<boolean> {
|
||||
checkParameter(groupId, "groupId", "string")
|
||||
checkParameter(member, "member", "string")
|
||||
requireString(groupId, "groupId")
|
||||
requireString(member, "member")
|
||||
|
||||
const config: AxiosRequestConfig = {
|
||||
method: "post",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Chain, PublicClient, Transport } from "viem"
|
||||
|
||||
export type EthersNetwork =
|
||||
| "mainnet"
|
||||
| "sepolia"
|
||||
@@ -12,6 +14,8 @@ export type EthersNetwork =
|
||||
| "linea"
|
||||
| "linea-sepolia"
|
||||
|
||||
export type ViemNetwork = EthersNetwork
|
||||
|
||||
export type GroupOptions = {
|
||||
members?: boolean
|
||||
validatedProofs?: boolean
|
||||
@@ -54,3 +58,12 @@ export type EthersOptions = {
|
||||
applicationId?: string // Pocket
|
||||
applicationSecret?: string // Pocket
|
||||
}
|
||||
|
||||
export type ViemOptions = {
|
||||
address?: string
|
||||
startBlock?: bigint | number
|
||||
transport?: Transport // Transport from viem
|
||||
chain?: Chain // Chain from viem
|
||||
apiKey?: string
|
||||
publicClient?: PublicClient
|
||||
}
|
||||
|
||||
397
packages/data/src/viem.ts
Normal file
397
packages/data/src/viem.ts
Normal file
@@ -0,0 +1,397 @@
|
||||
import {
|
||||
SupportedNetwork,
|
||||
defaultNetwork,
|
||||
getDeployedContract,
|
||||
isSupportedNetwork
|
||||
} from "@semaphore-protocol/utils/networks"
|
||||
import { SemaphoreABI } from "@semaphore-protocol/utils/constants"
|
||||
import { requireString } from "@zk-kit/utils/error-handlers"
|
||||
import {
|
||||
Address,
|
||||
createPublicClient,
|
||||
http,
|
||||
PublicClient,
|
||||
getContract,
|
||||
GetContractReturnType,
|
||||
zeroAddress,
|
||||
Transport,
|
||||
Chain,
|
||||
Log
|
||||
} from "viem"
|
||||
import { GroupResponse, ViemNetwork, ViemOptions } from "./types"
|
||||
|
||||
// Define types for the event logs to properly access args
|
||||
type GroupCreatedLog = Log<bigint, number, boolean, any, any, any, "GroupCreated"> & {
|
||||
args: {
|
||||
groupId: bigint
|
||||
}
|
||||
}
|
||||
|
||||
type MemberRemovedLog = Log<bigint, number, boolean, any, any, any, "MemberRemoved"> & {
|
||||
args: {
|
||||
groupId: string
|
||||
index: bigint
|
||||
}
|
||||
}
|
||||
|
||||
type MemberUpdatedLog = Log<bigint, number, boolean, any, any, any, "MemberUpdated"> & {
|
||||
args: {
|
||||
groupId: string
|
||||
index: bigint
|
||||
newIdentityCommitment: string
|
||||
}
|
||||
}
|
||||
|
||||
type MembersAddedLog = Log<bigint, number, boolean, any, any, any, "MembersAdded"> & {
|
||||
args: {
|
||||
groupId: string
|
||||
startIndex: bigint
|
||||
identityCommitments: string[]
|
||||
}
|
||||
}
|
||||
|
||||
type MemberAddedLog = Log<bigint, number, boolean, any, any, any, "MemberAdded"> & {
|
||||
args: {
|
||||
groupId: string
|
||||
index: bigint
|
||||
identityCommitment: string
|
||||
}
|
||||
}
|
||||
|
||||
type ProofValidatedLog = Log<bigint, number, boolean, any, any, any, "ProofValidated"> & {
|
||||
args: {
|
||||
groupId: string
|
||||
message: string
|
||||
merkleTreeRoot: string
|
||||
merkleTreeDepth: string
|
||||
scope: string
|
||||
nullifier: string
|
||||
x: string
|
||||
y: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The SemaphoreViem class provides a high-level interface to interact with the Semaphore smart contract
|
||||
* using the {@link https://viem.sh | viem} library. It encapsulates all necessary functionalities to connect to Ethereum networks,
|
||||
* manage contract instances, and perform operations such as retrieving group information or checking group memberships.
|
||||
* This class simplifies the interaction with the Ethereum blockchain by abstracting the details of network connections
|
||||
* and contract interactions.
|
||||
*/
|
||||
export default class SemaphoreViem {
|
||||
private _network: ViemNetwork | string
|
||||
private _options: ViemOptions
|
||||
private _client: PublicClient
|
||||
private _contract: GetContractReturnType<typeof SemaphoreABI, PublicClient>
|
||||
|
||||
/**
|
||||
* Constructs a new SemaphoreViem instance, initializing it with a network or a custom Ethereum node URL,
|
||||
* and optional configuration settings for the viem client and contract.
|
||||
* @param networkOrEthereumURL The Ethereum network name or a custom JSON-RPC URL to connect to.
|
||||
* @param options Configuration options for the viem client and the Semaphore contract.
|
||||
*/
|
||||
constructor(networkOrEthereumURL: ViemNetwork | string = defaultNetwork, options: ViemOptions = {}) {
|
||||
requireString(networkOrEthereumURL, "networkOrEthereumURL")
|
||||
|
||||
if (options.apiKey) {
|
||||
requireString(options.apiKey, "apiKey")
|
||||
}
|
||||
|
||||
if (isSupportedNetwork(networkOrEthereumURL)) {
|
||||
const { address, startBlock } = getDeployedContract(networkOrEthereumURL as SupportedNetwork)
|
||||
|
||||
options.address ??= address
|
||||
options.startBlock ??= BigInt(startBlock)
|
||||
} else {
|
||||
options.startBlock ??= 0n
|
||||
}
|
||||
|
||||
if (options.address === undefined) {
|
||||
throw new Error(`Network '${networkOrEthereumURL}' needs a Semaphore contract address`)
|
||||
}
|
||||
|
||||
let transport: Transport
|
||||
if (options.transport) {
|
||||
transport = options.transport
|
||||
} else if (!networkOrEthereumURL.startsWith("http")) {
|
||||
transport = http()
|
||||
} else {
|
||||
transport = http(networkOrEthereumURL)
|
||||
}
|
||||
|
||||
this._network = networkOrEthereumURL
|
||||
this._options = options
|
||||
|
||||
// Create the public client
|
||||
this._client =
|
||||
options.publicClient ??
|
||||
createPublicClient({
|
||||
transport,
|
||||
chain: options.chain as Chain
|
||||
})
|
||||
|
||||
// Create the contract instance
|
||||
this._contract = getContract({
|
||||
address: options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
client: this._client
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Ethereum network or custom URL currently used by this instance.
|
||||
* @returns The network or URL as a string.
|
||||
*/
|
||||
get network(): ViemNetwork | string {
|
||||
return this._network
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the options used for configuring the viem client and the Semaphore contract.
|
||||
* @returns The configuration options.
|
||||
*/
|
||||
get options(): ViemOptions {
|
||||
return this._options
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the viem Contract instance used to interact with the Semaphore contract.
|
||||
* @returns The Contract instance.
|
||||
*/
|
||||
get contract(): GetContractReturnType<typeof SemaphoreABI, PublicClient> {
|
||||
return this._contract
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the viem Public Client instance used to interact with the blockchain.
|
||||
* @returns The Public Client instance.
|
||||
*/
|
||||
get client(): PublicClient {
|
||||
return this._client
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the list of group IDs from the Semaphore contract by querying the "GroupCreated" events.
|
||||
* @returns A promise that resolves to an array of group IDs as strings.
|
||||
*/
|
||||
async getGroupIds(): Promise<string[]> {
|
||||
const logs = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "GroupCreated",
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as GroupCreatedLog[]
|
||||
|
||||
return logs.map((log) => log.args.groupId.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves detailed information about a specific group by its ID. This method queries the Semaphore contract
|
||||
* to get the group's admin, Merkle tree root, depth, and size.
|
||||
* @param groupId The unique identifier of the group.
|
||||
* @returns A promise that resolves to a GroupResponse object.
|
||||
*/
|
||||
async getGroup(groupId: string): Promise<GroupResponse> {
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.read.getGroupAdmin([groupId])
|
||||
|
||||
if (groupAdmin === zeroAddress) {
|
||||
throw new Error(`Group '${groupId}' not found`)
|
||||
}
|
||||
|
||||
const merkleTreeRoot = await this._contract.read.getMerkleTreeRoot([groupId])
|
||||
const merkleTreeDepth = await this._contract.read.getMerkleTreeDepth([groupId])
|
||||
const merkleTreeSize = await this._contract.read.getMerkleTreeSize([groupId])
|
||||
|
||||
const group: GroupResponse = {
|
||||
id: groupId,
|
||||
admin: groupAdmin as string,
|
||||
merkleTree: {
|
||||
depth: Number(merkleTreeDepth),
|
||||
size: Number(merkleTreeSize),
|
||||
root: merkleTreeRoot ? merkleTreeRoot.toString() : ""
|
||||
}
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of members from a specific group. This method queries the Semaphore contract for events
|
||||
* related to member additions and updates, and constructs the list of current group members.
|
||||
* @param groupId The unique identifier of the group.
|
||||
* @returns A promise that resolves to an array of member identity commitments as strings.
|
||||
*/
|
||||
async getGroupMembers(groupId: string): Promise<string[]> {
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.read.getGroupAdmin([groupId])
|
||||
|
||||
if (groupAdmin === zeroAddress) {
|
||||
throw new Error(`Group '${groupId}' not found`)
|
||||
}
|
||||
|
||||
// Get member removed events
|
||||
const memberRemovedEvents = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "MemberRemoved",
|
||||
args: {
|
||||
groupId: BigInt(groupId)
|
||||
},
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as MemberRemovedLog[]
|
||||
|
||||
// Get member updated events
|
||||
const memberUpdatedEvents = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "MemberUpdated",
|
||||
args: {
|
||||
groupId: BigInt(groupId)
|
||||
},
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as MemberUpdatedLog[]
|
||||
|
||||
const memberUpdatedEventsMap = new Map<string, [bigint, string]>()
|
||||
|
||||
for (const event of memberUpdatedEvents) {
|
||||
if (event.args.index && event.args.newIdentityCommitment && event.blockNumber) {
|
||||
memberUpdatedEventsMap.set(event.args.index.toString(), [
|
||||
event.blockNumber,
|
||||
event.args.newIdentityCommitment.toString()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
for (const event of memberRemovedEvents) {
|
||||
if (event.args.index && event.blockNumber) {
|
||||
const groupUpdate = memberUpdatedEventsMap.get(event.args.index.toString())
|
||||
|
||||
if (!groupUpdate || (groupUpdate && groupUpdate[0] < event.blockNumber)) {
|
||||
memberUpdatedEventsMap.set(event.args.index.toString(), [event.blockNumber, "0"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get members added events (batch additions)
|
||||
const membersAddedEvents = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "MembersAdded",
|
||||
args: {
|
||||
groupId: BigInt(groupId)
|
||||
},
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as MembersAddedLog[]
|
||||
|
||||
const membersAddedEventsMap = new Map<string, string[]>()
|
||||
|
||||
for (const event of membersAddedEvents) {
|
||||
if (event.args.startIndex && event.args.identityCommitments) {
|
||||
membersAddedEventsMap.set(
|
||||
event.args.startIndex.toString(),
|
||||
event.args.identityCommitments.map((i) => i.toString())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Get individual member added events
|
||||
const memberAddedEvents = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "MemberAdded",
|
||||
args: {
|
||||
groupId: BigInt(groupId)
|
||||
},
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as MemberAddedLog[]
|
||||
|
||||
const members: string[] = []
|
||||
|
||||
const merkleTreeSize = await this._contract.read.getMerkleTreeSize([groupId])
|
||||
|
||||
let index = 0
|
||||
|
||||
while (index < Number(merkleTreeSize)) {
|
||||
const identityCommitments = membersAddedEventsMap.get(index.toString())
|
||||
|
||||
if (identityCommitments) {
|
||||
members.push(...identityCommitments)
|
||||
index += identityCommitments.length
|
||||
} else {
|
||||
const currentIndex = index // Create a closure to capture the current index value
|
||||
const event = memberAddedEvents.find((e) => Number(e.args.index) === currentIndex)
|
||||
|
||||
if (event && event.args.identityCommitment) {
|
||||
members.push(event.args.identityCommitment.toString())
|
||||
}
|
||||
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Apply updates to members
|
||||
for (let j = 0; j < members.length; j += 1) {
|
||||
const groupUpdate = memberUpdatedEventsMap.get(j.toString())
|
||||
|
||||
if (groupUpdate) {
|
||||
members[j] = groupUpdate[1].toString()
|
||||
}
|
||||
}
|
||||
|
||||
return members
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of validated proofs for a specific group. This method queries the Semaphore contract for events
|
||||
* related to proof verification.
|
||||
* @param groupId The unique identifier of the group.
|
||||
* @returns A promise that resolves to an array of validated proofs.
|
||||
*/
|
||||
async getGroupValidatedProofs(groupId: string): Promise<any> {
|
||||
requireString(groupId, "groupId")
|
||||
|
||||
const groupAdmin = await this._contract.read.getGroupAdmin([groupId])
|
||||
|
||||
if (groupAdmin === zeroAddress) {
|
||||
throw new Error(`Group '${groupId}' not found`)
|
||||
}
|
||||
|
||||
const proofValidatedEvents = (await this._client.getContractEvents({
|
||||
address: this._options.address as Address,
|
||||
abi: SemaphoreABI,
|
||||
eventName: "ProofValidated",
|
||||
args: {
|
||||
groupId: BigInt(groupId)
|
||||
},
|
||||
fromBlock: BigInt(this._options.startBlock || 0)
|
||||
})) as ProofValidatedLog[]
|
||||
|
||||
return proofValidatedEvents.map((event) => ({
|
||||
message: event.args.message?.toString() || "",
|
||||
merkleTreeRoot: event.args.merkleTreeRoot?.toString() || "",
|
||||
merkleTreeDepth: event.args.merkleTreeDepth?.toString() || "",
|
||||
scope: event.args.scope?.toString() || "",
|
||||
nullifier: event.args.nullifier?.toString() || "",
|
||||
points: [event.args.x?.toString() || "", event.args.y?.toString() || ""],
|
||||
timestamp: event.blockNumber ? new Date(Number(event.blockNumber) * 1000).toISOString() : undefined
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given identity commitment is a member of a specific group.
|
||||
* @param groupId The unique identifier of the group.
|
||||
* @param member The identity commitment to check.
|
||||
* @returns A promise that resolves to a boolean indicating whether the member is in the group.
|
||||
*/
|
||||
async isGroupMember(groupId: string, member: string): Promise<boolean> {
|
||||
requireString(groupId, "groupId")
|
||||
requireString(member, "member")
|
||||
|
||||
const members = await this.getGroupMembers(groupId)
|
||||
|
||||
return members.includes(member)
|
||||
}
|
||||
}
|
||||
108
packages/data/tests/getEvents.test.ts
Normal file
108
packages/data/tests/getEvents.test.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { Contract, EventLog } from "ethers/contract"
|
||||
import getEvents from "../src/getEvents"
|
||||
|
||||
jest.mock("ethers/contract", () => ({
|
||||
__esModule: true,
|
||||
Contract: jest.fn(),
|
||||
EventLog: jest.fn()
|
||||
}))
|
||||
|
||||
describe("getEvents", () => {
|
||||
let mockContract: jest.Mocked<Contract>
|
||||
|
||||
beforeEach(() => {
|
||||
mockContract = {
|
||||
filters: {
|
||||
TestEvent: jest.fn()
|
||||
},
|
||||
queryFilter: jest.fn()
|
||||
} as any
|
||||
})
|
||||
|
||||
describe("# getEvents", () => {
|
||||
it("should fetch events with basic parameters", async () => {
|
||||
const mockEvents = [
|
||||
{
|
||||
args: ["arg1", "arg2"],
|
||||
blockNumber: 123
|
||||
},
|
||||
{
|
||||
args: ["arg3", "arg4"],
|
||||
blockNumber: 124
|
||||
}
|
||||
] as EventLog[]
|
||||
|
||||
mockContract.queryFilter.mockResolvedValueOnce(mockEvents)
|
||||
|
||||
const result = await getEvents(mockContract, "TestEvent")
|
||||
|
||||
expect(mockContract.filters.TestEvent).toHaveBeenCalled()
|
||||
expect(mockContract.queryFilter).toHaveBeenCalled()
|
||||
expect(result).toEqual([
|
||||
["arg1", "arg2", 123],
|
||||
["arg3", "arg4", 124]
|
||||
])
|
||||
})
|
||||
|
||||
it("should handle filter arguments", async () => {
|
||||
const filterArgs = ["arg1", "arg2"]
|
||||
const mockEvents = [
|
||||
{
|
||||
args: ["arg1", "arg2"],
|
||||
blockNumber: 123
|
||||
}
|
||||
] as EventLog[]
|
||||
|
||||
mockContract.queryFilter.mockResolvedValueOnce(mockEvents)
|
||||
|
||||
await getEvents(mockContract, "TestEvent", filterArgs)
|
||||
|
||||
expect(mockContract.filters.TestEvent).toHaveBeenCalledWith(...filterArgs)
|
||||
})
|
||||
|
||||
it("should use startBlock parameter", async () => {
|
||||
const startBlock = 1000
|
||||
const mockEvents = [
|
||||
{
|
||||
args: ["arg1"],
|
||||
blockNumber: 1001
|
||||
}
|
||||
] as EventLog[]
|
||||
|
||||
mockContract.queryFilter.mockResolvedValueOnce(mockEvents)
|
||||
|
||||
await getEvents(mockContract, "TestEvent", [], startBlock)
|
||||
|
||||
expect(mockContract.queryFilter).toHaveBeenCalledWith(undefined, startBlock)
|
||||
})
|
||||
|
||||
it("should handle empty events array", async () => {
|
||||
mockContract.queryFilter.mockResolvedValueOnce([])
|
||||
|
||||
const result = await getEvents(mockContract, "TestEvent")
|
||||
|
||||
expect(result).toEqual([])
|
||||
})
|
||||
|
||||
it("should handle undefined filterArgs gracefully", async () => {
|
||||
const mockEvents = [
|
||||
{
|
||||
args: ["arg1"],
|
||||
blockNumber: 101
|
||||
}
|
||||
] as EventLog[]
|
||||
|
||||
mockContract.queryFilter.mockResolvedValueOnce(mockEvents)
|
||||
|
||||
await getEvents(mockContract, "TestEvent", undefined)
|
||||
|
||||
expect(mockContract.filters.TestEvent).toHaveBeenCalledWith()
|
||||
})
|
||||
|
||||
it("should handle contract errors", async () => {
|
||||
mockContract.queryFilter.mockRejectedValue(new Error("Contract error"))
|
||||
|
||||
await expect(getEvents(mockContract, "TestEvent")).rejects.toThrow("Contract error")
|
||||
})
|
||||
})
|
||||
})
|
||||
1110
packages/data/tests/viem.test.ts
Normal file
1110
packages/data/tests/viem.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/group",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "A library to create and manage Semaphore groups.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -36,8 +36,8 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zk-kit/lean-imt": "2.2.2",
|
||||
"@zk-kit/utils": "1.2.1",
|
||||
"@zk-kit/lean-imt": "2.2.3",
|
||||
"@zk-kit/utils": "1.3.0",
|
||||
"poseidon-lite": "0.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { BigNumber } from "@zk-kit/utils"
|
||||
import { poseidon2 } from "poseidon-lite/poseidon2"
|
||||
|
||||
/**
|
||||
* The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
|
||||
* The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html | LeanIMT}
|
||||
* (Lean Incremental Merkle Tree), i.e. an optimized version of the incremental binary Merkle tree
|
||||
* used by Semaphore V3. The new tree does not use zero hashes, and its depth is dynamic.
|
||||
* The members of a Semaphore group, or the leaves of a tree, are the identity commitments.
|
||||
@@ -13,7 +13,7 @@ import { poseidon2 } from "poseidon-lite/poseidon2"
|
||||
* generation and verification. Groups can also be exported or imported.
|
||||
*/
|
||||
export class Group {
|
||||
// The {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT} instance.
|
||||
// The {@link https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html | LeanIMT} instance.
|
||||
public leanIMT: LeanIMT
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/hardhat",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.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.8.2",
|
||||
"@semaphore-protocol/contracts": "4.12.0",
|
||||
"ethers": "^6.13.4",
|
||||
"hardhat-dependency-compiler": "^1.1.3"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/identity",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "A library to create Semaphore identities.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -39,7 +39,7 @@
|
||||
"dependencies": {
|
||||
"@zk-kit/baby-jubjub": "1.0.3",
|
||||
"@zk-kit/eddsa-poseidon": "1.0.4",
|
||||
"@zk-kit/utils": "1.2.1",
|
||||
"@zk-kit/utils": "1.3.0",
|
||||
"poseidon-lite": "0.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/proof",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "A library to generate and verify Semaphore proofs.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -47,13 +47,13 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@semaphore-protocol/group": "4.8.2",
|
||||
"@semaphore-protocol/identity": "4.8.2"
|
||||
"@semaphore-protocol/group": "4.12.0",
|
||||
"@semaphore-protocol/identity": "4.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/utils": "4.8.2",
|
||||
"@semaphore-protocol/utils": "4.12.0",
|
||||
"@zk-kit/artifacts": "1.8.0",
|
||||
"@zk-kit/utils": "1.2.1",
|
||||
"@zk-kit/utils": "1.3.0",
|
||||
"ethers": "6.13.4",
|
||||
"snarkjs": "0.7.4"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/utils",
|
||||
"version": "4.8.2",
|
||||
"version": "4.12.0",
|
||||
"description": "A library to provide utility functions to the other Semaphore packages.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -5,17 +5,37 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 6983614
|
||||
"startBlock": 8263690
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 6983614
|
||||
"startBlock": 8263690
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 6983614
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 8263690
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"network": "ethereum",
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 22424592
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 22424592
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 22424592
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -25,17 +45,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 93258221
|
||||
"startBlock": 149903019
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 93258221
|
||||
"startBlock": 149903019
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 93258221
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 149903019
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -45,17 +65,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 19289434
|
||||
"startBlock": 27341051
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 19289434
|
||||
"startBlock": 27341051
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 19289434
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 27341051
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -65,17 +85,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 13850778
|
||||
"startBlock": 21308099
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 13850778
|
||||
"startBlock": 21308099
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 13850778
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 21308099
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -85,17 +105,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 269586534
|
||||
"startBlock": 333645515
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 269586534
|
||||
"startBlock": 333645515
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 269586534
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 333645515
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -105,17 +125,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 63715311
|
||||
"startBlock": 71158898
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 63715311
|
||||
"startBlock": 71158898
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 63715311
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 71158898
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -125,17 +145,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 127391657
|
||||
"startBlock": 135443119
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 127391657
|
||||
"startBlock": 135443119
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 127391657
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 135443119
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -145,17 +165,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 17307202
|
||||
"startBlock": 25358716
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 17307202
|
||||
"startBlock": 25358716
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 17307202
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 25358716
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -165,17 +185,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 5225214
|
||||
"startBlock": 12757656
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 5225214
|
||||
"startBlock": 12757656
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 5225214
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 12757656
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -185,17 +205,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 21796660
|
||||
"startBlock": 29848242
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 21796660
|
||||
"startBlock": 29848242
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 21796660
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 29848242
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -205,17 +225,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 11459722
|
||||
"startBlock": 18707811
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 11459722
|
||||
"startBlock": 18707811
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 11459722
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 18707811
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -225,17 +245,17 @@
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 7397758
|
||||
"startBlock": 9604960
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 7397758
|
||||
"startBlock": 9604960
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 7397758
|
||||
"address": "0x697c80d1F2654e88d52B16154929EB976568DB04",
|
||||
"startBlock": 9604960
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ export default {
|
||||
chainId: 11155111,
|
||||
explorer: "https://sepolia.etherscan.io"
|
||||
},
|
||||
ethereum: {
|
||||
name: "Ethereum",
|
||||
url: "https://eth-mainnet.g.alchemy.com/v2/<your-api-key>",
|
||||
chainId: 1,
|
||||
explorer: "https://etherscan.io"
|
||||
},
|
||||
"arbitrum-sepolia": {
|
||||
name: "Arbitrum Sepolia",
|
||||
url: "https://sepolia-rollup.arbitrum.io/rpc",
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user