OcpClient is the ergonomic entry package surface for @open-captable-protocol/canton. Instantiate it once with your authenticated Canton ledger clients, then drill into OpenCapTable for every cap-table lifecycle action, OpenCapTableReports for valuation artifacts, CantonPayments / PaymentStreams for tokenized movement, and CouponMinter for TPS pacing utilities. context remembers FeaturedAppRight, issuer party, and the active cap-table contract id across calls so integrations do not re-thread disclosures on every invocation.
Reads through OpenCapTable.*.get return ContractResult<T> { data, contractId }, matching OCF payloads with Canton handles—see the per-entity pages under /reference/open-cap-table for one page per get. Stateful writes that mutate embedded cap-table rows run through CapTableBatch (capTable.update) unless you deliberately emit bare commands (issuer.buildCreate) with createBatch for multi-command Canton submissions.
Minimal setup
import { Canton } from '@fairmint/canton-node-sdk';
import { OcpClient, toContractId, toPartyId } from '@open-captable-protocol/canton';
const canton = new Canton({ network: 'localnet' });
const ocp = new OcpClient({
ledger: canton.ledger,
validator: canton.validator, // optional for strict cap-table workloads
});
Dependencies (new OcpClient)
| Parameter | Requirement | Meaning |
|---|---|---|
| ledger | Required | Canton LedgerJsonApiClient from new Canton(...). Mandatory for OpenCapTable, CapTableBatch, OpenCapTableReports, and anything that submits JSON API exercises. |
| validator | Optional | Canton ValidatorApiClient. Needed for PaymentStreams.utils.buildPaymentContext* stacks that hydrate validator + Amulet context. Pure cap-table code can omit this. |
If your transport layer changes (localnet preview vs pinned package line), disclose the pinned template ids explicitly through helper params—see capTable.update({ capTableContractDetails }) and IssuerAuthorization flows below.
Namespace overview
OpenCapTable
- Readers (
get) — hydrate any OCF object or transactional record by contract id. Every namespace key matches theOcpClienttable insrc/OcpClient.ts. issuer.buildCreate— emitCreateCapTablepayloads that must ride onocp.createBatch(addBuiltCommand).issuerAuthorization.authorize/withdraw— authorize an issuer party through the pinned OCP Factory or withdraw from an IssuerAuthorization contract.capTable—classify/getState(pinned-template queries only),update(fluentCapTableBatch),archive(system-operator teardown after empty maps). Package-level helpers (archiveFullCapTable,getSystemOperatorPartyId,buildUpdateCapTableCommand) live on the@open-captable-protocol/cantonroot export—not nested underOcpClient.
Consult the index at /reference/open-cap-table for the full routing matrix linking each namespace to get pages plus write paths.
OpenCapTableReports.companyValuationReport
Builder + submit helpers (buildCreate, create, update, addObservers) layered on CompanyValuationReport contracts—see /reference/reports/company-valuation-report for full parameters and submission semantics.
CantonPayments & PaymentStreams
Amulet / stream utilities that depend on both ledger and (usually) validator transports. See /reference/payments and /reference/payment-streams for per-builder disclosure requirements.
CouponMinter
TPS-throttled mint helpers (mintWithRateLimit, waitUntilCanMint, etc.). Pure stateless utilities over coupon payloads supplied by Canton.
Cached context (OcpContextManager)
Expose ocp.context accessors:
Set: setFeaturedAppRight, setIssuerParty, setCapTableContractId, setAll, clear.
Lazy helpers: requireFeaturedAppRight, requireIssuerParty, requireCapTableContractId throw OcpValidationError with REQUIRED_FIELD_MISSING when callers forget provisioning. isReadyForBatchOperations is true exactly when FeaturedAppRight + CapTable CID are hydrated—useful for guardrails before chaining CapTableBatch.
Contexts are process-local—not persisted.
createBatch
Signature:
ocp.createBatch({ actAs: string[]; readAs?: string[] }): TransactionBatch
Dependency contract: Canton Node SDK TransactionBatch expects the ledger you injected earlier. Populate actAs with signer parties (issuer rows for UpdateCapTable, system_operator for WithdrawAuthorization or ArchiveCapTable, etc.). Optionally include readAs when contract resolution spans stakeholders.
Purpose: Glue issuer creation, factory exercises, miscellaneous commands, etc., into atomic submissions that also include manually built payloads:
const built = ocp.OpenCapTable.issuer.buildCreate({
issuerAuthorizationContractDetails,
issuerParty: ISSUER_PARTY_ID,
issuerData: ISSUER_OCF_SHAPE,
});
await ocp.createBatch({ actAs: [ISSUER_PARTY_ID] }).addBuiltCommand(built).submitAndWaitForTransactionTree();
For only cap-table row edits, ocp.OpenCapTable.capTable.update(...) remains the ergonomically constrained path (CapTableBatch) issuing a single UpdateCapTable command.
Returns & errors surfaced from the façade
Writes wrap Canton responses with richer errors:
| Error | Typical trigger |
|---|---|
OcpValidationError | Missing actAs, empty CapTableBatch, malformed schema inputs, context.require* misses. Codes include REQUIRED_FIELD_MISSING and INVALID_TYPE. |
OcpContractError | Ledger rejects template mismatch, concurrency, or Canton-specific guard rails; CapTableBatch wraps UpdateCapTable failures with CHOICE_FAILED. |
Reads may raise OcpParseError or OcpContractError if template ids diverge (SCHEMA_MISMATCH, RESULT_NOT_FOUND).
Always surface cause when inspecting OcpContractError—the SDK attaches batch metadata for UpdateCapTable.
Auth, parties, and disclosure checklist
OcpClient never invents JWT scopes—supply a ledger client backed by Canton credentials that satisfy:
UpdateCapTable: signer is issuer.CreateCapTable: exercising party matchesissuerPartydisclosed onIssuerAuthorization.AuthorizeIssuer: exercised through OCP Factory with appropriate factory admin rights per deployment.WithdrawAuthorization,ArchiveCapTable,IssuerAuthorizationadmin ops: signer issystem_operator(seewithdraw,capTable.archive) per DAML privileges.readAson reads/batches broaden visibility windows for stakeholders when your token cannot otherwise witness contracts.
FeaturedAppRight / IssuerAuthorization disclosures MUST stay consistent with Canton network configuration (staging vs pinned package hashes).
Related pages
Source
src/OcpClient.tssrc/OcpClient.ts— OpenCapTableMethods typings (mirror ofOpenCapTablesurface)