npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pvium/p2id-verifier

v1.1.1

Published

Pvium's off-chain verifier for P2ID identity attestations (Noir/UltraHonk zero-knowledge proofs)

Readme

@pvium/p2id-verifier

Pvium's implementation for verifying identity attestations. It imports @pvium/p2id-core for the protocol identity types and hashing rules, then checks the attestation's zero-knowledge proof locally using a bundled circuit verification key and configured trusted signing keys. p2id-core is installed automatically as this package's runtime dependency.

Learn more about P2ID in the P2ID protocol specification.

Install

yarn add @pvium/p2id-verifier

Requires Node.js 20+.

Quick start

import { IdentityType } from '@pvium/p2id-core';
import { verifyIdentity, AttestationSigner, shutdown } from '@pvium/p2id-verifier';

const result = await verifyIdentity({
  attestation,                          // proof, public inputs and wallet
  signer: AttestationSigner.Production, // trusted Privy signing keys
  identityType: IdentityType.Email,     // identity type from the original request
  identityValue: '[email protected]',      // identity value from the original request
});

if (result.valid) {
  console.log(result.wallet);   // wallet linked to the email in the signed token
  console.log(result.issuedAt); // token issue time, in Unix seconds
} else {
  console.log(result.reason);
}

await shutdown(); // release the backend after verification is complete

Pass the identity type and value from the original request. Verification checks these values and the attestation's wallet against the proof.

Obtain an attestation

JSON representation:

{
  "proof": "<base64>",
  "publicInputs": "<base64>",
  "wallet": "0xA01b6E60D51eDB3fEB9f86a62b846f4F90070f98",
  "circuitVersion": 1
}

Pvium API or SDK: recipient resolution can return an attestation summary. Fetch the full attestation and pass it to verifyIdentity (see With the Pvium SDK).

Self-hosted prover: request an attestation from the prover service:

curl -s https://your-prover/attestations \
  -H "authorization: Bearer $AUTH_TOKEN" -H 'content-type: application/json' \
  -d '{ "identityType": "email", "identityValue": "[email protected]",
        "wallet": "0xA01b6E60D51eDB3fEB9f86a62b846f4F90070f98", "jwt": "<Privy identity token>" }'

Pass the response to verifyIdentity with signer set to your Privy app's JWKS URL.

Reading the result

| result | Meaning | | --- | --- | | { valid: true, wallet, issuedAt, circuitVersion } | The signed token links the requested identity and wallet. issuedAt is the token's issue time; circuitVersion is the circuit whose verification key accepted the proof. | | reason: 'identity value mismatch' / 'identity type mismatch' | The public inputs do not match the requested identity. | | reason: 'wallet mismatch' | The wallet does not match the public inputs. | | reason: 'attestation carries no wallet' | The public inputs contain no wallet commitment. | | reason: 'not signed by a trusted key' | The signing key is not accepted by the configured signer. | | reason: 'invalid proof' | The proof does not verify. | | reason: 'attestation is for circuit version N; …' or '… circuit build …' | The declared circuit version or verification-key hash is not one this entry point verifies (see Versioning). | | reason: 'malformed attestation: …' | The public inputs could not be decoded. | | reason: 'unknown identity type "…"' / 'unrecognised signer: …' | The identity type or signer argument is unsupported. |

These failures return { valid: false, reason }. Malformed input and backend initialization errors can also throw; callers should handle rejected promises.

The package does not enforce an attestation age. Apply an application-specific limit to issuedAt; this example uses 30 days:

const MAX_AGE = 30 * 24 * 3600;
if (!result.valid) throw new Error(result.reason);
const age = Date.now() / 1000 - result.issuedAt;
if (age < 0 || age > MAX_AGE) throw new Error('attestation outside the accepted time window');

In a server

Using Express 5:

import express from 'express';
import { verifyIdentity, AttestationSigner, IdentityType, shutdown } from '@pvium/p2id-verifier';

const app = express().use(express.json({ limit: '64kb' }));

app.post('/verify-identity', async (req, res) => {
  const { email, attestation } = req.body;
  const check = await verifyIdentity({ attestation, signer: AttestationSigner.Production, identityType: IdentityType.Email, identityValue: email });
  res.status(check.valid ? 200 : 422).json(check);
});

process.on('SIGTERM', () => shutdown());

The Barretenberg backend initializes on first proof verification and is reused. Startup time depends on the runtime and backend. Browser builds use WASM and workers.

Reading a claim without verifying it

decodeClaim reads public inputs without checking the proof. Treat the decoded fields as unverified until verification succeeds.

import { decodeClaim } from '@pvium/p2id-verifier';

const claim = decodeClaim(Buffer.from(attestation.publicInputs, 'base64'));
claim.identityType; // numeric identity type ID
claim.identityHash; // commitment to (type, value)
claim.wallet;       // reported EVM wallet, or null
claim.iat;          // reported token issue time
claim.signer;       // { x, y }: reported P-256 signing key

Trusted signers

signer selects the trusted token-signing keys.

| signer | Use | | --- | --- | | AttestationSigner.Production (or 'production') | Pvium's production Privy keys, pinned in PVIUM_ENVIRONMENTS.production.keys. Unknown keys trigger a lookup against the app's JWKS. | | AttestationSigner.Sandbox (or 'sandbox') | Pvium's sandbox Privy keys, with the same pinning and lookup behavior. | | A JWKS URL string, or { jwksUrl } | Accept P-256 keys from the specified JWKS. | | PEM string or { x, y } | Accept one specified P-256 key. |

PVIUM_ENVIRONMENTS exposes app IDs, JWKS URLs and pinned keys. Pinned keys remain trusted until removed in a package release. JWKS responses are cached for ten minutes.

With the Pvium SDK

Use payout.getAttestation to fetch a proof from a recipient's attestation summary. Verify it against the identity in the original request:

import { PviumSdk } from '@pvium/sdk';
import { verifyIdentity, AttestationSigner } from '@pvium/p2id-verifier';

const pvium = new PviumSdk({ apiKey: process.env.PVIUM_API_KEY!, environment: 'production' });
const recipient = { identityType: 'email' as const, identityValue: '[email protected]' };
const { data } = await pvium.payout.resolveRecipients(batchId, [recipient]);
const summary = data.resolved[0]?.attestation;
if (!summary) throw new Error('attestation unavailable');

const attestation = await pvium.payout.getAttestation(summary);
const result = await verifyIdentity({
  attestation,
  signer: AttestationSigner.Production,
  identityType: recipient.identityType,
  identityValue: recipient.identityValue,
});
if (!result.valid) throw new Error(result.reason);
// Apply the freshness policy, then use result.wallet as the payment destination.

An absent attestation does not establish an identity-to-wallet binding. Wallet payees do not require one; for identity payees, retry resolution when the proof is available.

Exports

| Export | Purpose | | --- | --- | | verifyIdentity(input) | Verify an identity-to-wallet attestation | | AttestationSigner, PVIUM_ENVIRONMENTS | Signer presets, app IDs, JWKS URLs and pinned keys | | decodeClaim(publicInputs), toPublicInputFields, PUBLIC_INPUT_COUNT | Decode and format public inputs without proof verification | | shutdown() | Release the verification backend | | CIRCUIT_VERSIONS | Every circuit version this release verifies | | CIRCUIT_VERSION, VK_SHA256 | The newest circuit version and its verification-key hash (on /v1, /v2: that entry point's version) | | IdentityType, IdentityTypeName | Identity types re-exported from @pvium/p2id-core |

Proof bytes and public inputs accept Uint8Array or base64 strings. Public inputs also accept an array of hexadecimal fields.

Versioning

Each release bundles the verification key of every circuit version it supports (CIRCUIT_VERSIONS), so one install verifies attestations from all of them. @aztec/bb.js is pinned to the matching Barretenberg version (5.0.0).

The package root accepts any supported version. It selects the verification key from the attestation's circuitVersion, or else its vkHash; with neither, it tries each version, newest first. Preserve both fields when passing attestations: they select the key directly and let a mismatch be reported before proof verification.

To accept a single circuit version only, import its entry point:

import { verifyIdentity } from '@pvium/p2id-verifier/v1'; // circuit version 1 only
import { verifyIdentity as verifyV2 } from '@pvium/p2id-verifier/v2'; // circuit version 2 only

Each entry point has the same API as the root. A new circuit version is added in a new package release, alongside the existing ones.