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

@cheny56/node-client

v1.0.16

Published

Client library for Quorum blockchain with Post-Quantum Cryptography (PQC) and Zero-Knowledge Proof (ZK) support

Readme

@cheny56/node-client

Client library for Quorum blockchain with Post-Quantum Cryptography (PQC) and Zero-Knowledge Proof (ZK) support.

Features

  • Post-Quantum Cryptography: Support for Dilithium (ML-DSA-65) signatures
  • Hybrid Signatures: Combine ECDSA and PQC for enhanced security
  • Zero-Knowledge Proofs: Support for ZK transactions (Groth16, PLONK, STARK)
  • Transaction Types: Legacy, AccessList, and DynamicFee transactions
  • ERC20 Token Support: Simplified interface for token transfers
  • CommonJS First: Uses require() syntax by default (JavaScript-friendly)

Installation

npm install @cheny56/node-client

Dependencies

  • ethers@^5.7.2 - Ethereum library
  • dilithium-crystals@^1.0.0 - Post-quantum cryptography implementation

Quick Start

Using CommonJS (Default)

const { QuorumProvider, ECDSAWallet, PQCWallet, HybridWallet } = require('@cheny56/node-client');

// Connect to Quorum node
const provider = new QuorumProvider('http://localhost:8545');

// Create ECDSA wallet (synchronous)
const ecdsaWallet = new ECDSAWallet('0x...', provider);

// Create PQC wallet (async - keys are generated asynchronously)
const pqcWallet = new PQCWallet();
await pqcWallet._initPromise; // Wait for keys to be generated

// Or use the static factory method (recommended)
const pqcWallet2 = await PQCWallet.create();

// Create hybrid wallet
const hybridWallet = new HybridWallet(ecdsaWallet, pqcWallet);
const hybridAddress = await hybridWallet.getAddress();

Using ES Modules (Optional)

import { QuorumProvider, ECDSAWallet, PQCWallet } from '@cheny56/node-client';

// Same usage as CommonJS
const provider = new QuorumProvider('http://localhost:8545');
const pqcWallet = await PQCWallet.create();

Wallets

ECDSA Wallet

Standard Ethereum wallet using ECDSA signatures.

const { ECDSAWallet } = require('@cheny56/node-client');

// Create from private key
const wallet = new ECDSAWallet('0x...', provider);

// Get address
console.log(wallet.address);

// Sign message
const signature = await wallet.signMessage('Hello, World!');

PQC Wallet

Post-quantum wallet using Dilithium signatures. Note: Key generation is asynchronous.

const { PQCWallet } = require('@cheny56/node-client');

// Method 1: Create and wait for initialization
const wallet = new PQCWallet();
await wallet._initPromise; // Keys are generated in the background
console.log(wallet.address); // Now available

// Method 2: Use static factory (recommended)
const wallet2 = await PQCWallet.create();
console.log(wallet2.address); // Immediately available

// Method 3: Create from existing keys
const wallet3 = PQCWallet.fromSecretKey(secretKey, publicKey);

// Sign message hash
const hash = new Uint8Array(32); // Your message hash
const signature = await wallet.sign(hash);

// Verify signature
const isValid = await wallet.verify(hash, signature);

// Get keys (async)
const publicKeyHex = await wallet.getPublicKeyHex();
const secretKeyHex = await wallet.getSecretKeyHex();

Important Notes:

  • PQC key generation uses dilithium.keyPair() which is async
  • Keys are generated in the background when you create a new wallet
  • Always await _initPromise or use PQCWallet.create() before accessing keys/address
  • The dilithium-crystals package returns { publicKey, privateKey } - the library maps privateKey to secretKey internally

Hybrid Wallet

Combines ECDSA and PQC signatures for enhanced security.

const { HybridWallet, ECDSAWallet, PQCWallet } = require('@cheny56/node-client');

// Create from ECDSA and PQC wallets
const ecdsaWallet = new ECDSAWallet('0x...');
const pqcWallet = await PQCWallet.create();
const hybridWallet = new HybridWallet(ecdsaWallet, pqcWallet);

// Get hybrid address (async - waits for PQC keys)
const address = await hybridWallet.getAddress();

// Or use static factory
const hybridWallet2 = await HybridWallet.create('0x...'); // ECDSA private key

// Create from existing keys
const hybridWallet3 = HybridWallet.fromKeys(
    ecdsaPrivateKey,
    pqcSecretKey,
    pqcPublicKey
);

Transactions

Legacy Transactions (Type 0)

ECDSA Transaction

const { LegacyTransaction } = require('@cheny56/node-client');

const tx = new LegacyTransaction({
    chainId: 1337,
    nonce: 0,
    gasPrice: ethers.utils.parseUnits('20', 'gwei'),
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
});

const signedTx = await tx.sign(ecdsaWallet);
const txHash = await provider.sendRawTransaction(signedTx);

PQC Transaction

const { PQCLegacyTransaction } = require('@cheny56/node-client');

const tx = new PQCLegacyTransaction({
    chainId: 1337,
    nonce: 0,
    gasPrice: 0n, // 0 if node doesn't charge gas
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
});

// Sign with PQC wallet (async)
await tx.sign(pqcWallet);
const serialized = tx.getHex();
const txHash = await provider.sendRawTransaction(serialized);

Hybrid Transaction

const { HybridLegacyTransaction } = require('@cheny56/node-client');

const tx = new HybridLegacyTransaction({
    chainId: 1337,
    nonce: 0,
    gasPrice: 0n,
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
});

// Sign with both wallets (async)
await tx.sign(ecdsaWallet, pqcWallet);
const serialized = tx.getHex();
const txHash = await provider.sendRawTransaction(serialized);

AccessList Transactions (Type 1)

const { PQCAccessListTransaction } = require('@cheny56/node-client');

const tx = new PQCAccessListTransaction({
    chainId: 1337,
    nonce: 0,
    gasPrice: 0n,
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
    accessList: [],
});

await tx.sign(pqcWallet);
const serialized = tx.getHex();
const txHash = await provider.sendRawTransaction(serialized);

DynamicFee Transactions (Type 2)

const { PQCDynamicFeeTransaction } = require('@cheny56/node-client');

const tx = new PQCDynamicFeeTransaction({
    chainId: 1337,
    nonce: 0,
    maxPriorityFeePerGas: ethers.utils.parseUnits('2', 'gwei'),
    maxFeePerGas: ethers.utils.parseUnits('20', 'gwei'),
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
    accessList: [],
});

await tx.sign(pqcWallet);
const serialized = tx.getHex();
const txHash = await provider.sendRawTransaction(serialized);

ERC20 Tokens

Standard Transfer (ECDSA)

const { ERC20Token } = require('@cheny56/node-client');

const token = new ERC20Token(tokenAddress, provider, ecdsaWallet);

// Transfer tokens
const tx = await token.transfer(recipientAddress, amount, {
    gasPrice: ethers.utils.parseUnits('20', 'gwei'),
    gasLimit: 100000,
});

PQC Token Transfer

const { ERC20Token } = require('@cheny56/node-client');

const token = new ERC20Token(tokenAddress, provider);

// Transfer using PQC wallet (async)
const txHash = await token.transferPQC(
    pqcWallet,
    provider,
    recipientAddress,
    amount,
    {
        chainId: 1337,
        gasPrice: 0n,
        gasLimit: 100000,
    }
);

Hybrid Token Transfer

const { ERC20Token } = require('@cheny56/node-client');

const token = new ERC20Token(tokenAddress, provider);

// Transfer using hybrid wallet (async)
const txHash = await token.transferHybrid(
    hybridWallet,
    provider,
    recipientAddress,
    amount,
    {
        chainId: 1337,
        gasPrice: 0n,
        gasLimit: 100000,
    }
);

Zero-Knowledge Proof Transactions

const { ZKTransaction, ZK_PROOF_SYSTEM } = require('@cheny56/node-client');

const zkTx = new ZKTransaction({
    chainId: 1337,
    nonce: 0,
    gasPrice: 0n,
    gasLimit: 21000,
    to: '0x...',
    value: ethers.utils.parseEther('1.0'),
    zkProofSystem: ZK_PROOF_SYSTEM.GROTH16,
    zkProof: proofBytes,
    zkPublicInputs: publicInputs,
    zkVerificationKeyHash: vkHash,
});

const txHash = await zkTx.send(provider, senderAddress);

Provider

const { QuorumProvider } = require('@cheny56/node-client');

const provider = new QuorumProvider('http://localhost:8545');

// Get block number
const blockNumber = await provider.getBlockNumber();

// Get balance
const balance = await provider.getBalance(address);

// Get transaction count (nonce)
const nonce = await provider.getTransactionCount(address);

// Send raw transaction
const txHash = await provider.sendRawTransaction(signedTxHex);

// Wait for transaction
const receipt = await provider.waitForTransaction(txHash);

Constants

const {
    TX_TYPE,
    PQC_TYPE,
    ZK_PROOF_SYSTEM,
    DEFAULT_CHAIN_ID,
} = require('@cheny56/node-client');

// Transaction types
TX_TYPE.LEGACY        // 0
TX_TYPE.ACCESS_LIST   // 1
TX_TYPE.DYNAMIC_FEE   // 2
TX_TYPE.ZK_PRIVATE   // 4

// PQC types
PQC_TYPE.NONE        // 0
PQC_TYPE.DILITHIUM   // 1

// ZK proof systems
ZK_PROOF_SYSTEM.GROTH16  // 1
ZK_PROOF_SYSTEM.PLONK    // 2
ZK_PROOF_SYSTEM.STARK    // 3

// Default chain ID
DEFAULT_CHAIN_ID  // 1337

Utilities

const {
    derivePQCAddress,
    deriveHybridAddress,
    isValidAddress,
    encodeUint64,
    encodeBigInt,
    encodeSignature,
} = require('@cheny56/node-client');

// Derive PQC address from public key
const address = derivePQCAddress(publicKey);

// Derive hybrid address from ECDSA + PQC public keys
const hybridAddress = deriveHybridAddress(ecdsaPublicKey, pqcPublicKey);

// Validate address
const isValid = isValidAddress('0x...');

// RLP encoding utilities
const nonceHex = encodeUint64(5);
const valueHex = encodeBigInt(ethers.utils.parseEther('1.0'));
const sigHex = encodeSignature('0x...');

Complete Example

const { QuorumProvider, PQCWallet, PQCLegacyTransaction } = require('@cheny56/node-client');
const { ethers } = require('ethers');

async function main() {
    // Connect to node
    const provider = new QuorumProvider('http://localhost:8545');
    
    // Create PQC wallet (async)
    const wallet = await PQCWallet.create();
    console.log('PQC Address:', wallet.address);
    
    // Get nonce
    const nonce = await provider.getTransactionCount(wallet.address, 'pending');
    
    // Create transaction
    const tx = new PQCLegacyTransaction({
        chainId: 1337,
        nonce: nonce,
        gasPrice: 0n, // 0 if node doesn't charge gas
        gasLimit: 21000,
        to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
        value: ethers.utils.parseEther('0.1'),
    });
    
    // Sign transaction (async)
    await tx.sign(wallet);
    const serialized = tx.getHex();
    
    // Send transaction
    const txHash = await provider.sendRawTransaction(serialized);
    console.log('Transaction hash:', txHash);
    
    // Wait for confirmation
    const receipt = await provider.waitForTransaction(txHash);
    console.log('Transaction confirmed in block:', receipt.blockNumber);
}

main().catch(console.error);

API Reference

PQCWallet

Constructor

new PQCWallet(secretKey?, publicKey?)
  • secretKey (optional): Existing secret key (Uint8Array or hex string)
  • publicKey (optional): Existing public key (Uint8Array or hex string)
  • If both are omitted, keys are generated asynchronously

Static Methods

  • PQCWallet.create(): Returns Promise<PQCWallet> - Creates wallet with initialized keys
  • PQCWallet.fromSecretKey(secretKey, publicKey): Creates wallet from existing keys

Instance Methods

  • async sign(hash: Uint8Array): Sign a message hash
  • async verify(hash: Uint8Array, signature: Uint8Array): Verify a signature
  • async getAddress(): Get wallet address (waits for initialization if needed)
  • async getPublicKeyHex(): Get public key as hex string
  • async getSecretKeyHex(): Get secret key as hex string

Properties

  • secretKey: Uint8Array (null until initialized)
  • publicKey: Uint8Array (null until initialized)
  • address: string (null until initialized)
  • _initialized: boolean
  • _initPromise: Promise - Wait for this to ensure keys are generated

Notes

  • CommonJS Default: This library uses CommonJS (require) by default for JavaScript compatibility
  • Async Key Generation: PQC keys are generated asynchronously - always await initialization before use
  • Gas Fees: Set gasPrice to 0n if your Quorum node doesn't charge gas fees
  • RLP Encoding: The library uses custom RLP encoding compatible with Go's RLP implementation
  • Dilithium Package: Uses dilithium-crystals package which returns { publicKey, privateKey } from keyPair()

License

LGPL-3.0