Skip to content

Contract Diagram

Cursor Agent edited this page Jun 22, 2026 · 11 revisions

OCP Contract Architecture

Contract Hierarchy

flowchart TB
    OcpFactory -->|AuthorizeIssuer| IssuerAuthorization
    IssuerAuthorization -->|CreateCapTable| CapTable
    CapTable -->|Edit| Issuer["Issuer (OCF object)"]
    CapTable -->|Create/Edit/Delete| OCF["OCF Objects & Transactions"]
Loading

CapTable manages all OCF contracts via Maps (OCF object ID → ContractId) for O(1) lookup. The OCF object ID is a business identifier (typically a GUID from the database), not the DAML ContractId which changes on each archive/recreate.

Contract Flow

sequenceDiagram
    actor SO as System Operator
    actor I as Issuer
    participant OcpFactory
    participant IssuerAuthorization
    participant Issuer
    participant CapTable
    participant OCF as OCF Contracts

    SO->>OcpFactory: Deploy (once)
    SO->>OcpFactory: AuthorizeIssuer(issuer)
    OcpFactory->>IssuerAuthorization: create

    I->>IssuerAuthorization: CreateCapTable(issuer_data)
    IssuerAuthorization->>Issuer: create
    IssuerAuthorization->>CapTable: create (with Issuer)

    I->>CapTable: UpdateCapTable(creates, edits, deletes)
    CapTable->>OCF: archive/create OCF contracts
Loading

Key Design Patterns

Pattern Description
Dual Signatories All contracts require both issuer and system_operator
Factory Chain OcpFactory → IssuerAuthorization → CapTable
State Management CapTable maintains Map Text (ContractId T) for O(1) lookup
Reference Validation CapTable validates referenced objects exist before creating (e.g., stakeholder must exist before stock issuance)
Archive + Recreate Edit = archive old contract + create new + update map
Issuer is Special Exactly one per CapTable, can only be edited (no delete)

File Structure

OpenCapTable-v35/daml/Fairmint/OpenCapTable/
├── OcpFactory.daml          # Factory contract
├── IssuerAuthorization.daml # Authorization contract  
├── CapTable.daml            # State management (GENERATED by codegen)
├── Types.daml               # Shared types & enums
└── OCF/                     # 48 OCF templates (47 map-backed; Issuer is edit-only, not a map)
    ├── Issuer.daml
    ├── Stakeholder.daml
    ├── StockClass.daml
    ├── StockIssuance.daml
    └── ...

scripts/codegen/
├── generate-captable.ts     # Generates CapTable.daml from OCF types
└── captable-config.yaml     # Reference validation configuration

Code Generation: CapTable.daml is generated by scripts/codegen/generate-captable.ts, which discovers OCF types from OpenCapTable-v35/daml/Fairmint/OpenCapTable/OCF/ and generates the appropriate Maps and CRUD choices. Regenerate by running npm run build from the repo root (there is no separate codegen:captable script).

NFT, equity certificate, and other Fairmint packages

The CapTable / OcpFactory diagram above lives entirely in OpenCapTable-v35 in this repo.

NFT (Nft.Api.V1, Nft.Reference.V1), equity certificate (EquityCertificateShared, EquityCertificate), CantonPayments, Reports, etc. are implemented in fairmint/daml (see #216). This repo’s dars/ tree holds OpenCapTable backups (v34 on-chain, v35 local); use fairmint/daml for other package DARs and history.

Use @fairmint/daml-js for generated JS from those packages; @fairmint/open-captable-protocol-daml-js publishes OpenCapTable + bundled Splice/DA helpers only — see Home (NPM). Product-specific write-ups (equity certificate UI/SDK, CantonPayments, etc.) live with their respective repositories, not this OCP-only wiki.

References

Clone this wiki locally