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

@provablehq/veil-aleo-sdk

v0.10.0

Published

Local signing and proving for the Veil Aleo SDK, backed by the Provable SDK.

Readme

@provablehq/veil-aleo-sdk

Local signing and proving for the Veil Aleo SDK, backed by the Provable WASM SDK (@provablehq/sdk).

Reach for this package when the caller holds an Aleo private key directly — bots, scripts, tests, and CI — rather than connecting a wallet. It turns a private key into an account, wires a wallet client with proving configured (delegated or local), builds record scanners, and derives the same account keys (address, view key) and blinded claim identity that private flows depend on. Because it loads WASM, an app that connects a wallet instead — the wallet holds the keys and proves for you — generally does not need this package at all.

Installation

pnpm add @provablehq/veil-aleo-sdk @provablehq/veil-core

Usage

Load the SDK for a network, then build the account, scanner, and clients from the returned handle. loadNetwork is async because it fetches the network's WASM binaries; the handle it returns is synchronous from there on.

import { loadNetwork } from '@provablehq/veil-aleo-sdk'

const aleo = await loadNetwork('testnet')

// A record scanner so the wallet client can find the private records that
// program calls spend. The first requestRecords registers the view key with the
// service (one network round-trip); later calls reuse it.
// `url` defaults to Provable's hosted scanner, so this needs no arguments.
const scanner = aleo.createRemoteScanner()

// A fully-wired client pair: an account from the private key, a public client
// for reads, and a wallet client with proving + the scanner attached. The
// credential store holds one Provable API session shared by proving and
// scanning — it registers a consumer on the first run and reuses it after.
import { fileCredentialStore } from '@provablehq/veil-aleo-sdk/node'

const { publicClient, walletClient, account } = aleo.createAleoClient({
  privateKey: PRIVATE_KEY,
  networkUrl: 'https://api.provable.com/v2',
  credentialStore: fileCredentialStore('./.provable-credentials.json'),
  records: scanner,
})

account.address // 'aleo1...'

No API key appears above: the store registers a Provable API consumer the first time something needs one and reuses it from then on. Already hold credentials? Pass consumerId and apiKey instead and drop the store — see Provable API credentials.

proverUrl is a base URL — the active network is appended, the same way the record scanner's url works — so switchChain re-targets proving instead of leaving it on the network the client started from. Do not include the network segment yourself. It defaults to Provable's hosted prover (DEFAULT_PROVER_URL) under delegated proving, so the option only needs setting for a self-hosted one.

Pass provingMode: 'local' to prove in-process instead of delegating to a prover service (drop proverUrl/apiKey/consumerId). The walletClient composes with action packages the same way a wallet-backed client does:

import { shieldSwapActions } from '@provablehq/shield-swap-sdk'

const client = walletClient.extend(
  shieldSwapActions({ api: {} }),
)

Provable API credentials

Delegated proving and the hosted record scanner both authenticate with a consumer id and API key, which the SDK exchanges for short-lived JWTs. A client builds a single session covering both services, so one credential mints one token instead of each service minting its own.

Where that credential comes from is the only decision. Three options:

| | Use when | Registers? | | --- | --- | --- | | fileCredentialStore(path) from /node | Bots, scripts, servers, CI that can write to disk | On first run, then reuses | | consumerId + apiKey | You already hold credentials — from a secret manager or env | Never | | memoryCredentialStore() (the default) | Tests, ephemeral workers | Every process, key discarded at exit |

memoryCredentialStore() is what a client falls back to when given neither, so delegated proving works with no configuration at all. It is only appropriate for a single short run: the API issues each key exactly once, so a process that registers into memory and runs again registers a second consumer nobody can reclaim. Anything long-lived wants a persistent store.

The session resolves on the first prove or scan. authenticateProvableApi() does it eagerly, which is worth doing at startup so a bad key fails before you have built a transaction:

const { credentials, expiration, registered, applied } =
  await walletClient.authenticateProvableApi()

applied // { proving: true, recordScanning: true }

applied reports which paths the session actually reaches. recordScanning is false when the client was given a record provider it cannot share a session with — any implementation other than the ones this package builds — in which case that provider keeps using whatever credentials it was constructed with.

If you do not have credentials yet, register a consumer once. The API key is issued exactly once and cannot be recovered, so persist it immediately:

import { registerProvableApi } from '@provablehq/veil-aleo-sdk'

const credentials = await registerProvableApi({ username: 'my-bot-42' })
await writeFile('creds.json', JSON.stringify(credentials), { mode: 0o600 })

A username is spent once. It is globally unique, the API exposes no endpoint that reads a consumer back, and a duplicate registration answers 409 with nothing usable in it — so a taken name cannot be traded for the credentials it belongs to. The stored key is the only copy, which is the real reason to give a client a persistent store rather than the in-memory default.

When a client registers for you, username chooses the name:

const { walletClient } = aleo.createAleoClient({
  privateKey: PRIVATE_KEY,
  networkUrl: 'https://api.provable.com/v2',
  proverUrl: 'https://api.provable.com/prove',
  credentialStore: fileCredentialStore('./.provable-credentials.json'),
  username: 'my-bot-42',        // or () => `bot-${shard}`, resolved at registration
})

Supplied names are used verbatim, so the consumer is identifiable in your account — and a collision fails with an error saying the name is taken rather than quietly registering something else. Omit it and the name is derived from the account address with a random suffix, which keeps the zero-configuration path working: since a username cannot be reused, an account that lost its stored key still needs to be able to register.

On Node, fileCredentialStore covers this. It writes with mode 0600, treats a missing file as "not registered yet", and reports a corrupt one rather than registering over credentials that might still be recoverable by hand. It lives on the /node subpath so the node:fs import never reaches a browser bundle:

import { fileCredentialStore } from '@provablehq/veil-aleo-sdk/node'

const { walletClient } = aleo.createAleoClient({
  privateKey: PRIVATE_KEY,
  networkUrl: 'https://api.provable.com/v2',
  proverUrl: 'https://api.provable.com/prove',
  credentialStore: fileCredentialStore('./.provable-credentials.json'),
  records: scanner,
})

const { registered } = await walletClient.authenticateProvableApi()
registered // true on the first run, false afterward

Anywhere else, implement the two-method interface yourself — a keychain, localStorage, IndexedDB, or a secret manager all satisfy it, and the SDK assumes nothing about which:

import type { ProvableCredentialStore } from '@provablehq/veil-aleo-sdk'

const credentialStore: ProvableCredentialStore = {
  load: () => {
    const raw = localStorage.getItem('provable-credentials')
    return raw ? JSON.parse(raw) : undefined // undefined → register
  },
  save: (c) => localStorage.setItem('provable-credentials', JSON.stringify(c)),
}

Two rules for a hand-written store. load MUST return undefined rather than throw when nothing is stored, or resolution fails instead of registering. And save must actually persist: it runs before the credentials are handed back precisely so a failed write fails the call, since a swallowed one orphans a consumer whose key cannot be reissued. That also means a genuinely read-only environment should supply consumerId/apiKey directly rather than rely on registration.

An explicit consumerId/apiKey pair takes precedence over the store, so an operator can inject a rotated key or CI credentials without clearing persisted state first.

One caveat on the mint itself: the API does not validate the consumer id against the API key. A mismatched id still yields a working token, because the token's issuer comes from the key. The mismatch surfaces later as a rejection from the service you call — the record scanner reports it as No credentials found for given 'iss'. Nothing in the mint path can catch that for you, so keep the pair together.

The handle also exposes the pieces individually when the caller does not want the full pair:

  • aleo.privateKeyToAccount(privateKey) / aleo.mnemonicToAccount(mnemonic) / aleo.generateAccount() — build a LocalAccount.
  • aleo.createProvingConfig({ ... }) — the proving config for createWalletClient({ proving }).
  • aleo.createStandaloneScanner({ ... }) — a scanner keyed by an explicit view key, with no account attached.
  • aleo.decryptRecord(viewKey, ciphertext) / aleo.verifySignature(...) — network-agnostic key operations.

For local iteration without a live chain, createDevnodeClient() returns the same client pair pointed at an Aleo Devnode instance with a pre-funded seeded account.

Provisioned API keys (edge gateway)

The edge gateway (edge.provable.com) runs a different auth model: no consumer registration and no JWTs. An operator hands out an API key, and every request carries it verbatim in an X-API-Key header. Configure it with auth instead of the consumer options:

const { walletClient } = aleo.createAleoClient({
  privateKey,
  networkUrl: 'https://edge.provable.com/api/v2',
  proverUrl: 'https://edge.provable.com/api/prove',
  records: aleo.createRemoteScanner({ url: 'https://edge.provable.com/api/scanner' }),
  auth: { mode: 'api-key', value: process.env.PROVABLE_API_KEY! },
})

The two models are mutually exclusive: combining auth with apiKey, consumerId, username, credentialStore, or session throws at construction. There is no session under keyed auth — nothing registers, persists, or refreshes — so authenticateProvableApi() throws, and a 401 means the key is invalid or revoked, which only the operator can fix.

WASM dependency

@provablehq/sdk ships the Aleo cryptography as WebAssembly, and this package loads it. That is the cost of holding keys and proving locally. An app that connects a wallet — Shield, Leo — should build its client from the wallet adapter instead (see @provablehq/veil-aleo-wallet-adapter) and skip @provablehq/veil-aleo-sdk, keeping the WASM out of the bundle.