Observed since 21 Oct, 09:44 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
End-user Canton wallet CLI (TUI + scripted)
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.
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.
Create a profile. The wizard walks you through the choices:
cws profile create work
The prompts in order:
mainnet | 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.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.Profiles live under $WALLET_CONFIG (default ~/.config/wallet-cli).
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 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.
cws health
cws profile list
cws profile create <name>
cws profile import <name> --from <path> --network <mainnet|testnet|localnet>
cws profile remove <name>
cws multisig list
cws multisig show <id>
cws multisig pending
cws multisig create
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>
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
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>
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>
cws instruments list [--json] # list available instruments across the active network
cws holdings list <partyId> [--instrument <id>] [--json] # list holdings for a party
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_NETWORK — localnet | 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.
--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.keystore.ts are actively zeroed.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.
cws profile import a
refreshed config, or edit the profile's encrypted keystore via the
profile create flow.baseUrl and keycloak.url to be set explicitly; the defaults only cover
mainnet and testnet. Check the values with cws profile list --json.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 transferA — accept transferP — manage transfer preapprovalsM — manage automerge delegationsi — browse instrumentsH — open full holdings viewx / Esc — switch accountsq — quit (suppressed while a text field has focus; Ctrl-C always quits)Multisig dashboard hotkeys:
s — send transfer proposalp — propose topology changea — approve pending itemr — reject pending itemi — browse instrumentsH — open full holdings viewx / Esc — switch accountsq — 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.
MIT
Download counts and popularity will appear here as the collector receives them.
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 21 Oct, 09:44 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:6feb364ec269e269391d6b8f2e21527e7d1e32cbcfd9aa056ee5e096bbe23bcf