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

@solidus-network/wallet

v0.1.0

Published

Solidus wallet SDK — did:solidus keypair derivation, an injectable verifiable-credential store, BBS+ selective-disclosure presentation, and scoped payment-mandate stamping. Publishes as @solidus-network/wallet.

Readme

@solidus-network/wallet

A wallet SDK for the Solidus Network: derive a did:solidus identity from a BIP-39 mnemonic, hold verifiable credentials in a store you supply, present them with BBS+ selective disclosure, and stamp scoped payment mandates for an agent to spend against.

Private keys live in a closure and are never returned.

Status — read this first

  • First release (0.1.0), testnet-grade. The API is small on purpose; treat it as a foundation, not a finished wallet.
  • Nothing is bundled that you might want to swap. The credential store and the BBS+ implementation are both injected. The only built-in store is in-memory.
  • There is no key-export function. This is deliberate (see below) and it is also a limitation: a mnemonic you did not save at creation time is unrecoverable through this API.

Install

npm install @solidus-network/wallet

Quick start

import { createWallet, newMnemonic } from '@solidus-network/wallet'

// Generate and SAVE this — the wallet will not give it back to you.
const mnemonic = newMnemonic()

const wallet = await createWallet({ mnemonic, network: 'testnet' })

console.log(wallet.did)      // did:solidus:testnet:7Kf9...
console.log(wallet.address)  // 7Kf9...

await wallet.addCredential(someVerifiableCredential)
const all = await wallet.listCredentials()

Keys

import { newMnemonic, isValidMnemonic, deriveWalletKeys } from '@solidus-network/wallet'

| Function | Does | |---|---| | newMnemonic() | Fresh 12-word BIP-39 mnemonic (128-bit entropy) | | isValidMnemonic(phrase) | Checksum + wordlist validation | | deriveWalletKeys(mnemonic, network?) | The full derivation, returned as plain data | | addressFromPublicKeyBytes(bytes) | base58(BLAKE3(publicKey)[0..20]) |

Derivation is deterministic — the same mnemonic always produces the same DID:

phrase → BIP-39 PBKDF2 seed (64 bytes) → first 32 bytes = Ed25519 private key
address = base58(BLAKE3(publicKey)[0..20])
did     = did:solidus:{network}:{address}

deriveWalletKeys returns mnemonic and privKeyHex in plain text. That is the point of the function — it is the low-level escape hatch — but it means the result is key material. Do not log it, return it over a wire, or put it in an error message. If you only need an identity and a credential store, use createWallet, which keeps both values in a closure and never exposes them.

Credential storage

interface CredentialStore {
  add(vc: VerifiableCredential): Promise<void>
  list(): Promise<VerifiableCredential[]>
  get(id: string): Promise<VerifiableCredential | undefined>
}

memoryStore() is the default and is not persistent — everything is gone when the process exits. Implement the same three methods over IndexedDB, SQLite, a Solidus pod, or anything else and pass it in:

const wallet = await createWallet({ mnemonic, store: myIndexedDbStore })

Selective disclosure

wallet.present(vcId, disclose) reveals only the named fields of a held credential and proves the rest without showing them. No BBS+ implementation is bundled, and none of the published packages drops in as one — you supply an object satisfying BbsLike:

interface BbsLike {
  present(
    vc: VerifiableCredential,
    disclose: string[],
  ): Promise<{ disclosed: string[]; proof: string }>
}
const wallet = await createWallet({ mnemonic, bbs: myBbsAdapter })

const { disclosed, proof } = await wallet.present(vcId, ['name', 'age_over_18'])

You will have to write the adapter. @solidus-network/bbs provides the cryptographic primitives (BbsSecretKey, BbsPublicKey, BbsSignature, BbsProof) and is byte-compatible with the chain — but it works in terms of message indices (disclosedIndices: number[]), not credential field names. Bridging "disclose name and age_over_18" to the indices those claims occupy in the signed message vector is the adapter's job, and that mapping depends on how your issuer canonicalizes the credential. Passing the bbs package itself as bbs will not type-check and will not work.

Calling present() without a bbs implementation throws with an explicit message rather than failing silently. Nothing else in the package requires it.

Payment mandates

stampMandate signs a scoped authorization the holder hands to an agent: pay this merchant, up to this amount, before this expiry. The agent can act within that envelope and cannot exceed it — the limit is inside the signed payload, so raising it requires the holder's key.

import { createWallet, stampMandate } from '@solidus-network/wallet'
import type { WalletInternal } from '@solidus-network/wallet'

const wallet = await createWallet({ mnemonic })

const { id, token } = await stampMandate(wallet as WalletInternal, {
  merchant: 'baku-bookshop',
  maxAmount: 500,
  rail: 'moka',        // 'moka' | 'x402'
  ttlMinutes: 15,      // default 15, hard ceiling 120
  claims: { age_over_18: true },
})

Returns { id, token } and nothing else — no key material. token is a compact JWS:

base64url(header).base64url(payload).base64url(ed25519 signature)

payload: { iss, aud, jti, merchant, max_amount_try, rail, exp, claims }
header:  { alg: 'EdDSA', typ: 'JWT', kid: <issuer DID> }

Any verifier that checks an EdDSA signature over header.body against the issuer's public key accepts it. Enforce scope yourself: check exp, merchant, and max_amount_try against the transaction before honouring it — the signature proves authorization, not appropriateness.

max_amount_try is TRY-denominated in its name, kept for wire-shape parity with the reference implementation this format mirrors. On the x402 (crypto) rail that name stretches its meaning. Known tension, not resolved in 0.1.0 — do not read the suffix as a currency guarantee.

Why the key never comes back

createWallet holds the mnemonic and private key in its closure and returns an object with no accessor for either. Signing happens through an internal capability that takes bytes and returns a signature, so stampMandate can sign without the key ever crossing a function boundary it could be captured at.

The tradeoff is real and one-directional: save the mnemonic when you generate it. There is no recovery path through this API.

What this package does not do

  • No network calls. It does not resolve DIDs, submit transactions, or fetch credentials. Pair it with @solidus-network/sdk for chain operations.
  • No credential issuance or verification. It stores and presents what you put in it.
  • No persistence, no encryption at rest. Both are the injected store's job.

License

Apache-2.0