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

@inco/lightning-js

v1.0.2

Published

TypeScript SDK for building privacy-preserving dapps on Inco Lightning.

Readme

@inco/lightning-js

TypeScript SDK for building privacy-preserving dapps on Inco Lightning. Encrypt values client-side, post ciphertexts to smart contracts for confidential computation, and retrieve attested decryptions — all with post-quantum hybrid encryption (X-Wing KEM).

Installation

npm install @inco/lightning-js
# or
yarn add @inco/lightning-js
# or
bun add @inco/lightning-js

Peer dependency: viem ^2.39.3 is used for Ethereum interactions.

Note: The library has currently only been tested with Webpack and Next.js. If you encounter issues with Rollup or Vite, please open an issue.

Quick Start

A typical workflow has three steps:

  1. Encrypt a value client-side
  2. Submit the ciphertext to a smart contract for confidential computation
  3. Decrypt the result via attested decryption
import { getViemChain, supportedChains, handleTypes } from '@inco/lightning-js';
import { Lightning } from '@inco/lightning-js/lite';
import { createWalletClient } from 'viem';

// 1. Setup
const chainId = supportedChains.baseSepolia;
const zap = await Lightning.baseSepoliaTestnet();
const walletClient = createWalletClient({
  chain: getViemChain(chainId),
  account: /* your account */,
  transport: /* your transport */,
});
const dappAddress = '0x...'; // Your contract address

// 2. Encrypt
const ciphertext = await zap.encrypt(42n, {
  accountAddress: walletClient.account.address,
  dappAddress,
  handleType: handleTypes.euint256,
});

// 3. Submit ciphertext to contract via viem writeContract (not SDK-specific)

// 4. Decrypt the result
const resultHandle = '0x...'; // Retrieved from the contract
const [attestation] = await zap.attestedDecrypt(walletClient, [resultHandle]);
console.log(attestation.plaintext.value);

Package Exports

| Import Path | Description | | --------------------------------- | --------------------------------------------------------------------------------- | | @inco/lightning-js | Core utilities: binary helpers, chain definitions, handle types, viem integration | | @inco/lightning-js/lite | Main SDK: Lightning class, encryption, attested decrypt/compute, session keys | | @inco/lightning-js/encryption | Encryption types, plaintext/ciphertext conversions, scheme constants | | @inco/lightning-js/reencryption | Reencryption types, EIP-712 payload creation | | @inco/lightning-js/abis | Generated smart contract ABIs (Lightning, Verifier) |


API Reference

Lightning Class

Import: import { Lightning } from '@inco/lightning-js/lite'

The primary entry point for all SDK operations. Binds to a specific Inco Lightning deployment and provides encryption, attested decryption, attested compute, and session key management.

Factory Methods

The constructor is private. Use one of the static factory methods. Prefer the network-specific factories — they bind to the latest deployment for that network:

// Connect to the latest deployment on a known network
const zap = await Lightning.baseSepoliaTestnet(); // Base Sepolia testnet
const zap = await Lightning.baseMainnet(); // Base mainnet

// Provide your own RPC endpoint(s) (recommended for production).
// When more than one URL is given, they are wrapped in viem's `fallback()`
// transport for automatic failover.
const zap = await Lightning.baseSepoliaTestnet({
  hostChainRpcUrls: ["https://your-rpc-url"],
});

Both network factories (baseSepoliaTestnet, baseMainnet) accept an optional { hostChainRpcUrls?: readonly string[] } argument.

| Method | Returns | Description | | ---------------------------------------- | -------------------- | ----------------------------------------- | | Lightning.baseSepoliaTestnet(options?) | Promise<Lightning> | Latest deployment on Base Sepolia (84532) | | Lightning.baseMainnet(options?) | Promise<Lightning> | Latest deployment on Base mainnet (8453) |

Local development: to run against a local Anvil + covalidator node, see the quick start guide and tutorials in the Inco docs.

Properties

| Property | Type | Description | | ----------------- | --------- | -------------------------------------------- | | executorAddress | Address | The executor contract address | | chainId | bigint | The host chain ID | | deployment | T | Shallow copy of the deployment configuration |

encrypt(value, context)

Encrypts a plaintext value using the network's public key.

async encrypt<T extends boolean | bigint | number>(
  value: T,
  context: {
    accountAddress: string;  // EOA interacting with the dapp
    dappAddress: string;     // Contract address
    handleType: TeeType;     // Required — the TEE handle type to encrypt as
  }
): Promise<HexString>

Recommended handle type per value type:

| Value Type | Handle Type | Example | | ------------------- | ---------------------- | ------------------------------------------------------------------------- | | boolean | handleTypes.ebool | zap.encrypt(true, { ...ctx, handleType: handleTypes.ebool }) | | bigint / number | handleTypes.euint256 | zap.encrypt(42n, { ...ctx, handleType: handleTypes.euint256 }) | | bigint (address) | handleTypes.euint160 | zap.encrypt(BigInt(addr), { ...ctx, handleType: handleTypes.euint160 }) |

Returns a hex string ciphertext to pass to your contract as bytes.

attestedDecrypt(walletClient, handles, ...)

Requests attested decryption of one or more handles. Only handles approved via e.allow() can be decrypted.

Three calling modes:

import { generateXwingKeypair } from "@inco/lightning-js/lite";

// Mode 1: Plaintext result (auto-generates ephemeral keypair internally)
const attestations = await zap.attestedDecrypt(walletClient, [handle]);
attestations[0].plaintext.value; // The decrypted value

// Mode 2: Reencrypt for a delegate (returns encrypted result)
const encrypted = await zap.attestedDecrypt(walletClient, [handle], {
  reencryptPubKey: delegatePubKey,
});
encrypted[0].encryptedPlaintext.ciphertext.value;

// Mode 3: Reencrypt and decrypt locally
const keypair = await generateXwingKeypair();
const decrypted = await zap.attestedDecrypt(walletClient, [handle], {
  reencryptPubKey: keypair.encodePublicKey(),
  reencryptKeypair: keypair,
});
decrypted[0].plaintext.value;

All modes accept an optional backoffConfig on the trailing opts object for retry tuning:

const attestations = await zap.attestedDecrypt(walletClient, [handle], {
  backoffConfig: {
    maxRetries: 10,
    baseDelayInMs: 1000,
    backoffFactor: 1.5,
  },
});

Return types:

| Mode | Return Type | | ------------------------- | ----------------------------------------------------------------------------------------------------------------- | | Plaintext | DecryptionAttestation[]{ handle, plaintext, covalidatorSignatures } | | Reencrypt | EncryptedDecryptionAttestation[]{ handle, encryptedPlaintext, encryptedSignatures, covalidatorSignatures } | | Reencrypt + local decrypt | DecryptionAttestation[] |

attestedReveal(handles, opts?)

Decrypts publicly revealed handles (those marked with e.reveal()). Does not require a wallet — anyone can call this.

const attestations = await zap.attestedReveal([handle]);
attestations[0].plaintext.value;

Warning: Once e.reveal() is called on-chain, the ciphertext is considered public and can be accessed by anyone. This cannot be undone.

attestedCompute(walletClient, lhsHandle, op, rhsPlaintext, ...)

Performs an off-chain comparison operation on an encrypted handle against a plaintext scalar, returning an attested result.

import { AttestedComputeSupportedOps } from "@inco/lightning-js/lite";

// Plaintext result
const result = await zap.attestedCompute(
  walletClient,
  handle,
  AttestedComputeSupportedOps.Ge,
  700n,
);
console.log(result.plaintext.value); // true or false

Supported operations:

| Operation | Description | | -------------------------------- | --------------------- | | AttestedComputeSupportedOps.Eq | Equal | | AttestedComputeSupportedOps.Ne | Not equal | | AttestedComputeSupportedOps.Ge | Greater than or equal | | AttestedComputeSupportedOps.Gt | Greater than | | AttestedComputeSupportedOps.Le | Less than or equal | | AttestedComputeSupportedOps.Lt | Less than |

Supports the same three calling modes as attestedDecrypt (plaintext, reencrypt, reencrypt + local decrypt).

Session Key Methods

Session keys (allowance vouchers) enable delegated decryption without requiring the data owner's wallet signature for each request.

// Owner grants a session key to a delegate
const voucher = await zap.grantSessionKeyAllowanceVoucher(
  walletClient, // Owner's wallet
  granteeAddress, // Delegate's address
  expiresAt, // Expiration Date
  sessionVerifierAddr, // Session verifier contract
);

// Delegate decrypts using the voucher
const attestations = await zap.attestedDecryptWithVoucher(
  ephemeralAccount,
  voucher,
  [handle],
);

// Delegate computes using the voucher
const result = await zap.attestedComputeWithVoucher(
  ephemeralAccount,
  voucher,
  handle,
  AttestedComputeSupportedOps.Eq,
  42n,
);

// Owner revokes all active vouchers
const txHash = await zap.updateActiveVouchersSessionNonce(walletClient);

| Method | Description | | ------------------------------------------------------------------------------ | ------------------------------------ | | grantSessionKeyAllowanceVoucher(walletClient, grantee, expiresAt, verifier) | Grant a time-limited session key | | grantCustomSessionKeyAllowanceVoucher(walletClient, verifier, sharerArgData) | Grant with custom verifier arguments | | attestedDecryptWithVoucher(account, voucher, handles, opts?) | Decrypt using a session key | | attestedComputeWithVoucher(account, voucher, handle, op, rhs, opts?) | Compute using a session key | | updateActiveVouchersSessionNonce(walletClient) | Revoke all active vouchers |

Static Helpers

// Read network public key from on-chain verifier
const pubkey = await Lightning.getNetworkPubkey(publicClient, executorAddress);

// Get the IncoVerifier contract instance
const verifier = await Lightning.getIncoVerifierContract(
  publicClient,
  executorAddress,
);

// Get covalidator URLs for a deployment
const urls = Lightning.getCovalidatorUrls(deployment, signers);

Core Utilities (@inco/lightning-js)

Chain Support

import {
  supportedChains,
  getSupportedChain,
  getViemChain,
} from "@inco/lightning-js";

// Supported chains
supportedChains.base; // 8453
supportedChains.baseSepolia; // 84532
supportedChains.anvil; // 31337

// Resolve chain from ID, name, or object
const chain = getSupportedChain(84532);
const chain = getSupportedChain("baseSepolia");
const chain = getSupportedChain({ id: 84532 });

// Get viem Chain object
const viemChain = getViemChain(84532);

Handle Types

import {
  handleTypes,
  isTeeType,
  validateHandle,
  getHandleType,
} from "@inco/lightning-js";

// FHE type identifiers
handleTypes.ebool; // 0
handleTypes.euint4; // 1
handleTypes.euint8; // 2
handleTypes.euint16; // 3
handleTypes.euint32; // 4
handleTypes.euint64; // 5
handleTypes.euint128; // 6
handleTypes.euint160; // 7
handleTypes.euint256; // 8
handleTypes.ebytes64; // 9
handleTypes.ebytes128; // 10
handleTypes.ebytes256; // 11

// Validate and inspect handles
validateHandle("0x..."); // throws if malformed
const handleType = getHandleType("0x..."); // extracts the handle type
isTeeType(5); // true (euint64)

Binary Utilities

import {
  bytesToBigInt,
  bigintToBytes,
  bigintToBytes32,
  bytes32ToBigint,
  bytesFromHexString,
  bytesToHex,
  mustBeHex,
  normaliseToHex,
  padLeft,
  asBytes32,
  parseAddress,
  parseHex,
} from "@inco/lightning-js";

// Conversions
bytesToBigInt(new Uint8Array([1, 0])); // 256n
bigintToBytes(42n); // 32-byte Buffer
bigintToBytes32(42n); // '0x000...002a' (Bytes32)

// Hex helpers
mustBeHex("0xdead"); // returns typed Hex, throws if invalid
normaliseToHex("dead"); // '0xdead'
bytesToHex(new Uint8Array()); // '0x'

// Parsing with validation
parseAddress("0x1234...5678"); // validated Address (20 bytes)
parseHex("0xabcd"); // validated HexString
asBytes32("0x00...00"); // validated Bytes32 (32 bytes)

Encryption Module (@inco/lightning-js/encryption)

Types and conversion utilities for plaintexts and ciphertexts.

import {
  // Constants
  encryptionSchemes, // { xwing: 2 }
  supportedTeeTypes, // { euint64: 5, euint160: 7, euint256: 8, ebool: 0 }

  // Conversions
  bigintToPlaintext, // (scheme, type, bigint) => Plaintext
  plaintextToBigint, // (plaintext) => bigint
  plaintextToBytes32, // (plaintext) => Bytes32
  plaintextToBytes, // (plaintext) => Buffer
  bytes32ToPlaintext, // (bytes32, scheme, type) => Plaintext
  bytesToPlaintext, // (bytes, scheme, type) => Plaintext

  // Helpers
  getEncryptionSchemeName, // (scheme) => 'X-Wing'
} from "@inco/lightning-js/encryption";

Key types:

| Type | Description | | ------------------ | -------------------------------------------------------------------------------------- | | Plaintext | { scheme, type, value } — value is bigint for integer types, boolean for ebool | | Ciphertext | { scheme, type, value } — value is a hex string | | EncryptionScheme | Currently only 2 (X-Wing) | | SupportedTeeType | 0, 5, 7, 8 (ebool, euint64, euint160, euint256) |


Deployment Utilities (@inco/lightning-js/lite)

import {
  getActiveLightningDeployment,
  getLightningDeployments,
} from "@inco/lightning-js/lite";

// Get the latest active deployment for a chain
const deployment = getActiveLightningDeployment("baseSepolia");

// Get all deployments for a chain
const deployments = getLightningDeployments(84532);

X-Wing Keypair (@inco/lightning-js/lite)

Generate an ephemeral X-Wing keypair for local reencryption (Mode 3 of attestedDecrypt and attestedCompute):

import {
  generateXwingKeypair,
  type XwingKeypair,
} from "@inco/lightning-js/lite";

const keypair: XwingKeypair = await generateXwingKeypair();

// Pass the public key to the attested call and the keypair for local decryption
const decrypted = await zap.attestedDecrypt(walletClient, [handle], {
  reencryptPubKey: keypair.encodePublicKey(),
  reencryptKeypair: keypair,
});
decrypted[0].plaintext.value;

X-Wing is a post-quantum hybrid KEM combining ML-KEM-768 and X25519. The generated keypair is ephemeral — generate a fresh one per request.


Reencryption Module (@inco/lightning-js/reencryption)

EIP-712 typed data utilities for signing reencryption requests.

import { createEIP712Payload } from "@inco/lightning-js/reencryption";

const payload = createEIP712Payload({
  chainId: 84532n,
  primaryType: "Reencrypt",
  primaryTypeFields: [{ name: "publicKey", type: "bytes" }],
  message: { publicKey: "0x..." },
  domainName: "IncoLite",
  domainVersion: "1",
  verifyingContract: "0x...",
});

Key types:

| Type | Description | | ----------------- | ---------------------------------------------- | | Reencryptor<S> | (args, backoffConfig?) => Promise<Plaintext> | | PubKeyEncodable | { encodePublicKey(): Uint8Array } | | EIP712<Message> | Full EIP-712 typed data payload |


ABIs (@inco/lightning-js/abis)

Generated contract ABIs for direct contract interaction with viem.

import { incoLightningAbi } from "@inco/lightning-js/abis/lightning";
import { incoVerifierAbi } from "@inco/lightning-js/abis/verifier";

Supported Chains

| Chain | Chain ID | Name | | ------------- | -------- | ------------- | | Base | 8453 | base | | Base Sepolia | 84532 | baseSepolia | | Anvil (local) | 31337 | anvil |


BackoffConfig

All attested decrypt/compute methods support optional retry configuration:

type BackoffConfig = {
  maxRetries: number; // Default: 5
  baseDelayInMs: number; // Default: 1000
  backoffFactor: number; // Default: 1.5
  errHandler?: (error: Error, attempt: number) => "stop" | "continue";
};

Only transient errors (timeouts, connection issues, 503s) are retried. Security-critical errors (auth failures, invalid signatures) fail immediately.


Migrating from @inco/js (v0.7.x → v1.0.0)

The package was renamed from @inco/js to @inco/lightning-js (the old package is deprecated on npm), and v1.0.0 ships breaking API changes on top of the rename. The headline change: encryption moved from ECIES to a post-quantum X-Wing scheme, so ciphertexts and reencryption keys produced by v0.7.x are not interoperable with v1.

Step 1 — Update the package

npm uninstall @inco/js && npm install @inco/lightning-js

Update every import specifier, including subpaths:

-import { supportedChains } from '@inco/js';
-import { Lightning } from '@inco/js/lite';
+import { supportedChains } from '@inco/lightning-js';
+import { Lightning } from '@inco/lightning-js/lite';

@inco/js/encryption, @inco/js/reencryption, and @inco/js/abis rename the same way. Note also that the @inco/js/fhevm subpath was removed.

Step 2 — Breaking API changes

| Area | Before (@inco/js v0.7.x) | After (@inco/lightning-js v1.0.0) | | ---------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | Encryption scheme | ECIES (encryptionSchemes.ecies, 1) | post-quantum X-Wing (encryptionSchemes.xwing, 2) — not interoperable | | Reencryption keypair | generateSecp256k1Keypair() (sync), Secp256k1Keypair | await generateXwingKeypair() (async), XwingKeypair | | Attested method extras | positional reencryptPubKey / reencryptKeypair / backoffConfig | a single trailing opts object | | Voucher methods | ephemeralKeypair: Secp256k1Keypair + positional ethClient | ephemeralAccount: PrivateKeyAccount, no ethClient, trailing opts | | RPC config | hostChainRpcUrl?: string | hostChainRpcUrls?: readonly string[] (multiple URLs use viem fallback()) | | Type names | FheType, SupportedFheType, supportedFheTypes | TeeType, SupportedTeeType, supportedTeeTypes | | AllowanceVoucher | — | new required warning: string field (shown by wallets; verifier enforces text) |

Attested methods now take an options object instead of positional arguments:

-await zap.attestedDecrypt(walletClient, handles, reencryptPubKey);
+await zap.attestedDecrypt(walletClient, handles, { reencryptPubKey });

-await zap.attestedDecrypt(walletClient, handles, reencryptPubKey, keypair, backoff);
+await zap.attestedDecrypt(walletClient, handles, {
+  reencryptPubKey,
+  reencryptKeypair: keypair,
+  backoffConfig: backoff,
+});

The voucher variants drop the ethClient argument and take a viem account for the ephemeral key:

-await zap.attestedDecryptWithVoucher(ephemeralKeypair, voucher, ethClient, handles, reencryptPubKey);
+await zap.attestedDecryptWithVoucher(ephemeralAccount, voucher, handles, { reencryptPubKey });

attestedCompute / attestedComputeWithVoucher change the same way, and attestedReveal's trailing backoffConfig moves into the opts object.

New in v1.0.0: Lightning.baseMainnet() and grantCustomSessionKeyAllowanceVoucher().


Further Reading

License

Apache-2.0