Fairmint DAML contracts
This repository contains Fairmint's DAML contract packages and publishes their generated JavaScript
bindings as @fairmint/daml-js.
The package covers:
- Canton payment streams
- OCF reporting contracts
- CIP-0112 equity tokens, OTC settlement, and clearing
- TA trade settlement on the OpenCapTable-v35 register: the transfer agent's trade desk
(
TradeSettlement-v01) and the holder-facing templates of its trades (TradeSettlementHolder-v01: terms, the holders' approvals and the Token Standard V2 cash leg) - the equity certificate, keyed by cap table, stakeholder and stock class (
EquityCertificate) - NFT API and reference contracts
- test-token helpers used by integrations
The Open Cap Table Protocol contracts are published separately. Install
@fairmint/open-captable-protocol-daml-js
for Fairmint.OpenCapTable and OCP_TEMPLATES; their source is in
Fairmint/open-captable-protocol-daml.
@fairmint/daml-js carries only a private copy of the OpenCapTable-v35 and OpenCapTableApi-v01
types that TradeSettlement-v01's bindings name (and of the equity certificate types the desk's
reserve and settle name), pinned to the OpenCapTable version it was built against. That copy is not
exported and registers no templates with @daml/types, so OpenCapTable templates always resolve
through @fairmint/open-captable-protocol-daml-js.
Developer documentation
The GitHub wiki is retired (disabled). Those hubs are canonical.
Install
npm install @fairmint/daml-js
The package declares the DAML JavaScript runtime versions that its generated bindings use. Keep
@daml/ledger and @daml/types compatible with the peer dependency versions reported by npm.
Package surface
The browser-safe root entry point exports generated namespaces including:
import { CantonPayments, Fairmint, Nft } from '@fairmint/daml-js';
const registryTemplate = Fairmint.EquityTokens.EquityRegistry.EquityRegistry;
const paymentFactoryTemplate =
CantonPayments.PaymentStream.PaymentStreamFactory.PaymentStreamFactory;
const nftInterface = Nft.Api.V1.Nft.Nft;
The exact module names are generated from the DAML source. Let TypeScript discover the available templates from the installed package instead of copying package IDs into application code.
Deployed singleton IDs are available through stable JSON subpaths:
import paymentStreamsFactory from '@fairmint/daml-js/paymentStreams-factory-contract-id.json';
import reportsFactory from '@fairmint/daml-js/reports-factory-contract-id.json';
Check package.json for the complete export map. The generated package surface is
also enforced by scripts/test-imports.ts and
scripts/verify-merged-lib-runtime.ts.
Trade desk and holder packages
The transfer agent's trade desk settles secondary trades on the OpenCapTable-v35 register, per
ADR-041
and the
OCP register
product doc. The module headers under TradeSettlement/, TradeSettlementHolder/ and
EquityCertificate/ are the exact contract; the shape is:
TradeSettlementHolder-v01holds the contracts a holder signs or observes (Types,Cash,AllocationRequest,Seller,Buyer) and depends on no OpenCapTable package, so a holder vets no register DAR and sees no register node.TradeSettlement-v01holds the desk (TradeDesk,DeskChecks).npm run check:holder-packages, whichbuildandtestrun first, fails if the holder package, the equity certificate packages or the NFT packages name OpenCapTable.TradeSettlement.TestPrivacychecks what holders see: no desk or register contract among their active contracts and, walking the transaction trees of reserve, settle and release, every register node only under desk nodes. Follow-up, not yet written: the per-party projection test of those transactions on LocalNet, which Daml Script cannot run, pinning that no holder's projection holds an OpenCapTable-v35 node (the design's visibility section asks for it), for example in ta-service's LocalNet tests.- The desk is signed by the cap table's three keys (the issuer, the system operator and the transfer
agent) and created through
TradeDeskAuthorization: the system operator creates it, the transfer agent accepts, then the issuer. The authorization names the desk it replaces and lapses at itsacceptBefore. ta_cashis a transfer agent party separate from the three keys. With the buyer it is the cash leg's executor, so the transfer agent alone can never move the cash.Acceptance_Settleon the buyer'sBuyerAcceptanceis controlled by the issuer, the system operator, the transfer agent andta_cashtogether.TradeDesk_Settleis the only code that exercises it: afterCapTable_Settleit checks the returnedSettleResultfield by field against the accepted terms, and a mismatch rolls back shares and cash together.TradeDesk_Reserveconsumes the seller's stakeholder-and-class instruction besideCapTable_PlaceHoldsand keeps the hold IDs on aTradeHoldRecordno holder sees;TradeDesk_Releaseends a trade throughCapTable_CancelHolds.EquityCertificateis keyed by cap table, stakeholder and stock class, signed by the same three keys, observed by its holder and minted only through the cap table'sEquityCertificateFactory.
In @fairmint/daml-js the modules of both trade packages merge into one Fairmint.TradeSettlement
namespace, while template IDs name the defining package: #TradeSettlementHolder-v01:… for the
holder modules and #TradeSettlement-v01:… for TradeDesk.
Repository layout
multi-package.yamldeclares the active package build graph.- Each package's
daml.yamlis the source of truth for its current name, version, SDK, and DAML dependencies. scripts/contains code generation, package verification, DAR policy, and deployment tooling.dars/anddars/dars.lockretain backed-up DARs and their integrity metadata.generated/andlib/are produced by the build and packaging pipeline; do not treat them as hand-maintained documentation.
Build and validate
Install dependencies and the DAML SDK versions selected by the package manifests:
npm install
npx canton-dev-tools install-dpm-sdks
TradeSettlement-v01 data-depends on the two OpenCapTable DARs pinned in
ocp-dars.json, the reader interfaces (OpenCapTableApi-v01) and the register
(OpenCapTable-v35), at one open-captable-protocol-daml commit. npm run sync-ocp-dars (run before
build, test, lint:daml and check-upgrade-compat) fetches both from that repository and
verifies their SHA-256. To build against local OpenCapTable DARs instead, for example ones not
backed up in that repository yet, set OCP_DAR_PATH to a comma-separated list of them. Each is
matched to the pin whose file is its basename (<package>-<version>.dar, as dpm names it), and a
hash that differs from the pin is reported as a warning.
The TradeSettlement-v01 DAR embeds both OpenCapTable DARs, so uploading it also uploads and vets
them. Release OpenCapTable through open-captable-protocol-daml on a network first, the reader
interfaces and then the register: npm run upload-dar refuses TradeSettlement until that
repository has the dar-deploy/<network>/<package>/v<version> tag of each of the two DARs. The desk
also embeds TradeSettlementHolder-v01 and the equity certificate and NFT packages, and
upload-dar refuses any package that embeds another package of this repository until that package
has its own dar-deploy/<network>/<package>/v<version> tag here. Upload them first, each through
its own run of the upload workflow; the refusal lists them in dependency order.
Other repositories that need these DARs (for example ta-service's LocalNet suites) install them from
the private @fairmint/daml-dars package (npm-dars/) at a pinned version
instead of vendoring them or cloning this repository. It carries the backed-up DARs of the
settlement packages, verified against dars/dars.lock. npm run stage:npm-dars regenerates its
manifest when a DAR changes and npm run check:npm-dars (CI) enforces it, with a version bump.
Merging a bump to main publishes it through npm trusted publishing (publish-dars.yml).
@fairmint/daml-js itself still ships no DARs.
The normal local validation path is:
npm run build
npm test
When generated bindings or the published npm surface are affected, also run:
npm run codegen
npm run verify-package
See package.json and the selected script's source for specialized checks and the
exact command interface.