Daml contracts
The on-chain surface — five templates and the choices that move collateral.
server/contracts — Daml. The ledger holds custody and commitments, nothing else. Matching is
off-chain by design.
Templates
Owned by the operator. Holds locked collateral for the venue.
Choices: accept a deposit (issuing a DepositReceipt), approve or reject a WithdrawalRequest,
submit a BatchManifest.
Titan is mono-operator today — GET /v1/vault returns the single active vault, while
GET /v1/vaults/:operator anticipates the multi-operator case.
Evidence that a trader locked collateral. Produced when the deposit choice is exercised, observed
by the indexer, and credited by the engine as inbound.deposit.
No approval step — the collateral is already locked, so the only latency is ledger finality plus indexer lag.
A trader's request to release collateral, carrying the current withdrawal counter as a nonce.
The engine evaluates it against free collateral at the last committed batch, then submits
engine.approve_submitted or engine.reject_submitted. On approval the vault releases and the
counter increments — which is what makes a captured request unusable a second time.
A per-user merkle root for one cadence window, chained to that user's previous batch.
The chain is the point: a user can walk their whole history hash by hash, and dropping or
reordering an interval breaks it. GET /v1/users/:party/user-batches returns them oldest-first so
the chain can be verified in order.
The global merkle root for a cadence window, numbered by batchNum. Each UserBatch root is a
leaf of this tree.
This is the venue's public commitment to what happened off-chain in that window.
Building
cd server/contracts
daml build # multi-package.yaml drives the buildThen upload the DAR, create the Vault, and seed counters — the first step of the engine
quickstart.
Verification surface
Because commitments are on-chain and the engine's leaves are readable through the BFF, the two can be compared without trusting either:
curl 'http://localhost:4000/v1/verifications/user-batches?status=mismatch'
curl 'http://localhost:4000/v1/verifications/manifests?status=mismatch'A non-empty mismatch list is an incident, not a warning: the off-chain engine and the on-chain commitment disagree about what was traded.
Auditor retrofit
An auditor party can be added as a read-only observer on manifests, giving a third party the ability to run the same cross-checks continuously without any trading capability.
Out of scope for v1
Cross-margin across operators, on-chain matching, and permissionless market creation. All three change the trust model rather than extending it, so they are deliberately deferred rather than partially implemented.