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

@0xsend/cws-cli

v0.4.0

Published

End-user Canton wallet CLI (TUI + scripted)

Readme

@0xsend/cws-cli

End-user Canton wallet CLI (cws) with both an interactive TUI and a scripted subcommand mode. Ships an encrypted keystore, profile-based multi-identity support, and mainnet typed-token confirmation for every mutation.

Install

npm install -g @0xsend/cws-cli
# or: pnpm add -g, yarn global add, bun install -g
cws --help

Requires Node.js 20 or newer. The published bundle is fully self-contained — no extra @0xsend/* packages need to be installed alongside.

First run

Create a profile. The wizard walks you through the choices:

cws profile create work

The prompts in order:

  1. Networkmainnet | testnet | localnet. Selects the Canton deployment and (for mainnet/testnet) the default cws-api base URL and Keycloak realm. Localnet requires you to supply baseUrl and keycloak.url explicitly.
  2. API key — paste the cws-api key for the target realm. Stored inside the encrypted keystore, never on disk in plaintext.
  3. Signing key source — one of:
    • generate — new P-256 keypair (default; secp256k1 also supported), private key held only in the keystore.
    • import — read a PEM/DER file from disk.
    • paste — paste hex/base64 material at the prompt.
  4. Password — encrypts the keystore with Argon2id + AES-256-GCM. You will be asked for it every time a command needs to sign (no session cache in v1).

Profiles live under $WALLET_CONFIG (default ~/.config/wallet-cli).

Commands

cws
├── health                                    check cws-api connectivity
├── profile
│   ├── create <name>
│   ├── list
│   ├── import <name> --from <path> --network <mainnet|testnet|localnet>
│   └── remove <name>
├── multisig
│   ├── list                                  list multisigs visible to the active profile
│   ├── show <id>                             show multisig details
│   ├── pending                               list pending items across all visible multisigs
│   ├── create                                create a new multisig
│   ├── queue                                 propose new multisig transactions (prepare + queue + self-sign)
│   │   ├── send <multisigPartyId> <to> <amount> <instrument> [--description <text>]
│   │   ├── accept <transferInstructionId> --multisig <partyId>
│   │   ├── preapproval grant <multisigPartyId> <providerPartyId> [--expires-at <ms>]
│   │   ├── preapproval revoke <multisigPartyId> <preapprovalContractId>
│   │   ├── automerge enable <multisigPartyId> --provider <partyId> --instrument <id>
│   │   ├── automerge disable <multisigPartyId> <delegationContractId>
│   │   └── automerge revoke <multisigPartyId> <delegationContractId>
│   ├── transaction                           operate on existing queued multisig transactions
│   │   ├── list --multisig <partyId> --queue [--status <status>] [--limit <n>]
│   │   ├── list --multisig <partyId> --offers [--direction <incoming|outgoing|all>]
│   │   ├── show <transactionId>
│   │   ├── history --multisig <partyId> [--status <status>] [--limit <n>]
│   │   ├── approve <transactionId>
│   │   ├── reject <transactionId>
│   │   ├── cancel <transactionId>
│   │   └── submit <transactionId>            re-submit a fully-signed queued transaction
│   └── topology
│       ├── list --multisig <id>
│       ├── show <id> --multisig <multisigId>
│       ├── propose add-member <multisigPartyId> <party>
│       ├── propose remove-member <multisigPartyId> <party>
│       ├── propose set-threshold <multisigPartyId> <from> <to>
│       ├── approve <id> --multisig <multisigId>
│       └── reject <id> --multisig <multisigId>
├── transaction                               single-signer (1/1) operations — partyId derived from keystore
│   ├── list --offers [--direction <incoming|outgoing|all>]
│   ├── send <to> <amount> <instrument> [--description <text>]
│   ├── accept <transferInstructionId>
│   ├── preapproval grant <providerPartyId> [--expires-at <ms>]
│   ├── preapproval revoke <preapprovalContractId>
│   ├── automerge enable --provider <partyId> --instrument <id>
│   ├── automerge disable <delegationContractId>
│   └── automerge revoke <delegationContractId>
├── instruments
│   └── list [--json]                         list available instruments
└── holdings
    └── list <partyId> [--instrument <id>] [--json]   list holdings for a party

All commands accept --json for machine-readable output and --profile <name> to override WALLET_PROFILE.

Multisig vs single-signer

multisig queue * commands take an explicit <multisigPartyId> and route the prepared transaction through the queue (threshold signers approve, then multisig transaction submit or auto-submit when threshold is met).

transaction * commands are for 1/1 wallets. The party id is derived automatically from the active profile's keystore — no party argument is needed. The cws-api submits the transaction directly upon signing.

Health

cws health

Profile

cws profile list
cws profile create <name>
cws profile import <name> --from <path> --network <mainnet|testnet|localnet>
cws profile remove <name>

Multisig — party-level

cws multisig list
cws multisig show <id>
cws multisig pending
cws multisig create

Multisig — propose new queued tx (queue)

cws multisig queue send <multisigPartyId> <to> <amount> <instrument> [--description <text>]
cws multisig queue accept <transferInstructionId> --multisig <partyId>
cws multisig queue preapproval grant <multisigPartyId> <providerPartyId> [--expires-at <ms>]
cws multisig queue preapproval revoke <multisigPartyId> <preapprovalContractId>
cws multisig queue automerge enable <multisigPartyId> --provider <partyId> --instrument <id>
cws multisig queue automerge disable <multisigPartyId> <delegationContractId>
cws multisig queue automerge revoke <multisigPartyId> <delegationContractId>

Multisig — act on queued tx (transaction)

list requires exactly one of --queue (queued multisig transactions) or --offers (incoming TransferInstructions). Pass --direction to filter offers by incoming (default), outgoing, or all.

cws multisig transaction list --multisig <partyId> --queue [--status <status>] [--limit <n>]
cws multisig transaction list --multisig <partyId> --offers [--direction <incoming|outgoing|all>]
cws multisig transaction show <transactionId>
cws multisig transaction history --multisig <partyId> [--status <status>] [--limit <n>]
cws multisig transaction approve <transactionId>
cws multisig transaction reject <transactionId>
cws multisig transaction cancel <transactionId>
cws multisig transaction submit <transactionId>   # re-submit a fully-signed queued transaction

Multisig — topology

cws multisig topology list --multisig <id>
cws multisig topology show <id> --multisig <multisigId>
cws multisig topology propose add-member <multisigPartyId> <party>
cws multisig topology propose remove-member <multisigPartyId> <party>
cws multisig topology propose set-threshold <multisigPartyId> <from> <to>
cws multisig topology approve <id> --multisig <multisigId>
cws multisig topology reject <id> --multisig <multisigId>

Single-signer transaction (1/1 wallets)

list --offers discovers TransferInstruction contract ids you can act on with accept / reject / withdraw. Default direction is incoming.

cws transaction list --offers [--direction <incoming|outgoing|all>]
cws transaction send <to> <amount> <instrument> [--description <text>]
cws transaction accept <transferInstructionId>
cws transaction preapproval grant <providerPartyId> [--expires-at <ms>]
cws transaction preapproval revoke <preapprovalContractId>
cws transaction automerge enable --provider <partyId> --instrument <id>
cws transaction automerge disable <delegationContractId>
cws transaction automerge revoke <delegationContractId>

Instruments

cws instruments list [--json]   # list available instruments across the active network

Holdings

cws holdings list <partyId> [--instrument <id>] [--json]   # list holdings for a party

Environment variables

  • WALLET_CONFIG — root directory for profiles (default ~/.config/wallet-cli).
  • WALLET_PROFILE — profile name used when --profile is not passed.
  • WALLET_PASSWORD — keystore password. Security warning: any process on the host can read the environment of another process owned by the same user; prefer the interactive prompt unless you are in a controlled non-interactive setting (CI runners with secret-backed env, etc.).

cws profile onboard <name> additionally reads the following when set, skipping the matching inquirer prompt:

  • WALLET_NETWORKlocalnet | testnet | mainnet.
  • WALLET_USERNAME — Keycloak username the profile will authenticate as.
  • WALLET_ONBOARDING_SECRET — one-shot onboarding secret minted by an admin via POST /onboarding-secrets.
  • --yes additionally skips the prepared-submission confirm so the flow runs end-to-end without a TTY. The same security caveat as WALLET_PASSWORD applies; intended for test scripts and CI.

--password <value> is accepted on the argv but prints a warning on every invocation because ps(1) leaks argv to other users on multi-user hosts.

Security model

  • Single encrypted keystore per profile. The keystore envelope contains both the cws-api API key and the signing-key material (P-256 by default; secp256k1 supported).
  • KDF: Argon2id with per-profile salt. Cipher: AES-256-GCM (authenticated encryption; tampering fails decryption instead of yielding silent garbage).
  • Interactive mainnet mutations require typed-token confirmation: the operator types the first 6 characters of the multisig party id. --yes short-circuits typed-token confirmation on every network, including mainnet — intended for CI and headless automation. The same security caveat as WALLET_PASSWORD applies (env/argv visibility).
  • --password on argv emits a warning. Argv is visible to ps.
  • No session cache in v1. Every command that signs re-prompts for the password.
  • Password zeroing is best-effort: JavaScript strings are immutable, so only Buffer copies of the password inside keystore.ts are actively zeroed.

Exit codes

Categories map to exit codes via EXIT_CODES in src/core/output.ts:

| Category | Code | |-------------|------| | unknown | 1 | | auth | 2 | | cancelled | 0 | | config | 3 | | io | 4 | | network | 5 | | safety | 6 | | signing | 7 | | validation | 8 |

cancelled deliberately exits 0 so shell pipelines treat user-aborted confirmations as a successful no-op; the reason still surfaces in stderr.

Troubleshooting

  • Unlock fails with decryption error — wrong password. There is no recovery path; if the password is lost, remove the profile and re-import the signing key.
  • Keycloak 401 / 403 — API key expired or bound to the wrong realm. Re-provision from the cws-api admin and cws profile import a refreshed config, or edit the profile's encrypted keystore via the profile create flow.
  • Localnet cannot reach cws-api — localnet profiles require both baseUrl and keycloak.url to be set explicitly; the defaults only cover mainnet and testnet. Check the values with cws profile list --json.

TUI tour

cws (no args) or cws ui launches the terminal UI:

profile-picker  →  unlock  →  primary dashboard  ⇄  account picker  ⇄  multisig dashboard

After unlock, the TUI lands on the active profile's primary wallet account and attempts to show holdings inline. Multisigs are available from the account picker and are treated as switchable first-party accounts rather than a separate mode. If cws-api cannot load holdings because its Ledger API dependency is unavailable, the dashboard stays usable and explains the limitation. Press H for the full holdings view.

Primary-account dashboard hotkeys:

  • s — send transfer
  • A — accept transfer
  • P — manage transfer preapprovals
  • M — manage automerge delegations
  • i — browse instruments
  • H — open full holdings view
  • x / Esc — switch accounts
  • q — quit (suppressed while a text field has focus; Ctrl-C always quits)

Multisig dashboard hotkeys:

  • s — send transfer proposal
  • p — propose topology change
  • a — approve pending item
  • r — reject pending item
  • i — browse instruments
  • H — open full holdings view
  • x / Esc — switch accounts
  • q — quit (suppressed while a text field has focus; Ctrl-C always quits)

Mainnet safety: in interactive use, before any mutation submits, the TUI asks you to type the first 6 characters of the multisig party id. --yes short-circuits this prompt on every network — automation paths are responsible for supplying it deliberately.

Links

  • Source: https://github.com/0xsend/canton-monorepo/tree/dev/packages/cws-cli
  • Website: https://send.it

License

MIT