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

@zkproofport-ai/sdk

v0.1.2

Published

Client SDK for ZKProofport proof generation

Readme

@zkproofport-ai/sdk

Client SDK for ZKProofport zero-knowledge proof generation on Base Mainnet.

Overview

@zkproofport-ai/sdk is a TypeScript SDK for generating privacy-preserving zero-knowledge proofs using Coinbase KYC attestations. Generate a proof with a single function call, or fine-tune each step for custom workflows.

Proofs are generated in trusted execution environments (Nitro Enclaves) with cryptographic attestation. Payment is handled transparently via the x402 protocol using EIP-3009 (no user gas costs).

E2E Encryption (TEE Blind Relay)

All proof inputs are end-to-end encrypted using X25519 ECDH + AES-256-GCM. The ZKProofport server acts as a blind relay — it cannot read your inputs, even during proof generation. Only the TEE (AWS Nitro Enclave) can decrypt.

How it works:

  1. generateProof() requests a 402 payment challenge from the server
  2. The 402 response includes teePublicKey — the TEE's attested X25519 public key (cryptographically bound to the Nitro Enclave via COSE Sign1 attestation)
  3. The SDK generates an ephemeral X25519 keypair, performs ECDH key agreement, and encrypts all circuit inputs with AES-256-GCM
  4. The encrypted payload is sent to the server, which relays it blindly to the TEE
  5. The TEE decrypts, generates the ZK proof, and returns it

This is fully automatic. generateProof() detects teePublicKey in the 402 response and applies E2E encryption when available. No additional configuration or code changes needed.

  • TEE enabled (production): Inputs are E2E encrypted. Server rejects plaintext (PLAINTEXT_REJECTED).
  • TEE disabled (local dev): Inputs are sent in plaintext. No encryption overhead.

Installation

npm install @zkproofport-ai/sdk ethers

Prerequisites

Before using the SDK, you need:

  1. Coinbase account with KYC verification — Complete identity verification on Coinbase

  2. Coinbase KYC EAS attestation on Base — Obtain an attestation via Coinbase Verifications. This creates an on-chain EAS attestation on Base linked to your wallet address.

  3. USDC balance on Base — At least $0.10 per proof. Payment is gasless (EIP-3009 signature, facilitator pays gas).

  4. Attestation wallet private key (required) — The private key of the wallet that holds the EAS attestation. This is always a raw private key because the attestation is tied to a specific address.

  5. Payment wallet (optional) — Wallet with USDC balance for proof payment. Defaults to the attestation wallet. Choose one:

    • Same as attestation wallet — No additional setup. The attestation wallet must hold USDC.

      ⚠️ Privacy risk: Using the attestation wallet for payment exposes your KYC-verified wallet address on-chain in the payment transaction, linking your identity to on-chain activity. Use a separate payment wallet for privacy.

    • Separate private key — A different wallet with USDC balance.
    • CDP MPC wallet — Coinbase Developer Platform managed wallet. Private keys never leave Coinbase's TEE. Get credentials at CDP Portal. Requires additional install:
      npm install @coinbase/agentkit @coinbase/cdp-sdk
      | Credential | Required | Description | |------------|----------|-------------| | CDP_API_KEY_ID | Yes | CDP API key ID | | CDP_API_KEY_SECRET | Yes | CDP API key secret | | CDP_WALLET_SECRET | Yes | CDP wallet encryption secret | | CDP_WALLET_ADDRESS | No | Existing wallet address (creates new if omitted) |

Quick Start

Single Wallet (attestation + payment)

import { generateProof, createConfig, fromPrivateKey, verifyProof } from '@zkproofport-ai/sdk';

const config = createConfig();
const signer = fromPrivateKey(process.env.PRIVATE_KEY);

const result = await generateProof(
  config,
  { attestation: signer },
  { circuit: 'coinbase_kyc', scope: 'my-app' }
);

const verification = await verifyProof(result);
console.log('Valid:', verification.valid);

Separate Payment Wallet

import { generateProof, createConfig, fromPrivateKey, verifyProof } from '@zkproofport-ai/sdk';

const config = createConfig();
const attestationSigner = fromPrivateKey(process.env.ATTESTATION_KEY);
const paymentSigner = fromPrivateKey(process.env.PAYMENT_KEY);

const result = await generateProof(
  config,
  { attestation: attestationSigner, payment: paymentSigner },
  { circuit: 'coinbase_kyc', scope: 'my-app' }
);

const verification = await verifyProof(result);
console.log('Valid:', verification.valid);

With CDP Payment Wallet

import { generateProof, createConfig, fromPrivateKey, CdpWalletSigner, verifyProof } from '@zkproofport-ai/sdk';

const config = createConfig();
const attestationSigner = fromPrivateKey(process.env.ATTESTATION_KEY);
const paymentSigner = new CdpWalletSigner({
  getAddress: () => myWallet.getAddress(),
  signMessage: (msg) => myWallet.signMessage(msg),
  signTypedData: (domain, types, message) => myWallet.signTypedData(domain, types, message),
});

const result = await generateProof(
  config,
  { attestation: attestationSigner, payment: paymentSigner },
  { circuit: 'coinbase_kyc', scope: 'my-app' }
);

const verification = await verifyProof(result);
console.log('Valid:', verification.valid);

External Wallet Adapter

Wrap any external wallet (WalletConnect, MetaMask, etc.) using fromExternalWallet():

import { generateProof, createConfig, fromPrivateKey, fromExternalWallet, verifyProof } from '@zkproofport-ai/sdk';

const config = createConfig();
const attestationSigner = fromPrivateKey(process.env.ATTESTATION_KEY);

// Wrap external wallet (e.g., from WalletConnect modal, Privy, etc.)
const externalWallet = await getWalletFromUI(); // Your wallet integration
const paymentSigner = fromExternalWallet(externalWallet);

const result = await generateProof(
  config,
  { attestation: attestationSigner, payment: paymentSigner },
  { circuit: 'coinbase_kyc', scope: 'my-app' }
);

const verification = await verifyProof(result);
console.log('Valid:', verification.valid);

Configuration

import { createConfig } from '@zkproofport-ai/sdk';

// Mainnet (default) — production use
const config = createConfig();

// Custom server or RPC endpoints
const config = createConfig({
  baseUrl: 'https://ai.zkproofport.app',
  easRpcUrl: 'https://mainnet.base.org',
  easGraphqlUrl: 'https://base.easscan.org/graphql',
});

// Custom x402 facilitator (e.g., for CDP with JWT auth)
const config = createConfig({
  facilitatorUrl: 'https://facilitator.example.com',
  facilitatorHeaders: {
    'Authorization': `Bearer ${process.env.CDP_FACILITATOR_TOKEN}`,
  },
});

Configuration fields:

| Field | Type | Default | Description | |-------|------|---------|-------------| | baseUrl | string | https://ai.zkproofport.app | proofport-ai server URL | | easRpcUrl | string | https://mainnet.base.org | Base Mainnet RPC for EAS attestation queries | | easGraphqlUrl | string | https://base.easscan.org/graphql | EAS GraphQL endpoint for attestation schema queries | | facilitatorUrl | string | https://x402.dexter.cash | x402 payment facilitator URL | | facilitatorHeaders | object | {} | Optional auth headers for custom facilitator (e.g., CDP with JWT) |

Proof Generation

Single-Step Flow

The generateProof() function handles the entire proof generation pipeline: signing, attestation fetching, circuit input preparation, x402 payment, and proof generation.

import { generateProof, createConfig, fromPrivateKey } from '@zkproofport-ai/sdk';
import type { StepResult } from '@zkproofport-ai/sdk';

const config = createConfig();
const attestationSigner = fromPrivateKey(process.env.ATTESTATION_KEY);
const paymentSigner = fromPrivateKey(process.env.PAYMENT_KEY); // optional

const result = await generateProof(
  config,
  {
    attestation: attestationSigner,
    payment: paymentSigner, // uses attestationSigner if not provided
  },
  {
    circuit: 'coinbase_kyc',
    scope: 'my-application',
    // Optional: for country circuit
    // countryList: ['US', 'KR'],
    // isIncluded: true, // true = inclusion list, false = exclusion
  },
  {
    onStep: (step: StepResult) => {
      console.log(`[${step.step}] ${step.name} (${step.durationMs}ms)`);
    },
  }
);

console.log('Proof generated in', result.timing.totalMs, 'ms');
console.log('Proof:', result.proof);
console.log('Public inputs:', result.publicInputs);
console.log('Payment TX:', result.paymentTxHash);

// Attestation present if TEE mode enabled on server
if (result.attestation) {
  console.log('TEE document:', result.attestation.document);
  console.log('Verification:', result.attestation.verification);
}

Proof generation flow:

  1. Sign signal hash with attestation signer
  2. Fetch Coinbase KYC attestation from EAS
  3. Build circuit inputs (Merkle tree, hashes)
  4. Request 402 payment challenge
  5. Auto-detect E2E encryption — if teePublicKey is present in 402 response, encrypt inputs with X25519 ECDH + AES-256-GCM
  6. Sign EIP-3009 TransferWithAuthorization
  7. Submit payment via x402 facilitator
  8. Generate proof in TEE with payment proof (encrypted inputs if TEE enabled)

Result fields:

| Field | Type | Description | |-------|------|-------------| | proof | string | 0x-prefixed proof hex | | publicInputs | string | 0x-prefixed public inputs hex | | proofWithInputs | string | Combined proof + public inputs | | paymentTxHash | string | Transaction hash of x402 payment | | attestation | object | TEE attestation (document, proof_hash, verification) or null | | timing | object | Execution times per step | | verification | object | On-chain verifier info (chainId, address, rpcUrl) |

On-Chain Verification

Automatic Verification

import { verifyProof } from '@zkproofport-ai/sdk';

const verification = await verifyProof(result);

if (verification.valid) {
  console.log('Proof is valid on-chain');
} else {
  console.log('Proof verification failed:', verification.error);
}

Step-by-Step API

For advanced workflows or debugging, use individual step functions instead of generateProof().

import {
  prepareInputs,
  requestChallenge,
  makePayment,
  submitProof,
  computeSignalHash,
  CIRCUIT_NAME_MAP,
  USDC_ADDRESSES,
  EthersWalletSigner,
  createConfig,
} from '@zkproofport-ai/sdk';
import { ethers } from 'ethers';

const config = createConfig();
const circuit = 'coinbase_kyc';
const circuitId = CIRCUIT_NAME_MAP[circuit];
const scope = 'my-app';

// Step 1: Sign signal hash
const attestationWallet = new ethers.Wallet(process.env.ATTESTATION_KEY);
const signalHash = computeSignalHash(attestationWallet.address, scope, circuitId);
const signalHashBytes = ethers.getBytes(ethers.hexlify(signalHash));
const signature = await attestationWallet.signMessage(signalHashBytes);

// Step 2: Prepare circuit inputs
const inputs = await prepareInputs(config, {
  circuitId,
  userAddress: attestationWallet.address,
  userSignature: signature,
  scope,
});

// Step 3: Request payment challenge
const challenge = await requestChallenge(config, circuit, inputs);

// Step 4: Make payment via x402 facilitator
const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');
const paymentWallet = new ethers.Wallet(process.env.PAYMENT_KEY, provider);
const paymentSigner = new EthersWalletSigner(paymentWallet);

const paymentTxHash = await makePayment(paymentSigner, {
  nonce: challenge.nonce,
  recipient: challenge.payment.payTo,
  amount: parseInt(challenge.payment.maxAmountRequired),
  asset: USDC_ADDRESSES['base'],
  network: challenge.payment.network,
  instruction: challenge.payment.description,
});

// Step 5: Submit proof with payment proof
const proofResponse = await submitProof(config, {
  circuit,
  inputs,
  paymentTxHash,
  paymentNonce: challenge.nonce,
});

console.log('Proof:', proofResponse.proof);
console.log('Public inputs:', proofResponse.publicInputs);

Circuits

Coinbase KYC

Proves wallet holder passed Coinbase Know-Your-Customer verification.

const result = await generateProof(config, signers, {
  circuit: 'coinbase_kyc',
  scope: 'my-app', // any string; used to prevent proof replay
});

Coinbase Country

Proves wallet holder's country is (or is not) in a specified list.

const result = await generateProof(config, signers, {
  circuit: 'coinbase_country',
  countryList: ['US', 'KR'],
  isIncluded: true, // true = prove in list, false = prove not in list
  scope: 'my-app',
});

Types Reference

Circuit Types:

type CircuitName = 'coinbase_kyc' | 'coinbase_country';
type CircuitId = 'coinbase_attestation' | 'coinbase_country_attestation';

Configuration:

interface ClientConfig {
  baseUrl: string;
  easRpcUrl?: string;
  easGraphqlUrl?: string;
  facilitatorUrl?: string;           // x402 facilitator URL (default: https://x402.dexter.cash)
  facilitatorHeaders?: Record<string, string>; // Auth headers for custom facilitator
}

Signer:

interface ProofportSigner {
  getAddress(): string | Promise<string>;
  signMessage(message: Uint8Array): Promise<string>;
  signTypedData(domain: {...}, types: {...}, message: {...}): Promise<string>;
  sendTransaction(tx: {...}): Promise<{ hash: string; wait(): Promise<{...}> }>;
}

// Create signer from ethers private key
function fromPrivateKey(key: string, provider?: ethers.Provider): ProofportSigner;

// Create signer from any external wallet (CDP, WalletConnect, Privy, etc.)
class CdpWalletSigner implements ProofportSigner {
  constructor(wallet: {
    getAddress(): string | Promise<string>;
    signMessage(message: Uint8Array | string): Promise<string>;
    signTypedData(domain: Record<string, unknown>, types: Record<string, Array<{ name: string; type: string }>>, message: Record<string, unknown>): Promise<string>;
    sendTransaction?(tx: { to: string; data: string; value?: bigint }): Promise<{ hash: string; wait(): Promise<{ status: number | null }> }>;
  });
}

// Wrap external wallet (WalletConnect, MetaMask, Privy, etc.)
function fromExternalWallet(wallet: {
  address: string | (() => Promise<string>);
  signMessage(message: Uint8Array): Promise<string>;
  signTypedData(domain: any, types: any, message: any): Promise<string>;
  sendTransaction?(tx: any): Promise<{ hash: string; wait(): Promise<any> }>;
}): ProofportSigner;

Proof Parameters:

interface ProofParams {
  circuit: CircuitName;
  scope?: string; // defaults to 'proofport'
  countryList?: string[]; // for coinbase_country only
  isIncluded?: boolean; // for coinbase_country only
}

Proof Result:

interface ProofResult {
  proof: string;
  publicInputs: string;
  proofWithInputs: string;
  paymentTxHash: string;
  attestation: {
    document: string;
    proof_hash: string;
    verification: {
      rootCaValid: boolean;
      chainValid: boolean;
      signatureValid: boolean;
      pcrs: Record<number, string>;
    };
  } | null;
  timing: {
    totalMs: number;
    paymentVerifyMs?: number;
    inputBuildMs?: number;
    proveMs?: number;
  };
  verification: {
    chainId: number;
    verifierAddress: string;
    rpcUrl: string;
  } | null;
}

Callbacks:

interface FlowCallbacks {
  onStep?: (step: StepResult) => void;
}

interface StepResult {
  step: number;
  name: string;
  data: unknown;
  durationMs: number;
}

Payment

Payment is transparent to the application. When generateProof() runs, the user signs an EIP-3009 TransferWithAuthorization message (no gas cost). The signature is sent to the x402 facilitator, which completes the USDC transfer and proves payment to the server.

  • Protocol: x402 (HTTP 402 Payment Required)
  • Method: EIP-3009 TransferWithAuthorization
  • Token: USDC on Base Mainnet
  • Amount: $0.10 per proof
  • Facilitator: https://x402.dexter.cash (default, pays gas)
  • User cost: Only USDC, no ETH for gas
  • Custom facilitator: Use facilitatorUrl + facilitatorHeaders in ClientConfig for alternative facilitators (e.g., CDP with JWT auth)

The payment transaction hash is included in result.paymentTxHash for settlement tracking.

Custom Facilitator (CDP Example)

const config = createConfig({
  facilitatorUrl: 'https://cdp-facilitator.example.com',
  facilitatorHeaders: {
    'Authorization': `Bearer ${process.env.CDP_JWT_TOKEN}`,
  },
});

const result = await generateProof(config, signers, params);

Error Handling

import { generateProof, createConfig, fromPrivateKey } from '@zkproofport-ai/sdk';

try {
  const result = await generateProof(config, signers, params);
} catch (error) {
  if (error instanceof Error) {
    if (error.message.includes('402')) {
      console.error('Payment required or payment failed');
    } else if (error.message.includes('attestation')) {
      console.error('Attestation not found or invalid');
    } else if (error.message.includes('Sumcheck')) {
      console.error('Proof verification failed on-chain');
    } else {
      console.error('Proof generation failed:', error.message);
    }
  }
}

Common errors:

| Error | Cause | Solution | |-------|-------|----------| | Attestation not found | Wallet has no Coinbase KYC attestation | Verify attestation on Base Mainnet via EAS | | 402 Payment Required | x402 payment failed or insufficient USDC | Ensure wallet has USDC balance, check x402 facilitator | | Sumcheck failed | On-chain verification failed | Proof corrupted or verifier contract mismatch | | Transaction failed | User rejected signature | Retry or check wallet |

License

MIT