mirror of
https://github.com/semaphore-protocol/semaphore.git
synced 2026-01-10 23:28:17 -05:00
feat(utils): new semaphore utilities + zk-kit replacements
The utils package will no longer provide errors and types utilities as those functions have been moved to zk-kit. The utils package now provides a list of supported networks and a function to decode messages instead. re #642, #641
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/data": "4.0.0-beta.2",
|
||||
"@semaphore-protocol/utils": "4.0.0-beta.2",
|
||||
"axios": "^1.6.7",
|
||||
"boxen": "^7.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
|
||||
@@ -18,7 +18,14 @@ const banner = `#!/usr/bin/env node
|
||||
export default {
|
||||
input: "src/index.ts",
|
||||
output: [{ file: pkg.bin.semaphore, format: "es", banner }],
|
||||
external: [...Object.keys(pkg.dependencies), "url", "fs", "path", "child_process"],
|
||||
external: [
|
||||
...Object.keys(pkg.dependencies),
|
||||
"url",
|
||||
"fs",
|
||||
"path",
|
||||
"child_process",
|
||||
"@semaphore-protocol/utils/supported-networks"
|
||||
],
|
||||
plugins: [
|
||||
typescript({
|
||||
tsconfig: "./build.tsconfig.json"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { GroupResponse, SemaphoreEthers, SemaphoreSubgraph, getSupportedNetworks } from "@semaphore-protocol/data"
|
||||
import { GroupResponse, SemaphoreEthers, SemaphoreSubgraph } from "@semaphore-protocol/data"
|
||||
import supportedNetworks from "@semaphore-protocol/utils/supported-networks"
|
||||
import chalk from "chalk"
|
||||
import { program } from "commander"
|
||||
import decompress from "decompress"
|
||||
@@ -16,8 +17,6 @@ import Spinner from "./spinner.js"
|
||||
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
|
||||
const { description, version } = JSON.parse(readFileSync(`${packagePath}/package.json`, "utf8"))
|
||||
|
||||
const supportedNetworks = getSupportedNetworks()
|
||||
|
||||
const supportedTemplates = [
|
||||
{
|
||||
value: "monorepo-ethers",
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("Semaphore", () => {
|
||||
const merkleTreeDepth = 12
|
||||
|
||||
const groupId = 0
|
||||
const members = Array.from({ length: 3 }, (_, i) => new Identity(i)).map(({ commitment }) => commitment)
|
||||
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(({ commitment }) => commitment)
|
||||
|
||||
before(async () => {
|
||||
const { semaphore } = await run("deploy", {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { SupportedNetwork } from "./types"
|
||||
|
||||
/**
|
||||
* Returns the list of Semaphore supported networks.
|
||||
* @returns Semaphore supported networks.
|
||||
*/
|
||||
export default function getSupportedNetworks(): string[] {
|
||||
return Object.values(SupportedNetwork)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import SemaphoreEthers from "./ethers"
|
||||
import getSupportedNetworks from "./getSupportedNetworks"
|
||||
import SemaphoreSubgraph from "./subgraph"
|
||||
|
||||
export * from "./types"
|
||||
export { SemaphoreSubgraph, SemaphoreEthers, getSupportedNetworks }
|
||||
export { SemaphoreSubgraph, SemaphoreEthers }
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import getSupportedNetworks from "../src/getSupportedNetworks"
|
||||
|
||||
describe("Data", () => {
|
||||
describe("# getSupportedNetworks", () => {
|
||||
it("Should return a list of supported networks", () => {
|
||||
const supportedNetworks = getSupportedNetworks()
|
||||
|
||||
expect(supportedNetworks).toHaveLength(5)
|
||||
expect(supportedNetworks).toContain("sepolia")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
GenerateRegistrationOptionsOpts as RegistrationOptions
|
||||
} from "@simplewebauthn/server"
|
||||
|
||||
import { HeyAuthn } from "../src"
|
||||
import HeyAuthn from "../src/hey-authn"
|
||||
|
||||
jest.mock("@simplewebauthn/browser", () => ({
|
||||
startRegistration: async () => ({
|
||||
|
||||
@@ -34,7 +34,8 @@ export default {
|
||||
"ethers/crypto",
|
||||
"ethers/utils",
|
||||
"ethers/abi",
|
||||
"@semaphore-protocol/utils/errors"
|
||||
"@zk-kit/utils/error-handlers",
|
||||
"@zk-kit/utils/proof-packing"
|
||||
],
|
||||
plugins: [
|
||||
alias({
|
||||
|
||||
@@ -39,7 +39,8 @@ export default {
|
||||
"ethers/crypto",
|
||||
"ethers/utils",
|
||||
"ethers/abi",
|
||||
"@semaphore-protocol/utils/errors"
|
||||
"@zk-kit/utils/error-handlers",
|
||||
"@zk-kit/utils/proof-packing"
|
||||
],
|
||||
plugins: [
|
||||
typescript({
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import type { Group, MerkleProof } from "@semaphore-protocol/group"
|
||||
import type { Identity } from "@semaphore-protocol/identity"
|
||||
import { requireDefined, requireNumber, requireObject, requireTypes } from "@semaphore-protocol/utils/errors"
|
||||
import { MIN_DEPTH, MAX_DEPTH } from "@semaphore-protocol/utils/constants"
|
||||
import { NumericString, groth16 } from "snarkjs"
|
||||
import { MAX_DEPTH, MIN_DEPTH } from "@semaphore-protocol/utils/constants"
|
||||
import { requireDefined, requireNumber, requireObject, requireTypes } from "@zk-kit/utils/error-handlers"
|
||||
import { packGroth16Proof } from "@zk-kit/utils/proof-packing"
|
||||
import type { BigNumberish } from "ethers"
|
||||
import { NumericString, groth16 } from "snarkjs"
|
||||
import getSnarkArtifacts from "./get-snark-artifacts.node"
|
||||
import hash from "./hash"
|
||||
import toBigInt from "./to-bigint"
|
||||
import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
|
||||
import { SemaphoreProof, SnarkArtifacts } from "./types"
|
||||
|
||||
/**
|
||||
* It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
|
||||
@@ -44,8 +45,8 @@ export default async function generateProof(
|
||||
|
||||
requireObject(identity, "identity")
|
||||
requireObject(groupOrMerkleProof, "groupOrMerkleProof")
|
||||
requireTypes(message, "message", ["string", "bigint", "number", "uint8array"])
|
||||
requireTypes(scope, "scope", ["string", "bigint", "number", "uint8array"])
|
||||
requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"])
|
||||
requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"])
|
||||
|
||||
if (merkleTreeDepth) {
|
||||
requireNumber(merkleTreeDepth, "merkleTreeDepth")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* istanbul ignore file */
|
||||
import { requireNumber } from "@semaphore-protocol/utils/errors"
|
||||
import { requireNumber } from "@zk-kit/utils/error-handlers"
|
||||
import { SnarkArtifacts } from "./types"
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* istanbul ignore file */
|
||||
import { requireNumber } from "@semaphore-protocol/utils/errors"
|
||||
import { requireNumber } from "@zk-kit/utils/error-handlers"
|
||||
import { createWriteStream, existsSync, readdirSync } from "node:fs"
|
||||
import { mkdir } from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { BigNumberish } from "ethers"
|
||||
import { keccak256 } from "ethers/crypto"
|
||||
import { toBeHex } from "ethers/utils"
|
||||
import { NumericString } from "snarkjs"
|
||||
import { BigNumberish } from "./types"
|
||||
|
||||
/**
|
||||
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { BigNumberish } from "ethers"
|
||||
import { encodeBytes32String } from "ethers/abi"
|
||||
import { toBigInt as _toBigInt } from "ethers/utils"
|
||||
import { BigNumberish } from "./types"
|
||||
|
||||
/**
|
||||
* Converts a bignumberish to a bigint.
|
||||
* Converts a bignumberish or a text to a bigint.
|
||||
* @param value The value to be converted to bigint.
|
||||
* @return The value converted to bigint.
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import type { NumericString } from "snarkjs"
|
||||
import type { PackedGroth16Proof } from "@zk-kit/utils"
|
||||
|
||||
export type BigNumberish = string | number | bigint
|
||||
|
||||
export type SnarkArtifacts = {
|
||||
wasmFilePath: string
|
||||
zkeyFilePath: string
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import {
|
||||
requireArray,
|
||||
requireDefined,
|
||||
requireNumber,
|
||||
requireObject,
|
||||
requireString
|
||||
} from "@semaphore-protocol/utils/errors"
|
||||
import { MIN_DEPTH, MAX_DEPTH } from "@semaphore-protocol/utils/constants"
|
||||
import { groth16 } from "snarkjs"
|
||||
import { MAX_DEPTH, MIN_DEPTH } from "@semaphore-protocol/utils/constants"
|
||||
import { requireArray, requireDefined, requireNumber, requireObject, requireString } from "@zk-kit/utils/error-handlers"
|
||||
import { unpackGroth16Proof } from "@zk-kit/utils/proof-packing"
|
||||
import { groth16 } from "snarkjs"
|
||||
import hash from "./hash"
|
||||
import { SemaphoreProof } from "./types"
|
||||
import verificationKeys from "./verification-keys.json"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Group } from "@semaphore-protocol/group"
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
import { getCurveFromName } from "ffjavascript"
|
||||
import { SemaphoreProof, generateProof, verifyProof } from "../src"
|
||||
import generateProof from "../src/generate-proof"
|
||||
import { SemaphoreProof } from "../src/types"
|
||||
import verifyProof from "../src/verify-proof"
|
||||
|
||||
describe("Proof", () => {
|
||||
const treeDepth = 10
|
||||
@@ -9,7 +11,7 @@ describe("Proof", () => {
|
||||
const message = "Hello world"
|
||||
const scope = "Scope"
|
||||
|
||||
const identity = new Identity(42)
|
||||
const identity = new Identity("secret")
|
||||
|
||||
let proof: SemaphoreProof
|
||||
let curve: any
|
||||
|
||||
@@ -70,10 +70,10 @@ yarn add @semaphore-protocol/utils
|
||||
For more information on the functions and modules provided by `@semaphore-protocol/utils`, please refer to the [TypeDoc documentation](https://js.semaphore.pse.dev/modules/_semaphore_protocol_utils).
|
||||
|
||||
```typescript
|
||||
// You can import modules from the main bundle.
|
||||
import { errors, types } from "@semaphore-protocol/utils"
|
||||
// You can import functions/parameters from the main bundle.
|
||||
import { supportedNetworks, decodeMessage } from "@semaphore-protocol/utils"
|
||||
|
||||
// Or by using conditional exports.
|
||||
import { requireNumber } from "@semaphore-protocol/utils/errors"
|
||||
import { isNumber } from "@semaphore-protocol/utils/types"
|
||||
import supportedNetworks from "@semaphore-protocol/utils/supported-networks"
|
||||
import decodeMessage from "@semaphore-protocol/utils/decode-message"
|
||||
```
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
"require": "./dist/index.cjs",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./errors": {
|
||||
"types": "./dist/types/errors.d.ts",
|
||||
"require": "./dist/lib.commonjs/errors.cjs",
|
||||
"default": "./dist/lib.esm/errors.js"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./dist/types/types.d.ts",
|
||||
"require": "./dist/lib.commonjs/types.cjs",
|
||||
"default": "./dist/lib.esm/types.js"
|
||||
"./supported-networks": {
|
||||
"types": "./dist/types/supported-networks.d.ts",
|
||||
"require": "./dist/lib.commonjs/supported-networks.cjs",
|
||||
"default": "./dist/lib.esm/supported-networks.js"
|
||||
},
|
||||
"./constants": {
|
||||
"types": "./dist/types/constants.d.ts",
|
||||
"require": "./dist/lib.commonjs/constants.cjs",
|
||||
"default": "./dist/lib.esm/constants.js"
|
||||
},
|
||||
"./decode-message": {
|
||||
"types": "./dist/types/decode-message.d.ts",
|
||||
"require": "./dist/lib.commonjs/decode-message.cjs",
|
||||
"default": "./dist/lib.esm/decode-message.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@@ -51,5 +51,8 @@
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.12.0",
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethers": "^6.11.1"
|
||||
}
|
||||
}
|
||||
|
||||
17
packages/utils/src/decode-message.ts
Normal file
17
packages/utils/src/decode-message.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { BigNumberish } from "ethers"
|
||||
import { decodeBytes32String } from "ethers/abi"
|
||||
import { toBeHex } from "ethers/utils"
|
||||
|
||||
/**
|
||||
* Typically used for decoding on-chain Semaphore messages.
|
||||
* When Semaphore messages are text they are converted to bigints before
|
||||
* the proof is generated (and eventually sent on-chain).
|
||||
* This function help devs converting bigint messages to text again.
|
||||
* If the original message was not text the output of this
|
||||
* function won't probably be human-readable text.
|
||||
* @param message The Semaphore message as a bigint.
|
||||
* @returns The Semaphore message as a text.
|
||||
*/
|
||||
export default function decodeMessage(message: BigNumberish) {
|
||||
return decodeBytes32String(toBeHex(message, 32))
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/**
|
||||
* @module Errors
|
||||
* This module is designed to provide utility functions for validating
|
||||
* function parameters. It includes functions that throw type errors if
|
||||
* the parameters do not meet specified criteria, such as being defined,
|
||||
* a number, a string, a function, or an array. This module helps ensure
|
||||
* that functions receive the correct types of inputs, enhancing code
|
||||
* reliability and reducing runtime errors.
|
||||
*/
|
||||
|
||||
import {
|
||||
SupportedType,
|
||||
isArray,
|
||||
isBigInt,
|
||||
isDefined,
|
||||
isFunction,
|
||||
isNumber,
|
||||
isObject,
|
||||
isString,
|
||||
isSupportedType,
|
||||
isType,
|
||||
isUint8Array
|
||||
} from "./types"
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value has not been defined.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireDefined(parameterValue: any, parameterName: string) {
|
||||
if (!isDefined(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not defined`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not a number.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireNumber(parameterValue: number, parameterName: string) {
|
||||
if (!isNumber(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not a number`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not a string.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireString(parameterValue: string, parameterName: string) {
|
||||
if (!isString(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not a string`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not a function.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireFunction(parameterValue: Function, parameterName: string) {
|
||||
if (!isFunction(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not a function`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not an array.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireArray(parameterValue: any[], parameterName: string) {
|
||||
if (!isArray(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not an array`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not a uint8array.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireUint8Array(parameterValue: Uint8Array, parameterName: string) {
|
||||
if (!isUint8Array(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not a Uint8Array`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not an object.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireObject(parameterValue: object, parameterName: string) {
|
||||
if (!isObject(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not an object`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value is not a bigint.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireBigInt(parameterValue: bigint, parameterName: string) {
|
||||
if (!isBigInt(parameterValue)) {
|
||||
throw new TypeError(`Parameter '${parameterName}' is not a bigint`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It throws a type error if the parameter value type is not part of the list of types.
|
||||
* @param parameterValue The parameter value.
|
||||
* @param parameterName The parameter name.
|
||||
*/
|
||||
export function requireTypes(parameterValue: any, parameterName: string, types: SupportedType[]) {
|
||||
for (const type of types) {
|
||||
if (!isSupportedType(type)) {
|
||||
throw new Error(`Type '${type}' is not supported`)
|
||||
}
|
||||
}
|
||||
|
||||
for (const type of types) {
|
||||
if (isType(parameterValue, type)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeError(`Parameter '${parameterName}' is none of the following types: ${types.join(", ")}`)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as errors from "./errors"
|
||||
import * as types from "./types"
|
||||
import * as constants from "./constants"
|
||||
import supportedNetworks from "./supported-networks"
|
||||
|
||||
export { errors, types, constants }
|
||||
export * from "./types"
|
||||
export { constants, supportedNetworks }
|
||||
|
||||
6
packages/utils/src/supported-networks.ts
Normal file
6
packages/utils/src/supported-networks.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { SupportedNetwork } from "./types"
|
||||
|
||||
// List of Semaphore supported networks.
|
||||
const supportedNetwork: SupportedNetwork[] = ["sepolia", "mumbai", "optimism-sepolia", "arbitrum-sepolia", "arbitrum"]
|
||||
|
||||
export default supportedNetwork
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* @module Types
|
||||
* This module provides utility functions to check data types.
|
||||
* It defines a set of supported types and includes functions to check if
|
||||
* a value is defined and if it matches a supported type. These functions
|
||||
* are useful for type checking and validation in the other libraries,
|
||||
* enhancing code robustness and reliability.
|
||||
*/
|
||||
|
||||
// The list of types supported by this utility functions.
|
||||
const supportedTypes = ["number", "string", "function", "array", "uint8array", "object", "bigint"] as const
|
||||
|
||||
// Type extracted from the list above.
|
||||
export type SupportedType = (typeof supportedTypes)[number]
|
||||
|
||||
/**
|
||||
* It returns true if the value is defined, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isDefined(value: any): boolean {
|
||||
return typeof value !== "undefined"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is a number, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isNumber(value: any): boolean {
|
||||
return typeof value === "number"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is a string, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isString(value: any): boolean {
|
||||
return typeof value === "string"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is a function, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isFunction(value: any): boolean {
|
||||
return typeof value === "function"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is an array, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isArray(value: any): boolean {
|
||||
return typeof value === "object" && Array.isArray(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is a uint8array, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isUint8Array(value: any): boolean {
|
||||
return value instanceof Uint8Array
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is an object, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isObject(value: any): boolean {
|
||||
return typeof value === "object"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value is a bigint, false otherwise.
|
||||
* @param value The value to be checked.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isBigInt(value: any): boolean {
|
||||
return typeof value === "bigint"
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns true if the value type is the same as the type passed
|
||||
* as the second parameter, false otherwise.
|
||||
* @param type The expected type.
|
||||
* @returns True or false.
|
||||
*/
|
||||
export function isType(value: any, type: SupportedType): boolean {
|
||||
switch (type) {
|
||||
case "number":
|
||||
return isNumber(value)
|
||||
case "string":
|
||||
return isString(value)
|
||||
case "function":
|
||||
return isFunction(value)
|
||||
case "array":
|
||||
return isArray(value)
|
||||
case "uint8array":
|
||||
return isUint8Array(value)
|
||||
case "object":
|
||||
return isObject(value)
|
||||
case "bigint":
|
||||
return isBigInt(value)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the type is being supported by this utility
|
||||
* functions, false otherwise.
|
||||
* @param type The type to be checked.
|
||||
* @returns True or false
|
||||
*/
|
||||
export function isSupportedType(type: string): type is SupportedType {
|
||||
return (supportedTypes as readonly string[]).includes(type)
|
||||
}
|
||||
1
packages/utils/src/types/index.ts
Normal file
1
packages/utils/src/types/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type SupportedNetwork = "sepolia" | "mumbai" | "optimism-sepolia" | "arbitrum-sepolia" | "arbitrum"
|
||||
@@ -1,206 +1,24 @@
|
||||
import { errors, types } from "../src"
|
||||
import { encodeBytes32String } from "ethers/abi"
|
||||
import { toBigInt } from "ethers/utils"
|
||||
import { supportedNetworks } from "../src"
|
||||
import decodeMessage from "../src/decode-message"
|
||||
|
||||
describe("Utils", () => {
|
||||
describe("# types", () => {
|
||||
it("Should return true if the value is a number", () => {
|
||||
expect(types.isNumber(1)).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not a number", () => {
|
||||
expect(types.isNumber("string")).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is a string", () => {
|
||||
expect(types.isString("string")).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not a string", () => {
|
||||
expect(types.isString(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is a function", () => {
|
||||
expect(types.isFunction(() => true)).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not a function", () => {
|
||||
expect(types.isFunction(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is an array", () => {
|
||||
expect(types.isArray([])).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not an array", () => {
|
||||
expect(types.isArray(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is a uint8array", () => {
|
||||
expect(types.isUint8Array(new Uint8Array([]))).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not a uint8array", () => {
|
||||
expect(types.isUint8Array(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is an object", () => {
|
||||
expect(types.isObject({})).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not an object", () => {
|
||||
expect(types.isObject(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value is a bigint", () => {
|
||||
expect(types.isBigInt(BigInt(1))).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value is not a bigint", () => {
|
||||
expect(types.isBigInt(1)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the value type is the one expected", () => {
|
||||
expect(types.isType(1, "number")).toBeTruthy()
|
||||
expect(types.isType("string", "string")).toBeTruthy()
|
||||
expect(types.isType(() => true, "function")).toBeTruthy()
|
||||
expect(types.isType([], "array")).toBeTruthy()
|
||||
expect(types.isType(new Uint8Array([]), "uint8array")).toBeTruthy()
|
||||
expect(types.isType({}, "object")).toBeTruthy()
|
||||
expect(types.isType(BigInt(1), "bigint")).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the value type is not the one expected or is not supported", () => {
|
||||
expect(types.isType("string", "number")).toBeFalsy()
|
||||
expect(types.isType(1, "string")).toBeFalsy()
|
||||
expect(types.isType(1, "function")).toBeFalsy()
|
||||
expect(types.isType(1, "array")).toBeFalsy()
|
||||
expect(types.isType(1, "uint8array")).toBeFalsy()
|
||||
expect(types.isType(1, "object")).toBeFalsy()
|
||||
expect(types.isType(1, "bigint")).toBeFalsy()
|
||||
expect(types.isType(1, "type" as any)).toBeFalsy()
|
||||
})
|
||||
|
||||
it("Should return true if the type is supported", () => {
|
||||
expect(types.isSupportedType("number")).toBeTruthy()
|
||||
})
|
||||
|
||||
it("Should return false if the type is not supported", () => {
|
||||
expect(types.isSupportedType("type")).toBeFalsy()
|
||||
describe("# supportedNetworks", () => {
|
||||
it("Should be a list of networks supported by Semaphore", () => {
|
||||
expect(supportedNetworks).toBeInstanceOf(Array)
|
||||
expect(typeof supportedNetworks[0]).toBe("string")
|
||||
})
|
||||
})
|
||||
|
||||
describe("# errors", () => {
|
||||
it("Should throw an error if the parameter is not defined", () => {
|
||||
const fun = () => errors.requireDefined(undefined as any, "parameter")
|
||||
describe("# decodeMessage", () => {
|
||||
it("Should decode a text message previously encoded to 32-byte bigint", () => {
|
||||
const message = "Hello World"
|
||||
const encodedMessage = toBigInt(encodeBytes32String(message))
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not defined")
|
||||
})
|
||||
const decodedMessage = decodeMessage(encodedMessage)
|
||||
|
||||
it("Should not throw an error if the parameter is defined", () => {
|
||||
const fun = () => errors.requireDefined(1, "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not a number", () => {
|
||||
const fun = () => errors.requireNumber("euo" as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not a number")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is a number", () => {
|
||||
const fun = () => errors.requireNumber(1, "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not a string", () => {
|
||||
const fun = () => errors.requireString(1 as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not a string")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is a string", () => {
|
||||
const fun = () => errors.requireString("string", "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not an array", () => {
|
||||
const fun = () => errors.requireArray(1 as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not an array")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is an array", () => {
|
||||
const fun = () => errors.requireArray([], "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not a uint8array", () => {
|
||||
const fun = () => errors.requireUint8Array([] as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not a Uint8Array")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is a uint8array", () => {
|
||||
const fun = () => errors.requireUint8Array(new Uint8Array([]), "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not a function", () => {
|
||||
const fun = () => errors.requireFunction(1 as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not a function")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is a function", () => {
|
||||
const fun = () => errors.requireFunction(() => true, "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not an object", () => {
|
||||
const fun = () => errors.requireObject(1 as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not an object")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is an object", () => {
|
||||
const fun = () => errors.requireObject({}, "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is not a bigint", () => {
|
||||
const fun = () => errors.requireBigInt(1 as any, "parameter")
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is not a bigint")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is a bigint", () => {
|
||||
const fun = () => errors.requireBigInt(BigInt(1), "parameter")
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter is neither a function nor a number", () => {
|
||||
const fun = () => errors.requireTypes("string", "parameter", ["function", "number"])
|
||||
|
||||
expect(fun).toThrow("Parameter 'parameter' is none of the following types: function, number")
|
||||
})
|
||||
|
||||
it("Should not throw an error if the parameter is either a string or an array", () => {
|
||||
const fun = () => errors.requireTypes("string", "parameter", ["string", "array"])
|
||||
|
||||
expect(fun).not.toThrow()
|
||||
})
|
||||
|
||||
it("Should throw an error if the parameter types are not supported", () => {
|
||||
const fun = () => errors.requireTypes("string", "parameter", ["string", "type" as any])
|
||||
|
||||
expect(fun).toThrow("Type 'type' is not supported")
|
||||
expect(decodedMessage).toBe(message)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
44
yarn.lock
44
yarn.lock
@@ -8554,6 +8554,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@rollup/plugin-typescript": "npm:^11.1.6"
|
||||
"@semaphore-protocol/data": "npm:4.0.0-beta.2"
|
||||
"@semaphore-protocol/utils": "npm:4.0.0-beta.2"
|
||||
"@types/figlet": "npm:^1.5.8"
|
||||
"@types/inquirer": "npm:^9.0.7"
|
||||
"@types/pacote": "npm:^11.1.8"
|
||||
@@ -8665,7 +8666,7 @@ __metadata:
|
||||
"@rollup/plugin-node-resolve": "npm:^15.2.3"
|
||||
"@rollup/plugin-typescript": "npm:^11.1.6"
|
||||
"@zk-kit/baby-jubjub": "npm:0.2.0"
|
||||
"@zk-kit/eddsa-poseidon": "npm:0.6.0"
|
||||
"@zk-kit/eddsa-poseidon": "npm:0.7.0"
|
||||
"@zk-kit/utils": "npm:0.6.0"
|
||||
poseidon-lite: "npm:0.2.0"
|
||||
rimraf: "npm:^5.0.5"
|
||||
@@ -8701,6 +8702,7 @@ __metadata:
|
||||
resolution: "@semaphore-protocol/utils@workspace:packages/utils"
|
||||
dependencies:
|
||||
"@rollup/plugin-typescript": "npm:^11.1.6"
|
||||
ethers: "npm:^6.11.1"
|
||||
rimraf: "npm:^5.0.5"
|
||||
rollup: "npm:^4.12.0"
|
||||
rollup-plugin-cleanup: "npm:^3.2.1"
|
||||
@@ -10924,6 +10926,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@zk-kit/baby-jubjub@npm:0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "@zk-kit/baby-jubjub@npm:0.3.0"
|
||||
dependencies:
|
||||
"@zk-kit/utils": "npm:0.6.0"
|
||||
checksum: 10/a5b6f80e277c90be6874f60632cb3818ac3267434c52173474bc475798237e0c0fee92522a434cb2cb8b512b3246d5fb41ae38b117aeeb814b62f57875cfc6d9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@zk-kit/circuits@npm:0.2.4":
|
||||
version: 0.2.4
|
||||
resolution: "@zk-kit/circuits@npm:0.2.4"
|
||||
@@ -10943,6 +10954,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@zk-kit/eddsa-poseidon@npm:0.7.0":
|
||||
version: 0.7.0
|
||||
resolution: "@zk-kit/eddsa-poseidon@npm:0.7.0"
|
||||
dependencies:
|
||||
"@zk-kit/baby-jubjub": "npm:0.3.0"
|
||||
"@zk-kit/utils": "npm:0.6.0"
|
||||
buffer: "npm:6.0.3"
|
||||
checksum: 10/25bce37fee4c8fc273de603275e0555908c14be45ee9380b0ae5a60455b05dddf9aebd54dbbb0946af394dab8533f71695edfc5557b0f264c6ffa71e78eccac2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@zk-kit/imt.sol@npm:2.0.0-beta.5, @zk-kit/imt.sol@npm:^2.0.0-beta.5":
|
||||
version: 2.0.0-beta.5
|
||||
resolution: "@zk-kit/imt.sol@npm:2.0.0-beta.5"
|
||||
@@ -12881,6 +12903,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer@npm:6.0.3, buffer@npm:^6.0.1, buffer@npm:^6.0.3":
|
||||
version: 6.0.3
|
||||
resolution: "buffer@npm:6.0.3"
|
||||
dependencies:
|
||||
base64-js: "npm:^1.3.1"
|
||||
ieee754: "npm:^1.2.1"
|
||||
checksum: 10/b6bc68237ebf29bdacae48ce60e5e28fc53ae886301f2ad9496618efac49427ed79096750033e7eab1897a4f26ae374ace49106a5758f38fb70c78c9fda2c3b1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer@npm:^5.2.1, buffer@npm:^5.5.0":
|
||||
version: 5.7.1
|
||||
resolution: "buffer@npm:5.7.1"
|
||||
@@ -12891,16 +12923,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer@npm:^6.0.1, buffer@npm:^6.0.3":
|
||||
version: 6.0.3
|
||||
resolution: "buffer@npm:6.0.3"
|
||||
dependencies:
|
||||
base64-js: "npm:^1.3.1"
|
||||
ieee754: "npm:^1.2.1"
|
||||
checksum: 10/b6bc68237ebf29bdacae48ce60e5e28fc53ae886301f2ad9496618efac49427ed79096750033e7eab1897a4f26ae374ace49106a5758f38fb70c78c9fda2c3b1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"builtin-modules@npm:^3.1.0, builtin-modules@npm:^3.3.0":
|
||||
version: 3.3.0
|
||||
resolution: "builtin-modules@npm:3.3.0"
|
||||
|
||||
Reference in New Issue
Block a user