@0xsend/cws-client
v0.3.0
Published
Typed fetch client and helpers for the Canton Wallet Service API
Downloads
728
Readme
@0xsend/cws-client
Typed fetch client for the Canton Wallet Service (CWS) HTTP API, plus client-side helpers for verifying server-prepared submissions before signing.
cws-client is the integration surface for any TypeScript/JavaScript app that
needs to drive a Canton wallet — sending and accepting transfers, managing
preapprovals and automerge UTXO delegations, and operating multisig wallets —
without trusting the server to compose what gets signed.
Install
npm install @0xsend/cws-clientRequires Node.js 20 or newer.
Quick start
import { createClient } from '@0xsend/cws-client/client'
const wallet = createClient({
apiKey: 'sk_testnet_...',
network: 'testnet',
})
const multisigs = await wallet.multisig.listMultisigs()createClient accepts either an apiKey + network pair (mainnet/testnet
presets, Keycloak token exchange handled internally) or a static token +
baseUrl for environments that mint their own bearer tokens.
Prepare → verify → sign → submit
Every mutation in CWS follows the same shape:
- Call a
prepare*method on the client. The server returns a base64-encodedPreparedTransactionand the hash it expects you to sign. - Decode the prepared submission locally and recompute the hash with
verifyPreparedSubmission(or the topology variants below). If the hash you recompute does not match what the server claims, do not sign — the server is asking you to authorize something other than what you requested. - Sign the verified hash with your own keys (P-256 or secp256k1 via ECDSA). The private key never leaves your environment.
- Submit the signature back via the corresponding submit/approve method.
import {
createClient,
decodePreparedSubmission,
verifyPreparedSubmission,
} from '@0xsend/cws-client'
const prepared = await wallet.transaction.prepareTransferInstruction({
body: { to: counterparty, amount: '10.0', instrument },
})
const decoded = decodePreparedSubmission(prepared.data.preparedTransaction)
verifyPreparedSubmission({
preparedTransaction: decoded,
expectedHash: prepared.data.preparedTransactionHash,
intent: { kind: 'transfer', to: counterparty, amount: '10.0', instrument },
})
const signature = await sign(prepared.data.preparedTransactionHash) // your signer
await wallet.transaction.submit({ body: { /* prepared id, signature */ } })Single-signer transfers (1/1 wallets)
For wallets where the active key is the sole signer, use the transaction.*
prepare helpers. The server submits the transaction as soon as it receives a
valid signature — no queue, no co-signers.
Available flows:
prepareTransferInstruction— send a transfer.prepareTransferInstructionAccept/Reject/Withdraw— respond to a pending transfer instruction.prepareBulkTransfer/prepareBulkTransferSetup— batch multiple transfers into a single signed submission.preparePreapproval/preparePreapprovalRevoke— manage transfer preapprovals (see below).prepareAutoMerge/prepareAutoMergeRevoke— manage automerge UTXO delegations (see below).
Each prepare* returns the same prepared-transaction envelope; verify and
sign it the same way.
Multisig
Multisigs in CWS are first-class wallet accounts with their own party id, threshold, and signer set. The lifecycle:
- Create —
multisig.createproposes a new multisig with an initial member set and threshold. Each prospective member signs the topology transaction before the multisig becomes active. - Queue — any member calls a
prepare*method (transfer, preapproval, automerge, topology) with the multisig party id as the actor. The server decomposes the prepared submission into a queued transaction visible to every member. - Approve — members independently re-derive the prepared-transaction
hash with
verifyPreparedSubmission(orverifyPreparedMultisigTopology/verifyPreparedTopologyUpdatefor topology changes) and submit their signatures viamultisig.approveTransaction/approveTopologyUpdate. - Submit — once the threshold is reached,
multisig.submit(or the server's auto-submit, when configured) finalizes the transaction on the ledger.
Topology changes (add/remove member, change threshold) flow through the same prepare → verify → sign loop, with their own verifier so you can recompute the multi-hash before authorizing a change to the signer set.
Transfer preapprovals
A preapproval is a long-lived authorization for a counterparty to pull a specified instrument from your wallet without a per-transfer signature. CWS exposes both grant and revoke as prepared submissions:
preparePreapproval— grant. Verify that the prepared submission targets the counterparty and instrument you intend, optionally with an expiry.preparePreapprovalRevoke— revoke a specific preapproval contract.
Preapprovals are used by services that need recurring debits (subscriptions, streaming payments) and by automerge providers (below).
Automerge UTXO delegations
Canton wallets accumulate small UTXOs as they receive funds. Automerge is a delegation that authorizes a provider to consolidate those UTXOs back into a single holding on your behalf, without you signing each merge. This keeps wallets responsive when sending — fewer, larger UTXOs mean fewer inputs to gather and sign.
prepareAutoMerge— grant the delegation, scoped to a provider party and an instrument. The verifier ensures the prepared submission matches that scope; the provider cannot use the delegation to move value off-wallet.prepareAutoMergeRevoke— revoke an active delegation contract.
For multisig wallets, automerge follows the same queue-and-approve flow as any other prepared submission.
Public exports
| Subpath | Use |
|---|---|
| @0xsend/cws-client | createClient, prepared-submission verifiers (verifyPreparedSubmission, verifyPreparedMultisigTopology, verifyPreparedTopologyUpdate, verifyTopologyTransactionHashes), network presets, response types |
| @0xsend/cws-client/client | Client-construction surface only — createClient, CantonWallet, type-only re-exports of the generated wallet types. Use this when you only need types and want to avoid pulling in the verifier code. |
resolveNetwork and NETWORKS expose the built-in mainnet/testnet base URL
and Keycloak presets for callers that want to introspect or override them.
Links
- Source: https://github.com/0xsend/canton-monorepo/tree/dev/packages/cws-client
- Website: https://send.it
License
MIT
