Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions packages/data/src/ethers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { requireString, requireTypes } from "@zk-kit/utils/error-handlers"
import { EthersNetwork, EthersOptions, GroupResponse, GroupId } from "./types"
import getEvents from "./getEvents"

/**
Expand Down Expand Up @@ -139,8 +139,8 @@ export default class SemaphoreEthers {
* @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")
async getGroup(groupId: GroupId): Promise<GroupResponse> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.getGroupAdmin(groupId)

Expand All @@ -153,7 +153,7 @@ export default class SemaphoreEthers {
const merkleTreeSize = await this._contract.getMerkleTreeSize(groupId)

const group: GroupResponse = {
id: groupId,
id: groupId.toString(),
admin: groupAdmin,
merkleTree: {
depth: Number(merkleTreeDepth),
Expand All @@ -171,8 +171,8 @@ export default class SemaphoreEthers {
* @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")
async getGroupMembers(groupId: GroupId): Promise<string[]> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.getGroupAdmin(groupId)

Expand Down Expand Up @@ -256,8 +256,8 @@ export default class SemaphoreEthers {
* @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")
async getGroupValidatedProofs(groupId: GroupId): Promise<any> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.getGroupAdmin(groupId)

Expand Down Expand Up @@ -289,8 +289,8 @@ export default class SemaphoreEthers {
* @param member The identity commitment of the member to check.
* @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> {
requireString(groupId, "groupId")
async isGroupMember(groupId: GroupId, member: string): Promise<boolean> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])
requireString(member, "member")

return this._contract.hasMember(groupId, member)
Expand Down
20 changes: 10 additions & 10 deletions packages/data/src/subgraph.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { defaultNetwork, SupportedNetwork } from "@semaphore-protocol/utils/networks"
import { AxiosRequestConfig } from "axios"
import { requireString, requireObject, requireBoolean } from "@zk-kit/utils/error-handlers"
import { requireString, requireObject, requireBoolean, requireTypes } from "@zk-kit/utils/error-handlers"
import getURL from "./getURL"
import request from "./request"
import { GroupOptions, GroupResponse } from "./types"
import { GroupId, GroupOptions, GroupResponse } from "./types"
import { jsDateToGraphqlDate } from "./utils"

/**
Expand Down Expand Up @@ -163,8 +163,8 @@ export default class SemaphoreSubgraph {
* @param options Configuration options to specify which details to fetch about the group.
* @returns A promise that resolves to the details of the specified group.
*/
async getGroup(groupId: string, options: Omit<GroupOptions, "filters"> = {}): Promise<GroupResponse> {
requireString(groupId, "groupId")
async getGroup(groupId: GroupId, options: Omit<GroupOptions, "filters"> = {}): Promise<GroupResponse> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number"])
requireObject(options, "options")

const { members = false, validatedProofs = false } = options
Expand All @@ -176,7 +176,7 @@ export default class SemaphoreSubgraph {
method: "post",
data: JSON.stringify({
query: `{
groups(where: { id: "${groupId}" }) {
groups(where: { id: "${groupId.toString()}" }) {
id
merkleTree {
root
Expand Down Expand Up @@ -223,7 +223,7 @@ export default class SemaphoreSubgraph {
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to an array of group members' identity commitments.
*/
async getGroupMembers(groupId: string): Promise<string[]> {
async getGroupMembers(groupId: GroupId): Promise<string[]> {
const group = await this.getGroup(groupId, { members: true }) // parameters are checked inside getGroup
return group.members!
}
Expand All @@ -233,7 +233,7 @@ export default class SemaphoreSubgraph {
* @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[]> {
async getGroupValidatedProofs(groupId: GroupId): Promise<any[]> {
const group = await this.getGroup(groupId, { validatedProofs: true }) // parameters are checked inside getGroup

return group.validatedProofs!
Expand All @@ -246,15 +246,15 @@ export default class SemaphoreSubgraph {
* @param member The identity commitment of the member to check.
* @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> {
requireString(groupId, "groupId")
async isGroupMember(groupId: GroupId, member: string): Promise<boolean> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number"])
requireString(member, "member")

const config: AxiosRequestConfig = {
method: "post",
data: JSON.stringify({
query: `{
groups(where: { id: "${groupId}", members_: { identityCommitment: "${member}" } }) {
groups(where: { id: "${groupId.toString()}", members_: { identityCommitment: "${member}" } }) {
id
}
}`
Expand Down
3 changes: 3 additions & 0 deletions packages/data/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Chain, PublicClient, Transport } from "viem"
import type { BigNumberish } from "ethers"

export type EthersNetwork =
| "mainnet"
Expand All @@ -16,6 +17,8 @@ export type EthersNetwork =

export type ViemNetwork = EthersNetwork

export type GroupId = BigNumberish

export type GroupOptions = {
members?: boolean
validatedProofs?: boolean
Expand Down
52 changes: 30 additions & 22 deletions packages/data/src/viem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
isSupportedNetwork
} from "@semaphore-protocol/utils/networks"
import { SemaphoreABI } from "@semaphore-protocol/utils/constants"
import { requireString } from "@zk-kit/utils/error-handlers"
import { requireString, requireTypes } from "@zk-kit/utils/error-handlers"
import {
Address,
createPublicClient,
Expand All @@ -18,7 +18,15 @@ import {
Chain,
Log
} from "viem"
import { GroupResponse, ViemNetwork, ViemOptions } from "./types"
import { GroupResponse, ViemNetwork, ViemOptions, GroupId } from "./types"

function toBigIntId(id: GroupId): bigint {
if (typeof id === "bigint") return id
if (typeof id === "number") return BigInt(id)
if (typeof id === "string") return BigInt(id)
if ((id as any) && typeof (id as any).toString === "function") return BigInt((id as any).toString())
throw new TypeError("groupId must be a valid BigNumberish")
}

// Define types for the event logs to properly access args
type GroupCreatedLog = Log<bigint, number, boolean, any, any, any, "GroupCreated"> & {
Expand Down Expand Up @@ -191,21 +199,21 @@ export default class SemaphoreViem {
* @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")
async getGroup(groupId: GroupId): Promise<GroupResponse> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.read.getGroupAdmin([groupId])
const groupAdmin = await this._contract.read.getGroupAdmin([toBigIntId(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 merkleTreeRoot = await this._contract.read.getMerkleTreeRoot([toBigIntId(groupId)])
const merkleTreeDepth = await this._contract.read.getMerkleTreeDepth([toBigIntId(groupId)])
const merkleTreeSize = await this._contract.read.getMerkleTreeSize([toBigIntId(groupId)])

const group: GroupResponse = {
id: groupId,
id: groupId.toString(),
admin: groupAdmin as string,
merkleTree: {
depth: Number(merkleTreeDepth),
Expand All @@ -223,10 +231,10 @@ export default class SemaphoreViem {
* @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")
async getGroupMembers(groupId: GroupId): Promise<string[]> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.read.getGroupAdmin([groupId])
const groupAdmin = await this._contract.read.getGroupAdmin([toBigIntId(groupId)])

if (groupAdmin === zeroAddress) {
throw new Error(`Group '${groupId}' not found`)
Expand All @@ -238,7 +246,7 @@ export default class SemaphoreViem {
abi: SemaphoreABI,
eventName: "MemberRemoved",
args: {
groupId: BigInt(groupId)
groupId: toBigIntId(groupId)
},
fromBlock: BigInt(this._options.startBlock || 0)
})) as MemberRemovedLog[]
Expand All @@ -249,7 +257,7 @@ export default class SemaphoreViem {
abi: SemaphoreABI,
eventName: "MemberUpdated",
args: {
groupId: BigInt(groupId)
groupId: toBigIntId(groupId)
},
fromBlock: BigInt(this._options.startBlock || 0)
})) as MemberUpdatedLog[]
Expand Down Expand Up @@ -281,7 +289,7 @@ export default class SemaphoreViem {
abi: SemaphoreABI,
eventName: "MembersAdded",
args: {
groupId: BigInt(groupId)
groupId: toBigIntId(groupId)
},
fromBlock: BigInt(this._options.startBlock || 0)
})) as MembersAddedLog[]
Expand All @@ -303,14 +311,14 @@ export default class SemaphoreViem {
abi: SemaphoreABI,
eventName: "MemberAdded",
args: {
groupId: BigInt(groupId)
groupId: toBigIntId(groupId)
},
fromBlock: BigInt(this._options.startBlock || 0)
})) as MemberAddedLog[]

const members: string[] = []

const merkleTreeSize = await this._contract.read.getMerkleTreeSize([groupId])
const merkleTreeSize = await this._contract.read.getMerkleTreeSize([toBigIntId(groupId)])

let index = 0

Expand Down Expand Up @@ -350,8 +358,8 @@ export default class SemaphoreViem {
* @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")
async getGroupValidatedProofs(groupId: GroupId): Promise<any> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])

const groupAdmin = await this._contract.read.getGroupAdmin([groupId])

Expand All @@ -364,7 +372,7 @@ export default class SemaphoreViem {
abi: SemaphoreABI,
eventName: "ProofValidated",
args: {
groupId: BigInt(groupId)
groupId: toBigIntId(groupId)
},
fromBlock: BigInt(this._options.startBlock || 0)
})) as ProofValidatedLog[]
Expand All @@ -386,8 +394,8 @@ export default class SemaphoreViem {
* @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")
async isGroupMember(groupId: GroupId, member: string): Promise<boolean> {
requireTypes(groupId as any, "groupId", ["string", "bigint", "number", "object"])
requireString(member, "member")

const members = await this.getGroupMembers(groupId)
Expand Down