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

@prvtlabs/prvttools

v1.0.0

Published

SDK for Solana ZK Programs — Privacy-preserving VRF, Lottery, Airdrop, Dice, Voting & Payments on Solana. Zero deployment, AI-native, composable via CPI.

Readme

@prvtlabs/prvttools

AI-Powered Zero-Knowledge DApps on Solana — Build privacy-preserving decentralized applications without deploying a single smart contract.

npm version License: MIT


What is this?

prvt.tools provides 6 pre-deployed zero-knowledge programs on Solana that developers and AI agents can call directly — no Anchor build, no deploy keys, no upgrade authority. Just build and sign transactions.

This SDK gives you TypeScript classes, utilities, and types to interact with all 6 programs.

Why use this?

  • Zero Deployment — Use shared on-chain ZK programs out of the box. No Rust, no Anchor CLI.
  • AI-Native — AI agents read IDL definitions and generate transaction instructions automatically.
  • One Program, Unlimited Apps — Every project uses the same on-chain programs with unique PDA-isolated state.
  • Privacy by Default — Sensitive data stays off-chain, only zero-knowledge proofs go on-chain.
  • Composable via CPI — Any Solana program can cross-program invoke these ZK primitives.

Programs

All programs are live on Solana Devnet and verified on-chain.

| Program | Description | Program ID | Test Results | |---------|-------------|------------|--------------| | ZK Dice | Provably fair casino — dice, coin flip, custom range | 4zsyst6Sf6MymUCJthR65eSgWEahbJJ5nd2zRCbJ8Yh6 | 7/7 PASS | | ZK Lottery | Provably fair lottery with committed randomness | BqB7rvCAeU8ig3AxUZsZBgfK2ZTiSHr6p67ez5z8FuhK | 7/7 PASS | | ZK Airdrop | Merkle-proof token distribution with nullifiers | 4X1UaqFrJXjoZg8eGt866yytQB5BYZktANi2KDFi9RZ5 | 7/7 PASS | | ZK Voting | Anonymous commit-reveal voting with Merkle eligibility | 3C5NdnjyEkwGu5mqJhh9t21b4PVCufiYgQZhqxd5sp4g | 4/6 PASS | | ZK Payments | Private payments, escrow, invoices with range proofs | 7gN9AJYbjNtc7wkeRzU2BeUQLNfoA99DnmPyeyRMvFFg | 8/9 PASS | | ZK VRF | Verifiable random function for tamper-proof randomness | 4QLdhkY3TT2RBxv39jCYFpetiwZxSw6dkXKFfTbkfm1B | 5/7 PASS |

Overall: 38/43 tests passing (88%)


Installation

npm install @prvtlabs/prvttools
yarn add @prvtlabs/prvttools
pnpm add @prvtlabs/prvttools

Peer Dependencies

npm install @coral-xyz/anchor @solana/web3.js

Quick Start

import { Connection, Keypair } from '@solana/web3.js';
import * as anchor from '@coral-xyz/anchor';
import {
  ZkVrf, ZkLottery, ZkDice,
  ZkAirdrop, ZkVoting, ZkPayments
} from '@prvtlabs/prvttools';

// Setup provider
const connection = new Connection('https://api.devnet.solana.com');
const wallet = new anchor.Wallet(Keypair.generate());
const provider = new anchor.AnchorProvider(connection, wallet, {});

// Initialize any program — no deployment needed
const vrf = new ZkVrf(provider);
const lottery = new ZkLottery(provider);
const dice = new ZkDice(provider);
const airdrop = new ZkAirdrop(provider);
const voting = new ZkVoting(provider);
const payments = new ZkPayments(provider);

Program Guides

ZK Dice — Provably Fair Casino Games

Game types: dice6, dice100, coinFlip, custom range. Uses commit-reveal: house commits a server seed hash, player bets, house reveals seed, bet is resolved deterministically.

Instructions: initialize, commitServerSeed, placeBet, revealServerSeed, resolveBet, depositHouseFunds, withdrawHouseFunds, updateConfig

import { ZkDice, generateSalt, sha256 } from '@prvtlabs/prvttools';

const dice = new ZkDice(provider);

// House setup
const houseEdgeBps = 250; // 2.5%
const maxBet = BigInt(0.1 * 1e9);
const minBet = BigInt(0.001 * 1e9);
await dice.initialize(houseEdgeBps, maxBet, minBet, authority.publicKey);
await dice.depositHouseFunds(BigInt(1 * 1e9), depositor.publicKey);

// Commit server seed
const seedId = BigInt(Date.now());
const serverSeed = generateSalt();
const commitment = sha256(serverSeed);
await dice.commitServerSeed(seedId, commitment, house.publicKey);

// Player places bet
await dice.placeBet(
  BigInt(0.01 * 1e9),  // bet amount
  generateSalt(),       // client seed
  { dice6: {} },        // game type
  4,                    // prediction: roll 4+ to win
  seedId,
  player.publicKey
);

// Reveal and resolve
await dice.revealServerSeed(seedId, serverSeed, house.publicKey);
await dice.resolveBet(seedId, player.publicKey);

ZK Lottery — Provably Fair Lottery System

Create lottery rounds, users buy tickets, winner is revealed using committed randomness. Prize pool distributed to winner minus platform fee.

Instructions: initialize, createLottery, buyTickets, revealWinner, claimPrize, cancelLottery, updateConfig

import { ZkLottery } from '@prvtlabs/prvttools';

const lottery = new ZkLottery(provider);

await lottery.initialize(authority.publicKey);

// Create lottery
const lotteryId = BigInt(Date.now());
await lottery.createLottery(
  lotteryId,
  BigInt(0.01 * 1e9),  // ticket price
  100,                   // max tickets
  BigInt(currentSlot + 1000),  // end slot
  creator.publicKey
);

// Buy tickets
await lottery.buyTickets(lotteryId, 5, buyer.publicKey);

// Draw winner & claim
await lottery.draw(lotteryId, vrfRoundId, authority.publicKey);
await lottery.claimPrize(lotteryId, winner.publicKey);

ZK Airdrop — Privacy-Preserving Token Distribution

Distribute tokens using Merkle tree proofs. Users prove eligibility without revealing the full recipient list. Nullifiers prevent double-claiming.

Instructions: createAirdrop, claim, closeAirdrop, pauseAirdrop, resumeAirdrop, updateMerkleRoot, addFunds

import { ZkAirdrop, buildMerkleTree, computeMerkleLeaf, generateSalt } from '@prvtlabs/prvttools';
import { PublicKey } from '@solana/web3.js';

const airdrop = new ZkAirdrop(provider);

// Build Merkle tree from eligible addresses
const leaves = eligibleAddresses.map(addr => computeMerkleLeaf(addr));
const { root, proofs } = buildMerkleTree(leaves);

// Create airdrop campaign
const airdropId = BigInt(Date.now());
await airdrop.createAirdrop(
  airdropId, root,
  BigInt(100 * 1e9),                  // amount per recipient
  BigInt(eligibleAddresses.length),    // total recipients
  tokenMint,
  BigInt(currentSlot + 50000),         // expiry
  authority.publicKey
);

// Eligible user claims
const userIndex = eligibleAddresses.findIndex(a => a.equals(user.publicKey));
const proof = proofs.get(userIndex)!;
await airdrop.claim(airdropId, proof, BigInt(userIndex), generateSalt(), user.publicKey);

ZK Voting — Anonymous Voting System

Two-phase commit-reveal voting. Phase 1: voters commit encrypted vote hash. Phase 2: voters reveal their vote. Nullifiers prevent double-voting. Merkle root gates voter eligibility.

Instructions: initialize, createProposal, commitVote, revealVote, finalizeProposal, cancelProposal, updateVoterRoot

Lifecycle: Pending → Active → Revealing → Finalized (or Cancelled)

import { ZkVoting, createVoteCommitment, generateSalt, generateNullifier,
         buildMerkleTree, computeMerkleLeaf } from '@prvtlabs/prvttools';

const voting = new ZkVoting(provider);
await voting.initialize(authority.publicKey);

// Build voter eligibility tree
const leaves = eligibleVoters.map(v => computeMerkleLeaf(v));
const { root, proofs } = buildMerkleTree(leaves);

// Create proposal
const proposalId = BigInt(Date.now());
await voting.createProposal(
  proposalId, "Treasury Allocation",
  "How should we allocate Q1 funds?",
  ["Development", "Marketing", "Community", "Reserve"],
  root,
  BigInt(currentSlot + 100),    // voting start
  BigInt(currentSlot + 5000),   // voting end
  BigInt(currentSlot + 10000),  // reveal end
  creator.publicKey
);

// Commit vote (Phase 1)
const salt = generateSalt();
const commitment = createVoteCommitment(0, salt);  // vote for option 0
const nullifier = generateNullifier(voter.publicKey, proposalId);
const proof = proofs.get(voterIndex)!;
await voting.commitVote(proposalId, commitment, proof, BigInt(voterIndex), nullifier, voter.publicKey);

// Reveal vote (Phase 2)
await voting.revealVote(proposalId, 0, salt, voter.publicKey);

// Finalize
await voting.finalizeProposal(proposalId, authority.publicKey);

ZK Payments — Private Payment Verification & Escrow

Commit-reveal payments, range proofs, escrow with hidden amounts, and invoicing. Payment amounts stay private until revealed. Escrow supports dispute resolution.

Instructions: initialize, createPaymentCommitment, revealPayment, executePayment, createRangeAttestation, createEscrow, depositToEscrow, releaseEscrow, refundEscrow, createInvoice, payInvoice

Escrow lifecycle: Active → Funded → Released / Refunded / Disputed Invoice lifecycle: Pending → Paid / Cancelled / Overdue

import { ZkPayments, createAmountCommitment, generateSalt, sha256 } from '@prvtlabs/prvttools';

const payments = new ZkPayments(provider);
await payments.initialize(authority.publicKey);

// Private payment with hidden amount
const paymentId = BigInt(Date.now());
const amount = BigInt(0.5 * 1e9);
const salt = generateSalt();
const commitment = createAmountCommitment(amount, salt);

await payments.createPayment(
  paymentId, commitment, recipient.publicKey,
  BigInt(0.1 * 1e9), BigInt(1 * 1e9),    // min/max range
  BigInt(currentSlot + 10000),
  sender.publicKey
);
await payments.revealPayment(paymentId, amount, salt, sender.publicKey);
await payments.executePayment(paymentId, sender.publicKey);

// Escrow with hidden amount
const escrowId = BigInt(Date.now());
const escrowCommitment = createAmountCommitment(BigInt(1 * 1e9), generateSalt());
const conditionHash = sha256(Buffer.from('condition_met'));

await payments.createEscrow(
  escrowId, escrowCommitment, conditionHash,
  arbiter.publicKey, BigInt(currentSlot + 50000),
  depositor.publicKey, beneficiary.publicKey
);
await payments.depositToEscrow(escrowId, BigInt(1 * 1e9), depositor.publicKey);
await payments.releaseEscrow(escrowId, Buffer.from('condition_met'), arbiter.publicKey);

// Invoice system
const invoiceId = BigInt(Date.now());
const invoiceCommitment = createAmountCommitment(BigInt(0.1 * 1e9), generateSalt());
await payments.createInvoice(
  invoiceId, invoiceCommitment, sha256(Buffer.from('Service Payment')),
  BigInt(currentSlot + 10000), issuer.publicKey, payer.publicKey
);
await payments.payInvoice(invoiceId, BigInt(0.1 * 1e9), generateSalt(), payer.publicKey);

ZK VRF — Verifiable Random Function

On-chain verifiable randomness. Operator commits to a seed, users request randomness, operator reveals preimage, request is fulfilled with deterministic random output.

Instructions: initialize, createRound, requestRandomness, reveal, fulfillRequest, closeRound, withdrawFees, updateConfig

import { ZkVrf, generateSalt, sha256 } from '@prvtlabs/prvttools';

const vrf = new ZkVrf(provider);
await vrf.initialize(authority.publicKey);

// Operator creates round
const roundId = BigInt(Date.now());
await vrf.createRound(roundId, authority.publicKey);

// User requests randomness
const clientSeed = generateSalt();
await vrf.requestRandomness(roundId, clientSeed, requester.publicKey);

// Operator reveals and fulfills
const serverSeed = generateSalt();
await vrf.reveal(roundId, serverSeed, oracle.publicKey);
await vrf.fulfillRequest(roundId, requester.publicKey);

Utility Functions

Cryptographic Utilities

import {
  sha256,                  // SHA256 hash
  generateSalt,            // Random 32-byte salt
  createCommitment,        // Generic commit: sha256(value + salt)
  createAmountCommitment,  // Amount commit for payments
  createVoteCommitment,    // Vote commit for voting
  generateNullifier,       // Nullifier to prevent double-actions
} from '@prvtlabs/prvttools';

const salt = generateSalt();              // 32-byte Buffer
const hash = sha256(Buffer.from('data')); // 32-byte hash
const commitment = createCommitment(value, salt);

Merkle Tree Utilities

import {
  computeMerkleLeaf,   // Compute leaf from PublicKey
  computeMerkleNode,   // Compute parent from two children
  buildMerkleTree,     // Build tree, returns { root, proofs }
  verifyMerkleProof,   // Verify a proof against root
} from '@prvtlabs/prvttools';

const leaves = addresses.map(addr => computeMerkleLeaf(addr));
const { root, proofs } = buildMerkleTree(leaves);
const isValid = verifyMerkleProof(leaf, proof, leafIndex, root);

PDA Derivation

Every program uses Program Derived Addresses for state isolation. The SDK provides helpers for all PDAs:

import {
  PROGRAM_IDS,
  // VRF
  getVrfConfigPDA, getVrfRoundPDA, getVrfRequestPDA,
  // Lottery
  getLotteryConfigPDA, getLotteryPDA, getLotteryPoolPDA, getTicketPDA,
  // Airdrop
  getAirdropPDA, getAirdropVaultPDA, getAirdropNullifierPDA,
  // Dice
  getDiceConfigPDA, getHouseVaultPDA, getServerSeedPDA, getBetPDA,
  // Voting
  getVotingConfigPDA, getProposalPDA, getVotePDA, getVoteNullifierPDA,
  // Payments
  getPaymentConfigPDA, getPaymentPDA, getEscrowPDA, getEscrowVaultPDA,
  getInvoicePDA, getAttestationPDA,
} from '@prvtlabs/prvttools';

Types

All TypeScript types are fully exported:

import type {
  // VRF
  VrfConfig, VrfRound, RandomnessRequest,
  // Lottery
  LotteryConfig, Lottery, LotteryTicket, LotteryStatus,
  // Dice
  DiceConfig, ServerSeed, Bet, GameType,
  // Airdrop
  Airdrop, AirdropNullifier, AirdropStatus,
  // Voting
  VotingConfig, Proposal, Vote, ProposalStatus,
  // Payments
  PaymentConfig, PaymentCommitment, Escrow, Invoice,
  PaymentStatus, EscrowStatus, InvoiceStatus,
} from '@prvtlabs/prvttools';

AI Agent Integration

AI agents can build ZK dApps in 3 steps:

  1. Load IDL — Read the JSON IDL for any program (included in idl/ directory)
  2. Derive PDAs — Use program ID + seeds to compute account addresses
  3. Build TX — Construct TransactionInstruction with discriminator + args

No deployment. No Rust. No Anchor CLI. Just transaction construction.

The SDK ships with IDL files for all 6 programs:

  • idl/zk_dice.json
  • idl/zk_lottery.json
  • idl/zk_voting.json
  • idl/zk_airdrop.json
  • idl/zk_payments.json
  • idl/zk_vrf.json

Error Handling

All SDK methods return transaction signatures on success:

try {
  const tx = await dice.placeBet(amount, clientSeed, gameType, prediction, seedId, player);
  console.log('Transaction:', tx);
} catch (error) {
  if (error.message.includes('insufficient funds')) {
    console.error('Not enough SOL');
  } else if (error.message.includes('6001')) {
    console.error('Anchor program error — check error code');
  } else {
    console.error('Transaction failed:', error);
  }
}

Network Configuration

Programs are deployed on Solana Devnet. For custom RPC:

const connection = new Connection('https://your-rpc-endpoint.com', 'confirmed');
const provider = new anchor.AnchorProvider(connection, wallet, {
  commitment: 'confirmed',
  preflightCommitment: 'confirmed',
});

Wallet Connection

Node.js / Backend

import { Connection, Keypair } from '@solana/web3.js';
import * as anchor from '@coral-xyz/anchor';
import { ZkDice } from '@prvtlabs/prvttools';

// Load keypair from file
import fs from 'fs';
const secret = JSON.parse(fs.readFileSync('./keypair.json', 'utf-8'));
const keypair = Keypair.fromSecretKey(Uint8Array.from(secret));

const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
const wallet = new anchor.Wallet(keypair);
const provider = new anchor.AnchorProvider(connection, wallet, {});

const dice = new ZkDice(provider);

React / Next.js (with Wallet Adapter)

npm install @solana/wallet-adapter-react @solana/wallet-adapter-wallets @solana/wallet-adapter-react-ui
import { useAnchorWallet, useConnection } from '@solana/wallet-adapter-react';
import * as anchor from '@coral-xyz/anchor';
import { ZkDice, ZkLottery } from '@prvtlabs/prvttools';

function MyComponent() {
  const { connection } = useConnection();
  const wallet = useAnchorWallet();

  const playDice = async () => {
    if (!wallet) return;
    const provider = new anchor.AnchorProvider(connection, wallet, {});
    const dice = new ZkDice(provider);

    // Now use any SDK method — wallet signs automatically
    await dice.placeBet(
      BigInt(0.01 * 1e9),
      generateSalt(),
      { dice6: {} },
      4,
      seedId,
      wallet.publicKey
    );
  };

  return <button onClick={playDice}>Roll Dice</button>;
}

Wallet Provider Setup (App root)

import { WalletProvider } from '@solana/wallet-adapter-react';
import { ConnectionProvider } from '@solana/wallet-adapter-react';
import { PhantomWalletAdapter, SolflareWalletAdapter } from '@solana/wallet-adapter-wallets';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';

const wallets = [new PhantomWalletAdapter(), new SolflareWalletAdapter()];

function App({ children }) {
  return (
    <ConnectionProvider endpoint="https://api.devnet.solana.com">
      <WalletProvider wallets={wallets} autoConnect>
        <WalletModalProvider>
          {children}
        </WalletModalProvider>
      </WalletProvider>
    </ConnectionProvider>
  );
}

Supported Wallets

Any Solana wallet works — Phantom, Solflare, Backpack, Ledger, Torus, etc. The SDK just needs an AnchorProvider with a connected wallet.


Use Cases

| Use Case | Programs | |----------|----------| | Gaming | ZK Dice + ZK VRF for provably fair games | | Governance | ZK Voting for anonymous DAO proposals | | Token Distribution | ZK Airdrop for private Merkle airdrops | | DeFi | ZK Payments for private escrow & invoicing | | Lotteries & Raffles | ZK Lottery + ZK VRF for fair draws | | Any dApp needing randomness | ZK VRF standalone |


Contributing

Contributions are welcome! Please submit issues and pull requests.


License

MIT