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

@baerae/zkap-aa

v0.1.4

Published

ZKAP Account Abstraction SDK — ERC-4337 smart wallet, passkey, zk-oidc signers.

Readme

@baerae/zkap-aa

npm version CI License: ISC

TypeScript SDK for ZKAP smart wallets — ERC-4337 account abstraction with WebAuthn (Passkey) and ZK-OIDC (Google / Kakao) signing.

Features

  • Passkey signing — WebAuthn / FIDO2 credentials, no seed phrases
  • ZK-OIDC signing — sign with Google or Kakao identity, privacy-preserving via ZK proofs
  • EOA signing — standard private key / ethers.Wallet integration
  • Gas sponsorship — verifying and ERC-20 paymaster support
  • Batch transactions — multiple calls in a single UserOperation
  • Dual build — CommonJS and ESM, works in Node.js and bundlers

Installation

npm install @baerae/zkap-aa

ethers is a peer dependency — install it alongside:

npm install ethers

Requires Node.js >= 18.

Quick Start

Prerequisites: ZKAP wallets are ERC-4337 smart contract wallets. You need a wallet address before you can send UserOps.

  • OAuth flow (Google / Kakao): derive your address with helper.deriveAddress({ aud, sub, chainId }) — see step 3 below.
  • EOA flow (testing): use ZkapCreator to deploy a new wallet with a private key as the master key, or contact the team to provision a testnet wallet.
  • The first UserOp sent to a counterfactual address will automatically deploy the wallet on-chain via initCode.

1. Discover supported chains

import { ChainRegistry } from '@baerae/zkap-aa';

const registry = new ChainRegistry();
const chains = await registry.getSupportedChains();
console.log(chains.map(c => `${c.name} (${c.chainId})`));

2. Send a transaction (EOA signer)

WalletHelper.sendTransaction handles the full UserOp lifecycle in one call:

import {
  ChainRegistry,
  BundlerClient,
  ZkapBundlerProvider,
  WalletHelper,
  AddressKeySigner,
} from '@baerae/zkap-aa';

const CHAIN_ID = 11155111; // use a chainId from getSupportedChains()
const WALLET_ADDRESS = '0xYourZkapWalletAddress';
const PRIVATE_KEY = process.env.PRIVATE_KEY!;

const registry = new ChainRegistry();
const bundlerClient = new BundlerClient(new ZkapBundlerProvider());
const helper = new WalletHelper({ chainRegistry: registry, bundlerClient });

const signer = new AddressKeySigner([PRIVATE_KEY]);

const { userOpHash, receipt } = await helper.sendTransaction({
  sender: WALLET_ADDRESS,
  to: '0xRecipientAddress',
  value: '1000000000000000', // 0.001 ETH in wei
  chainId: CHAIN_ID,
  signer,
});

console.log('Submitted:', userOpHash);
const result = await receipt;
console.log('Confirmed in tx:', result.receipt.transactionHash);

3. Derive a counterfactual wallet address

Before a wallet is deployed, its address is deterministic from the user's identity:

const address = await helper.deriveAddress({
  aud: 'your-google-client-id',
  sub: 'user-subject-from-provider',
  chainId: CHAIN_ID,
});
console.log('Wallet address:', address);

Signers

AddressKeySigner

Signs with one or more EOA private keys. Useful for testing or server-side flows.

import { AddressKeySigner } from '@baerae/zkap-aa';

const signer = new AddressKeySigner([privateKey]);

PasskeySigner

Signs with a WebAuthn credential. Provide a verifyWithPasskey callback that calls navigator.credentials.get and returns the assertion response.

import { PasskeySigner } from '@baerae/zkap-aa';

const signer = new PasskeySigner(
  credentialId,
  async (credentialId, challenge) => {
    const assertion = await navigator.credentials.get({
      publicKey: {
        challenge: Buffer.from(challenge, 'base64url'),
        allowCredentials: [{ type: 'public-key', id: Buffer.from(credentialId, 'base64url') }],
        userVerification: 'required',
      },
    }) as PublicKeyCredential;

    const response = assertion.response as AuthenticatorAssertionResponse;
    return {
      response: {
        signature: Buffer.from(response.signature).toString('base64url'),
        authenticatorData: Buffer.from(response.authenticatorData).toString('base64url'),
        clientDataJSON: Buffer.from(response.clientDataJSON).toString('base64url'),
      },
    };
  }
);

ZkOAuthSigner

Signs using a ZK proof of a Google or Kakao OAuth JWT. The user's identity is never revealed on-chain — the proof shows they hold a valid token without exposing it.

Supported providers: "google" and "kakao" only. Currently zkapK=1 (single-provider).

import { ZkOAuthSigner } from '@baerae/zkap-aa';

const chainConfig = await registry.getChainConfig(CHAIN_ID);

const signer = new ZkOAuthSigner(
  'https://your-proof-server.example.com', // ZK proof server URL (must be HTTPS)
  chainConfig.rpcUrl,
  walletAddress,
  ['google'],                               // socialServices: one entry per slot
  [async (msgHash) => fetchIdToken()],      // idTokenGenerators: one per provider
  chainConfig.contracts.poseidonMerkleTreeDirectory,
  1,  // zkapK: proof threshold (must be 1)
  1   // zkapN: number of providers
);

// Prepare the ZK proof before signing
await signer.prepareIdToken(msgHash);

WalletHelper API

WalletHelper is the recommended high-level interface.

const helper = new WalletHelper({ chainRegistry, bundlerClient });

| Method | Description | |--------|-------------| | deriveAddress({ aud, sub, chainId }) | Counterfactual address from OAuth identity | | sendTransaction({ sender, to, value, data?, signer, chainId }) | Single-call UserOp | | sendBatchTransaction({ sender, transactions, signer, chainId }) | Batch UserOp | | WalletHelper.computeSalt(aud, sub) | Raw keccak256 salt for address derivation |

Both send methods return { userOpHash: string; receipt: Promise<UserOpReceipt> }.

Low-level: ZkapBuilder

For direct control over UserOperation construction:

import { ZkapBuilder, BundlerClient, ZkapBundlerProvider } from '@baerae/zkap-aa';

const chainConfig = await registry.getChainConfig(CHAIN_ID);

const builder = new ZkapBuilder({
  chainId: CHAIN_ID,
  entryPoint: chainConfig.entryPoint,
  enUrl: chainConfig.rpcUrl,
});

builder
  .setSender(walletAddress)
  .setExecuteCallData(to, value, data, signer.keyTypes);

await builder.autoFillUserOp(); // estimates gas, sets nonce

const userOpHash = builder.getUserOpHash();
const signatures = await signer.signUserOpHash(userOpHash);
builder.setSignature([0], signatures);

const packedUserOp = builder.getPackedUserOp();
const bundlerClient = new BundlerClient(new ZkapBundlerProvider());
const submittedHash = await bundlerClient.submitUserOp(packedUserOp, chainConfig.entryPoint);
const receipt = await bundlerClient.waitForReceipt(submittedHash);

Gas Sponsorship (Paymaster)

Pass a paymaster config to ZkapBuilder to sponsor gas or accept ERC-20 payment:

import { ZkapBuilder, PaymasterMode } from '@baerae/zkap-aa';

const builder = new ZkapBuilder({
  chainId: CHAIN_ID,
  entryPoint: chainConfig.entryPoint,
  enUrl: chainConfig.rpcUrl,
  paymaster: {
    serverUrl: 'https://paymaster.example.com',
    paymasterAddress: '0xPaymasterContractAddress',
    chainId: CHAIN_ID,
    mode: PaymasterMode.VERIFYING, // or PaymasterMode.ERC20
    // tokenAddress: '0x...'       // required for ERC20 mode
  },
});

Chain Registry

ChainRegistry fetches contract addresses, RPC URLs, and bundler endpoints from the ZKAP API (https://api.zkap.app). Results are cached for 5 minutes by default.

import { ChainRegistry } from '@baerae/zkap-aa';

// Default API endpoint
const registry = new ChainRegistry();

// Custom API endpoint or cache TTL
const registry = new ChainRegistry({
  apiUrl: 'https://your-api.example.com',
  cacheTtlMs: 60_000,
});

const chainConfig = await registry.getChainConfig(chainId);
// { chainId, name, rpcUrl, entryPoint, zkapFactory, bundlerUrl, contracts }

registry.refresh(); // clear cache and force re-fetch

Bundler Providers

import { ZkapBundlerProvider, Erc4337BundlerProvider, BundlerClient } from '@baerae/zkap-aa';

// ZKAP hosted bundler (default: https://bundler.zkap.app)
const provider = new ZkapBundlerProvider();
const provider = new ZkapBundlerProvider({ baseUrl: 'https://your-bundler.example.com' });

// Any ERC-4337 compatible bundler RPC endpoint
const provider = new Erc4337BundlerProvider({ rpcUrl: 'https://bundler.example.com/rpc' });

const bundlerClient = new BundlerClient(provider);

Contributing

See CONTRIBUTING.md.

Security

To report a vulnerability, see SECURITY.md.

License

ISC — © 2026 baerae-zkap