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

@zebec-network/aleo-stream-sdk

v2.0.2

Published

TypeScript client for Zebec payroll streams on Aleo. It wraps the on-chain program (`test_zebec_stream_v3.aleo` on testnet, `zebec_stream_v1.aleo` on mainnet) so a frontend or backend can create, fund, pause, withdraw, auto-withdraw, and cancel token stre

Readme

Zebec Aleo Stream SDK

TypeScript client for Zebec payroll streams on Aleo. It wraps the on-chain program (test_zebec_stream_v3.aleo on testnet, zebec_stream_v1.aleo on mainnet) so a frontend or backend can create, fund, pause, withdraw, auto-withdraw, and cancel token streams without assembling Leo plaintext by hand.

Package: @zebec-network/aleo-stream-sdk

What it does

A stream pays a receiver a fixed amount of an IARC-22 stablecoin (usdcx or usad) linearly over a duration. The sender deposits tokens into the program; the receiver (or a designated withdrawer) pulls the vested portion over time.

The SDK is the off-chain counterpart of that program:

  • Builds and submits the program transitions (create, topup, pause/resume, withdraw, cancel, admin config).
  • Reads public mappings (streams, stream_anchors, stream_configs, per-address registries, token whitelist).
  • Decrypts private records (sender / receiver / withdrawer tickets, token and credits records).
  • Reproduces on-chain BHP256 hashing and Schnorr fee signatures so create-stream fees verify on-chain.
  • Loads one @provablehq/sdk WASM (testnet or mainnet), not both.

It does not ship a wallet. You pass an AleoWallet (Puzzle, a Provable Account + proving client, or your own adapter). The SDK only calls executeTransaction, decrypt, and requestRecords.

Public vs private streams

| | Public | Private | | --- | --- | --- | | Funding | Sender's public token balance (approve + transfer_from_public) | Private token record + Sealance freeze-list Merkle proofs | | Visibility | Stream + StreamAnchor live in public mappings | Tickets are private records; StreamAnchor is still public | | Who acts | Sender / receiver / config withdrawer by address | Same roles, authorized by the matching ticket | | Listing | listPublicStreams(config) | listPrivateStreams() |

Every stream, public or private, has a public anchor: start time, duration, deposited/withdrawn amounts, paused/canceled flags. Follow-on transactions must prove against the current on-chain anchor. A proving service returning accepted is not the same as explorer confirmed / mapping update — wait for confirmation before the next write.

Configs (tenants)

Streams belong to a stream config stored in stream_configs. The config key is a field. Human-readable names such as Stream_Config_001 are hashed off-chain with BHP256 (configNameToField); the program only ever sees the field.

A config records:

  • admin — only this address may updateConfig and setTokenWhitelisted. initializeConfig always sets admin to the executing wallet.
  • feeVault — receives the signed stream fee (paid in the stream token).
  • withdrawer — address allowed to call auto-withdraw.
  • baseFee / platformFee — credits fees used when autoWithdrawable is true.

Tokens must be whitelisted per config before create. On testnet the usual token is test_usdcx_stablecoin.

Signed stream fees

Create-stream requires an admin-signed StreamTokenFee: config, token identifier, fee amount, stream amount, expiry, nonce. streamAmount must equal the stream's amount — it binds the signed fee to one stream size so it can't be replayed against a larger stream. On-chain verification is verify_schnorr(fee_signature, config.admin, BHP256(token_fee)). Use signStreamTokenFee with the admin private key; the signature is a sign1... literal passed into create.

Auto-withdraw

If autoWithdrawable is true, the config withdrawer can pull vested tokens on a fixed withdrawFrequency (must be one of 60, 120, 3600, 43200, 86400, 604800, 1209600, 2592000, 7776000, 15552000, 31536000 seconds). The auto-withdrawal fee in microcredits is platformFee + (duration * baseFee) / frequency.

Requirements

  • Node.js 20+ (ESM). The package is "type": "module".
  • @provablehq/sdk ^0.11.9 (already a dependency).
  • An Aleo account with credits for fees.
  • For public streams: public token balance plus an approve_public allowance to the stream program address.
  • For private streams: unspent token (and, if auto-withdraw is on, credits) records; a record scanner for requestRecords.
  • Network access to an Aleo REST host (default https://api.provable.com/v2) and, if you prove remotely, Provable DPS.

Install

npm install @zebec-network/aleo-stream-sdk
# or
yarn add @zebec-network/aleo-stream-sdk
import {
  Network,
  ZebecStreamService,
  configNameToField,
  signStreamTokenFee,
  randomField,
  loadProvableSdk,
} from "@zebec-network/aleo-stream-sdk";

In a browser, construct the service for a single Network. loadProvableSdk(network) (and ZebecStreamService) dynamically import either @provablehq/sdk/testnet.js or mainnet.js. Do not statically import both, or the app will download two WASM blobs.

Setup

1. Provide a wallet

The service only needs this interface:

interface AleoWallet {
  address: string;
  decrypt: (cipherText: string) => Promise<string>;
  requestRecords: (
    program: string,
    includePlaintext?: boolean,
  ) => Promise<unknown[]>;
  executeTransaction: (options: {
    program: string;
    function: string;
    inputs: string[];
    fee?: number; // microcredits (SDK default 100_000)
    privateFee?: boolean;
    feeRecord?: string;
    imports?: string[];
  }) => Promise<{ transactionId: string }>;
}
  • Frontend: map Puzzle (or similar) connect/decrypt/records/execute onto this shape. Pass program imports through; the service fills IARC-22 nested imports for token dispatch.
  • Backend / scripts: wrap @provablehq/sdk Account + ProgramManager + DPS (submitProvingRequest). See tests/setup.ts for a complete adapter used by e2e (REST host, prover URI, record scanner, API key, consumer id).

priorityFee on service methods is microcredits. If your wallet's proving API expects credits, divide by 1_000_000 in the adapter (the e2e wallet does this).

2. Construct the service

const network = Network.TESTNET; // or Network.MAINNET
const service = await new ZebecStreamService(wallet, {
  network,
  // host: "https://api.provable.com/v2", // default
  // programId: "test_zebec_stream_v3.aleo", // default per network
}).ready();

ready() waits until that network's WASM is loaded. Async methods wait on it automatically; await ready() before reading service.networkClient.

Defaults:

| Network | Program | REST host | | --- | --- | --- | | testnet | test_zebec_stream_v3.aleo | https://api.provable.com/v2 | | mainnet | zebec_stream_v1.aleo | same default, override host if needed |

Explorers: testnet · mainnet. Transaction URL: https://testnet.explorer.provable.com/transaction/<id>.

3. Admin: initialize a config and whitelist a token

Do this once per tenant. The executing wallet becomes admin.

const configName = await configNameToField("Acme_Payroll", network);

const config = {
  configName,
  admin: adminWallet.address,
  feeVault: adminWallet.address,
  withdrawer: adminWallet.address, // auto-withdraw signer
  baseFee: 0,       // credits
  platformFee: 0,   // credits
};

await admin.initializeConfig(config, { priorityFee: 100_000 });

const token = "test_usdcx_stablecoin"; // without .aleo
await admin.setTokenWhitelisted(configName, token, true, {
  priorityFee: 100_000,
});

isTokenWhitelisted(configName, token) and getStreamConfig(configName) are the corresponding reads. updateConfig may only be called by the existing admin.

4. Sign a stream fee and create a stream

Token argument to create methods is "usdcx_stablecoin" or "usad_stablecoin". On testnet the service prefixes test_.

const decimals = 6;
const streamId = `${await randomField(network)}field`;
const now = Math.floor(Date.now() / 1000);

const tokenFee = {
  config: configName,
  streamToken: "test_usdcx_stablecoin",
  streamFeeAmount: 0,
  streamAmount: "10", // must equal params.amount below
  expiry: now + 3600,
  nonce: `${await randomField(network)}field`,
};

const feeSignature = await signStreamTokenFee(
  adminPrivateKey,
  tokenFee,
  network,
  decimals,
);

const params = {
  receiver: receiverAddress, // cannot be the sender
  streamId,
  amount: "10",
  startTime: now,
  duration: 86_400,
  isCancelable: true,
  isPausable: true,
  autoWithdrawable: false,
  withdrawFrequency: 60,
  startNow: true, // on-chain start_time = create block time
  canTopup: true,
  // can_topup requires a buffer > 0. Deposit is this amount, not `amount`.
  initialBufferAmount: "0.000001",
};

Public create (approve the program, then create):

const payroll = await sender.programAddress();
await sender.approveTokenPublic(
  "test_usdcx_stablecoin",
  payroll,
  "100", // allowance covering fee + deposit + later topups
  decimals,
  { priorityFee: 100_000 },
);

const txId = await sender.createStreamPublic(
  params,
  "usdcx_stablecoin",
  decimals,
  config,
  tokenFee,
  feeSignature,
  { priorityFee: 100_000 },
);

Private create finds a credits record (auto-withdraw fee) and a token record (deposit + stream fee), and attaches freeze-list Merkle proofs:

const txId = await sender.createStreamPrivate(
  params,
  "usdcx_stablecoin",
  decimals,
  config,
  tokenFee,
  feeSignature,
  { priorityFee: 100_000 },
);

Wait until getStreamAnchor(streamId) returns before the next write.

Stream lifecycle

Pass a fresh unix timestamp on each call (StreamParams). Finalize checks it is close to chain time; for start_now streams it must not be older than on-chain start_time.

const op = { streamId, timestamp: Math.floor(Date.now() / 1000) };

| Action | Public | Private | Who | | --- | --- | --- | --- | | Top up | topupStreamPublic({ ...op, amount, tokenDecimals }) | topupStreamPrivate(...) | Sender (needs canTopup) | | Pause / resume | pauseResumeStreamPublic(op) | pauseResumeStreamPrivate(op) | Sender (isPausable) | | Withdraw vested | withdrawStreamPublic(op) | withdrawStreamPrivate(op) | Receiver | | Auto-withdraw | withdrawStreamAutoPublic(op, config) | withdrawStreamAutoPrivate(op, config) | Config withdrawer | | Cancel | cancelStreamPublic(op) | cancelStreamPrivate(op) | Sender (isCancelable) |

Cancel requires withdrawable ≤ deposited. After a tiny create buffer, that usually means a successful topup first. Always wait for the previous transaction to confirm and for getStreamAnchor to show the new withdrawnAmount / paused / canceled before proving the next one.

Private methods take an optional ticket plaintext; otherwise the service scans records for the matching ticket type (0 sender, 1 receiver, 2 withdrawer).

Reads

await service.programAddress();
await service.getStream(streamId);       // public Stream mapping
await service.getStreamAnchor(streamId); // public accounting
await service.getStreamConfig(configName);
await service.isTokenWhitelisted(configName, "test_usdcx_stablecoin");

await service.getOutgoingStreamCount(address, configName);
await service.listOutgoingStreamIds(address, configName);
await service.listIncomingStreamIds(address, configName);
await service.listPublicStreams(configName); // this wallet, both directions

await service.listPrivateStreams();
await service.decryptProgramRecords(service.programId);

await service.getPublicBalance();
await service.getPublicTokenBalance("test_usdcx_stablecoin.aleo", 6);
await service.getPrivateBalance();
await service.getPrivateTokenBalance("test_usdcx_stablecoin.aleo", 6);

await service.getComplianceProofs("usdcx", address, network);

listPublicStreams hydrates each id with Stream + StreamAnchor (amounts in token units). Canceled and ended streams are included.

Token metadata: getTokenInfo(service.networkClient, "test_usdcx_stablecoin.aleo").

Helpers: approveTokenPublic, transferTokenPublic, transferTokenPrivateToPublic.

Withdrawable amount

computeWithdrawableAmount mirrors compute_withdrawable_amount in main.leo, so a UI can show the vested balance without sending a transaction. All arguments are bigint in the stream's micro units / unix seconds:

import { computeWithdrawableAmount } from "@zebec-network/aleo-stream-sdk";

const anchor = await service.getStreamAnchor(streamId);

const { totalWithdrawable, currentlyWithdrawable } = computeWithdrawableAmount(
  BigInt(Math.floor(Date.now() / 1000)), // effectiveNow
  BigInt(anchor.startTime),
  BigInt(anchor.duration),
  BigInt(anchor.pausedInterval),
  fullAmount,   // the stream's full amount, in micro units
  withdrawnAmount, // anchor.withdrawnAmount, in micro units
);
  • totalWithdrawable — vested up to effectiveNow; currentlyWithdrawable — that minus withdrawnAmount.
  • effectiveNow is the timestamp to evaluate at. pausedInterval only covers pauses that have ended, so for a stream that is currently paused or canceled pass the timestamp at which accrual stopped (anchor.lastPausedTime / anchor.canceledAt) instead of the current time.
  • Returns zeros before startTime and clamps to fullAmount once elapsed >= duration.
  • It does not consider depositedAmount. A stream created with a small buffer and topped up later can vest more than it holds — cap currentlyWithdrawable at depositedAmount - withdrawnAmount before showing it as claimable.
  • Throws if duration <= 0 or if the computed total is below withdrawnAmount.

Local development

git clone https://github.com/Zebec-Fintech-Labs/aleo_payroll_sdk.git
cd aleo_payroll_sdk
yarn install
cp .env.example .env

Fill .env (never commit it):

| Variable | Purpose | | --- | --- | | NETWORK | testnet or mainnet | | ADMIN_PRIVATE_KEY / SENDER_PRIVATE_KEY / RECEIVER_PRIVATE_KEY | Role keys for e2e. PRIVATE_KEY is a fallback for any role | | ENDPOINT | Aleo REST host. Default in code is https://api.provable.com/v2 | | EXPLORER_URL | Explorer origin for logged tx links | | PROVER_URI | Delegated proving, e.g. https://api.provable.com/prove/testnet | | PROVER_API_KEY / PROVER_CONSUMER_ID | DPS credentials. Register with POST https://api.provable.com/consumers {"username":"<handle>"} | | E2E_TOKEN_PROGRAM | Default test_usdcx_stablecoin | | E2E_PRIORITY_FEE | Microcredits, default 100000 | | E2E_CONFIG_NAME | Reuse an existing config (hashed name or …field literal). If unset, e2e initializes a new config | | E2E_STREAM_ID | Optional target for getter tests | | RUN_E2E | Set to true by the yarn e2e scripts |

yarn test:unit
yarn test:e2e:getters          # reads only
yarn test:e2e:public           # create → topup → pause/resume → withdraw → cancel → auto-withdraw
yarn test:e2e:private
yarn test:e2e:initialize-config

yarn test:e2e:public skips initialize_config when E2E_CONFIG_NAME is set.

Build:

yarn build   # emits dist/ (also runs on npm prepare)

API map

Admin: initializeConfig, updateConfig, setTokenWhitelisted

Public streams: createStreamPublic, topupStreamPublic, pauseResumeStreamPublic, withdrawStreamPublic, withdrawStreamAutoPublic, cancelStreamPublic

Private streams: createStreamPrivate, topupStreamPrivate, pauseResumeStreamPrivate, withdrawStreamPrivate, withdrawStreamAutoPrivate, cancelStreamPrivate

Tokens: approveTokenPublic, transferTokenPublic, transferTokenPrivateToPublic, getComplianceProofs

State: getStream, getStreamAnchor, getStreamConfig, isTokenWhitelisted, listPublicStreams, listPrivateStreams, balances, findCredits / findToken / findTokenRecords

Crypto / units: configNameToField, signStreamTokenFee, verifyStreamTokenFeeSignature, randomField, toMicroUnits / fromMicroUnits, computeAutoWithdrawalFee, computeWithdrawableAmount, WITHDRAW_FREQUENCIES

License

MIT. Copyright Zebec Network.