cantonjs 0.0.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +395 -0
  2. package/dist/cjs/auth/index.d.ts +2 -0
  3. package/dist/cjs/auth/index.d.ts.map +1 -0
  4. package/dist/cjs/auth/index.js +3 -0
  5. package/dist/cjs/auth/index.js.map +1 -0
  6. package/dist/cjs/auth/types.d.ts +27 -0
  7. package/dist/cjs/auth/types.d.ts.map +1 -0
  8. package/dist/cjs/auth/types.js +3 -0
  9. package/dist/cjs/auth/types.js.map +1 -0
  10. package/dist/cjs/chains/definitions.d.ts +5 -11
  11. package/dist/cjs/chains/definitions.d.ts.map +1 -1
  12. package/dist/cjs/chains/definitions.js +59 -13
  13. package/dist/cjs/chains/definitions.js.map +1 -1
  14. package/dist/cjs/chains/index.d.ts +2 -1
  15. package/dist/cjs/chains/index.d.ts.map +1 -1
  16. package/dist/cjs/chains/index.js +19 -6
  17. package/dist/cjs/chains/index.js.map +1 -1
  18. package/dist/cjs/chains/presets.d.ts +59 -0
  19. package/dist/cjs/chains/presets.d.ts.map +1 -0
  20. package/dist/cjs/chains/presets.js +55 -0
  21. package/dist/cjs/chains/presets.js.map +1 -0
  22. package/dist/cjs/errors/auth.d.ts +6 -0
  23. package/dist/cjs/errors/auth.d.ts.map +1 -1
  24. package/dist/cjs/errors/auth.js +17 -1
  25. package/dist/cjs/errors/auth.js.map +1 -1
  26. package/dist/cjs/errors/index.d.ts +1 -1
  27. package/dist/cjs/errors/index.d.ts.map +1 -1
  28. package/dist/cjs/errors/index.js +2 -1
  29. package/dist/cjs/errors/index.js.map +1 -1
  30. package/dist/cjs/index.d.ts +5 -4
  31. package/dist/cjs/index.d.ts.map +1 -1
  32. package/dist/cjs/index.js +9 -6
  33. package/dist/cjs/index.js.map +1 -1
  34. package/dist/cjs/testing/setupSandbox.d.ts +11 -1
  35. package/dist/cjs/testing/setupSandbox.d.ts.map +1 -1
  36. package/dist/cjs/testing/setupSandbox.js +25 -13
  37. package/dist/cjs/testing/setupSandbox.js.map +1 -1
  38. package/dist/cjs/transport/grpc.d.ts +2 -4
  39. package/dist/cjs/transport/grpc.d.ts.map +1 -1
  40. package/dist/cjs/transport/grpc.js +28 -16
  41. package/dist/cjs/transport/grpc.js.map +1 -1
  42. package/dist/cjs/transport/index.d.ts +1 -1
  43. package/dist/cjs/transport/index.d.ts.map +1 -1
  44. package/dist/cjs/transport/json-api.d.ts +1 -1
  45. package/dist/cjs/transport/json-api.d.ts.map +1 -1
  46. package/dist/cjs/transport/json-api.js +19 -5
  47. package/dist/cjs/transport/json-api.js.map +1 -1
  48. package/dist/cjs/transport/types.d.ts +13 -3
  49. package/dist/cjs/transport/types.d.ts.map +1 -1
  50. package/dist/cjs/transport/types.js +40 -0
  51. package/dist/cjs/transport/types.js.map +1 -1
  52. package/dist/esm/auth/index.d.ts +2 -0
  53. package/dist/esm/auth/index.d.ts.map +1 -0
  54. package/dist/esm/auth/index.js +2 -0
  55. package/dist/esm/auth/index.js.map +1 -0
  56. package/dist/esm/auth/types.d.ts +27 -0
  57. package/dist/esm/auth/types.d.ts.map +1 -0
  58. package/dist/esm/auth/types.js +2 -0
  59. package/dist/esm/auth/types.js.map +1 -0
  60. package/dist/esm/chains/definitions.d.ts +5 -11
  61. package/dist/esm/chains/definitions.d.ts.map +1 -1
  62. package/dist/esm/chains/definitions.js +59 -13
  63. package/dist/esm/chains/definitions.js.map +1 -1
  64. package/dist/esm/chains/index.d.ts +2 -1
  65. package/dist/esm/chains/index.d.ts.map +1 -1
  66. package/dist/esm/chains/index.js +2 -1
  67. package/dist/esm/chains/index.js.map +1 -1
  68. package/dist/esm/chains/presets.d.ts +59 -0
  69. package/dist/esm/chains/presets.d.ts.map +1 -0
  70. package/dist/esm/chains/presets.js +51 -0
  71. package/dist/esm/chains/presets.js.map +1 -0
  72. package/dist/esm/errors/auth.d.ts +6 -0
  73. package/dist/esm/errors/auth.d.ts.map +1 -1
  74. package/dist/esm/errors/auth.js +15 -0
  75. package/dist/esm/errors/auth.js.map +1 -1
  76. package/dist/esm/errors/index.d.ts +1 -1
  77. package/dist/esm/errors/index.d.ts.map +1 -1
  78. package/dist/esm/errors/index.js +1 -1
  79. package/dist/esm/errors/index.js.map +1 -1
  80. package/dist/esm/index.d.ts +5 -4
  81. package/dist/esm/index.d.ts.map +1 -1
  82. package/dist/esm/index.js +2 -2
  83. package/dist/esm/index.js.map +1 -1
  84. package/dist/esm/testing/setupSandbox.d.ts +11 -1
  85. package/dist/esm/testing/setupSandbox.d.ts.map +1 -1
  86. package/dist/esm/testing/setupSandbox.js +25 -14
  87. package/dist/esm/testing/setupSandbox.js.map +1 -1
  88. package/dist/esm/transport/grpc.d.ts +2 -4
  89. package/dist/esm/transport/grpc.d.ts.map +1 -1
  90. package/dist/esm/transport/grpc.js +28 -16
  91. package/dist/esm/transport/grpc.js.map +1 -1
  92. package/dist/esm/transport/index.d.ts +1 -1
  93. package/dist/esm/transport/index.d.ts.map +1 -1
  94. package/dist/esm/transport/json-api.d.ts +1 -1
  95. package/dist/esm/transport/json-api.d.ts.map +1 -1
  96. package/dist/esm/transport/json-api.js +19 -5
  97. package/dist/esm/transport/json-api.js.map +1 -1
  98. package/dist/esm/transport/types.d.ts +13 -3
  99. package/dist/esm/transport/types.d.ts.map +1 -1
  100. package/dist/esm/transport/types.js +38 -1
  101. package/dist/esm/transport/types.js.map +1 -1
  102. package/dist/tsconfig.build.tsbuildinfo +1 -1
  103. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  104. package/package.json +12 -2
  105. package/src/auth/index.ts +7 -0
  106. package/src/auth/types.ts +30 -0
  107. package/src/chains/definitions.ts +77 -22
  108. package/src/chains/index.ts +2 -1
  109. package/src/chains/presets.ts +121 -0
  110. package/src/errors/auth.ts +16 -0
  111. package/src/errors/index.ts +1 -1
  112. package/src/index.ts +34 -7
  113. package/src/testing/setupSandbox.ts +45 -17
  114. package/src/transport/grpc.ts +33 -19
  115. package/src/transport/index.ts +7 -1
  116. package/src/transport/json-api.ts +24 -7
  117. package/src/transport/types.ts +63 -3
package/README.md ADDED
@@ -0,0 +1,395 @@
1
+ <p align="center">
2
+ <strong>cantonjs</strong>
3
+ </p>
4
+
5
+ <p align="center">
6
+ TypeScript interface for the Canton Network &mdash; <em>viem for Canton</em>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/merged-one/cantonjs/actions/workflows/ci.yml"><img src="https://github.com/merged-one/cantonjs/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
11
+ <a href="https://www.npmjs.com/package/cantonjs"><img src="https://img.shields.io/npm/v/cantonjs.svg" alt="npm version" /></a>
12
+ <a href="https://www.npmjs.com/package/cantonjs"><img src="https://img.shields.io/npm/dm/cantonjs.svg" alt="npm downloads" /></a>
13
+ <a href="https://github.com/merged-one/cantonjs/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License" /></a>
14
+ <a href="https://img.shields.io/bundlephobia/minzip/cantonjs"><img src="https://img.shields.io/bundlephobia/minzip/cantonjs" alt="Bundle size" /></a>
15
+ </p>
16
+
17
+ ---
18
+
19
+ cantonjs is a modern, type-safe TypeScript library for the [Canton Network](https://www.canton.network/) Ledger API V2. It provides tree-shakeable function exports, real-time WebSocket streaming, structured errors, and first-class testing support.
20
+
21
+ **Companion CLI:** [cantonctl](https://github.com/merged-one/cantonctl) ("Hardhat for Canton")
22
+
23
+ Development policy: the included runtime surface is gated at 100% statements, branches, functions, and lines, and every coverage exclusion or inline `v8 ignore` must be justified in [`EXCLUSIONS.md`](./EXCLUSIONS.md).
24
+
25
+ ## Features
26
+
27
+ - **Function exports, not classes** &mdash; tree-shakeable, ESM + CJS dual build
28
+ - **Type-safe codegen** &mdash; generate TypeScript from Daml DAR files
29
+ - **Real-time streaming** &mdash; AsyncIterator WebSocket streams with auto-reconnect
30
+ - **React hooks** &mdash; TanStack Query-powered hooks via [cantonjs-react](#cantonjs-react)
31
+ - **Splice ecosystem packages** &mdash; public Scan, Validator ANS, Token Standard, and wallet-boundary integrations
32
+ - **First-class testing** &mdash; mock transports, recording transports, Canton sandbox fixtures
33
+ - **Structured errors** &mdash; error codes, recovery hints, traversable cause chains
34
+ - **Zero runtime dependencies** &mdash; transports are injected, not bundled
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ npm install cantonjs
40
+ ```
41
+
42
+ ## Package Map
43
+
44
+ The repo is now split into a stable Canton core plus focused Splice add-on packages.
45
+
46
+ | Package | Stability | Purpose |
47
+ | ------- | --------- | ------- |
48
+ | `cantonjs` | GA | Canton Ledger API V2 clients, transports, chains, streaming, errors, and codegen runtime types |
49
+ | `cantonjs-codegen` | GA | DAR-to-TypeScript code generation |
50
+ | `cantonjs-react` | GA | React hooks for participant-private ledger data |
51
+ | `cantonjs-splice-scan` | GA | Public Scan reads for DSO metadata, update history, and public ANS lookups |
52
+ | `cantonjs-splice-validator` | GA + legacy compatibility | Validator ANS, filtered GA Scan Proxy reads, and legacy wallet compatibility flows |
53
+ | `cantonjs-splice-interfaces` | GA | Stable Splice Daml interface descriptors and generated types |
54
+ | `cantonjs-splice-token-standard` | GA | Ledger-centric CIP-0056 helpers for new token transfer and allocation flows |
55
+ | `cantonjs-wallet-adapters` | Experimental | CIP-0103 wallet boundary adapters for browser and SDK interop |
56
+
57
+ ## Stability Tiers
58
+
59
+ - **GA**: Covered by the normal semver promise for the pinned release line.
60
+ - **Legacy compatibility**: Still supported for existing integrations, but not the recommended starting point for new work.
61
+ - **Experimental**: May break in minor releases while the upstream surface is still moving.
62
+
63
+ Current compatibility target:
64
+
65
+ - **Canton GA line:** `3.4.x`
66
+ - **Splice GA line:** `0.5.x`
67
+ - **Vendored Splice artifacts:** `0.5.17`
68
+ - **Legacy wallet note:** `createLegacyWalletClient()` exists for old `wallet-external` flows, but new transfer flows should use `cantonjs-splice-token-standard`.
69
+
70
+ See [compatibility policy](./docs/compatibility.md) and [migration notes](./docs/MIGRATING_TO_SPLICE_SUPPORT.md).
71
+
72
+ ## Quick Start
73
+
74
+ ```typescript
75
+ import { createLedgerClient, jsonApi } from 'cantonjs'
76
+
77
+ // 1. Create a transport
78
+ const transport = jsonApi({
79
+ url: 'http://localhost:7575',
80
+ token: 'your-jwt-token',
81
+ })
82
+
83
+ // 2. Create a party-scoped client
84
+ const client = createLedgerClient({
85
+ transport,
86
+ actAs: 'Alice::1234',
87
+ })
88
+
89
+ // 3. Create a contract
90
+ const created = await client.createContract('#my-pkg:Main:Asset', {
91
+ owner: 'Alice',
92
+ value: '100',
93
+ })
94
+
95
+ // 4. Exercise a choice
96
+ const tx = await client.exerciseChoice('#my-pkg:Main:Asset', created.contractId, 'Transfer', {
97
+ newOwner: 'Bob',
98
+ })
99
+
100
+ // 5. Query active contracts
101
+ const contracts = await client.queryContracts('#my-pkg:Main:Asset')
102
+ ```
103
+
104
+ Static bearer tokens remain supported. For request-scoped auth, provide an async token or session provider:
105
+
106
+ ```typescript
107
+ import { createLedgerClient, jsonApi, type AuthProvider } from 'cantonjs'
108
+
109
+ const auth: AuthProvider = async ({ request }) => {
110
+ if (request.path.startsWith('/v2/state/')) return undefined
111
+ return await getFreshJwtForAudience('participant')
112
+ }
113
+
114
+ const transport = jsonApi({
115
+ url: 'http://localhost:7575',
116
+ auth,
117
+ })
118
+
119
+ const client = createLedgerClient({
120
+ transport,
121
+ actAs: 'Alice::1234',
122
+ })
123
+ ```
124
+
125
+ ## Streaming
126
+
127
+ Subscribe to real-time updates with auto-reconnect and offset tracking:
128
+
129
+ ```typescript
130
+ import { streamUpdates } from 'cantonjs'
131
+
132
+ const controller = new AbortController()
133
+
134
+ for await (const update of streamUpdates(transport, {
135
+ beginExclusive: '0',
136
+ signal: controller.signal,
137
+ })) {
138
+ console.log('Update:', update.updateId)
139
+ }
140
+ ```
141
+
142
+ ## Subpath Imports
143
+
144
+ Import only what you need for smaller bundles:
145
+
146
+ ```typescript
147
+ import { createLedgerClient } from 'cantonjs/ledger'
148
+ import { createAdminClient } from 'cantonjs/admin'
149
+ import { createTestClient } from 'cantonjs/testing'
150
+ import { localNet, devNet, testNet, mainNet, withChainOverrides } from 'cantonjs/chains'
151
+ import type { TemplateDescriptor, InferPayload } from 'cantonjs/codegen'
152
+ ```
153
+
154
+ ## Network Presets
155
+
156
+ Built-in public presets are discovery-first. They carry public Scan discovery metadata, auth audience hints, and the pinned Splice release line, but they do not commit operator-specific participant or validator URLs.
157
+
158
+ Layer concrete deployment settings on top:
159
+
160
+ ```typescript
161
+ import { devNet, withChainOverrides } from 'cantonjs/chains'
162
+
163
+ const chain = withChainOverrides(devNet, {
164
+ participant: {
165
+ jsonApiUrl: process.env.CANTON_JSON_API_URL,
166
+ },
167
+ scan: {
168
+ url: process.env.SPLICE_SCAN_URL,
169
+ },
170
+ validator: {
171
+ apiBaseUrl: process.env.SPLICE_VALIDATOR_URL,
172
+ },
173
+ })
174
+ ```
175
+
176
+ `chain.scan.discoveryRoot` remains available when you need to resolve a live public Scan deployment from operator documentation first.
177
+
178
+ ## Clients
179
+
180
+ | Client | Purpose |
181
+ | ---------------------- | ------------------------------------------------------------------- |
182
+ | `createLedgerClient()` | Party-scoped contract operations (create, exercise, query, stream) |
183
+ | `createAdminClient()` | Node administration (parties, users, packages, IDP) |
184
+ | `createTestClient()` | Sandbox testing (time control, party allocation, sandbox lifecycle) |
185
+
186
+ ## Transports
187
+
188
+ | Transport | Description |
189
+ | ---------------------------------- | ------------------------------------------------------------------------------------- |
190
+ | `jsonApi({ url, token })` | HTTP transport for Canton JSON API V2 with static bearer auth |
191
+ | `jsonApi({ url, auth })` | HTTP transport with async per-request token lookup |
192
+ | `jsonApi({ url, session })` | HTTP transport with async per-request token and header injection |
193
+ | `grpc({ grpcTransport, token })` | gRPC via injected ConnectRPC client with static bearer auth |
194
+ | `grpc({ grpcTransport, auth })` | gRPC via injected ConnectRPC client with async per-request token lookup |
195
+ | `grpc({ grpcTransport, session })` | gRPC via injected ConnectRPC client with async per-request token and header injection |
196
+ | `fallback({ transports })` | Failover across multiple transports |
197
+
198
+ ## Error Handling
199
+
200
+ Every error is a `CantonjsError` with a machine-readable code, recovery hints, and a traversable cause chain:
201
+
202
+ ```typescript
203
+ import { CommandRejectedError, TokenExpiredError } from 'cantonjs'
204
+
205
+ try {
206
+ await client.createContract(templateId, args)
207
+ } catch (error) {
208
+ if (error instanceof TokenExpiredError) {
209
+ // error.code === 'CJ2001'
210
+ // error.metaMessages === ['Refresh your JWT token']
211
+ }
212
+ }
213
+ ```
214
+
215
+ | Range | Domain |
216
+ | ------ | ------------------------------------------- |
217
+ | CJ1xxx | Transport (connection, HTTP, gRPC, timeout) |
218
+ | CJ2xxx | Authentication (JWT, token lifecycle) |
219
+ | CJ3xxx | Ledger (command rejection, authorization) |
220
+ | CJ4xxx | Admin (party, user, package management) |
221
+ | CJ5xxx | Streaming (WebSocket, reconnection) |
222
+ | CJ6xxx | Codegen (type mismatch, generation) |
223
+
224
+ ## Packages
225
+
226
+ ### cantonjs-codegen
227
+
228
+ Generate TypeScript types from Daml DAR files:
229
+
230
+ ```bash
231
+ npm install --save-dev cantonjs-codegen
232
+
233
+ npx cantonjs-codegen --dar ./model.dar --output ./src/generated
234
+ ```
235
+
236
+ Records become type aliases, variants become discriminated unions, templates become companion const objects with `templateId` and choices. See [packages/cantonjs-codegen](./packages/cantonjs-codegen/).
237
+
238
+ ### cantonjs-react
239
+
240
+ React hooks for Canton dApps, powered by TanStack Query:
241
+
242
+ ```bash
243
+ npm install cantonjs-react @tanstack/react-query
244
+ ```
245
+
246
+ ```tsx
247
+ import { createLedgerClient, jsonApi } from 'cantonjs'
248
+ import { CantonProvider, useContracts, useCreateContract } from 'cantonjs-react'
249
+
250
+ const client = createLedgerClient({
251
+ transport: jsonApi({ url: 'http://localhost:7575', token: 'your-jwt-token' }),
252
+ actAs: 'Alice::1234',
253
+ })
254
+
255
+ function App() {
256
+ return (
257
+ <CantonProvider client={client}>
258
+ <AssetList />
259
+ </CantonProvider>
260
+ )
261
+ }
262
+
263
+ function AssetList() {
264
+ const { data: assets, isLoading } = useContracts({
265
+ templateId: '#my-pkg:Main:Asset',
266
+ })
267
+
268
+ const { mutate: create } = useCreateContract({
269
+ templateId: '#my-pkg:Main:Asset',
270
+ })
271
+
272
+ if (isLoading) return <div>Loading...</div>
273
+
274
+ return (
275
+ <div>
276
+ <button onClick={() => create({ createArguments: { owner: 'Alice', value: '100' } })}>
277
+ Create
278
+ </button>
279
+ <ul>
280
+ {assets?.map((c) => (
281
+ <li key={c.createdEvent.contractId}>{JSON.stringify(c.createdEvent.createArgument)}</li>
282
+ ))}
283
+ </ul>
284
+ </div>
285
+ )
286
+ }
287
+ ```
288
+
289
+ See [packages/cantonjs-react](./packages/cantonjs-react/).
290
+
291
+ `cantonjs-react` stays focused on participant-private ledger state. For public Splice data, use TanStack Query directly with `cantonjs-splice-scan`; see [docs/examples/react.md](./docs/examples/react.md).
292
+
293
+ ### Splice Packages
294
+
295
+ - `cantonjs-splice-scan` &mdash; GA public Scan reads for DSO metadata, updates, and public ANS lookups. Experimental Scan routes stay behind `cantonjs-splice-scan/experimental`. See [docs/guide/scan.md](./docs/guide/scan.md).
296
+ - `cantonjs-splice-validator` &mdash; GA validator ANS plus the filtered GA Scan Proxy subset. `createLegacyWalletClient()` is legacy compatibility only and is not recommended for new transfer flows. See [docs/guide/validator-ans.md](./docs/guide/validator-ans.md).
297
+ - `cantonjs-splice-token-standard` and `cantonjs-splice-interfaces` &mdash; GA stable CIP-0056 descriptors and ledger-centric helpers for new transfer and allocation flows. See [docs/guide/token-standard.md](./docs/guide/token-standard.md).
298
+ - `cantonjs-wallet-adapters` &mdash; experimental CIP-0103 wallet boundary adapters for browser and SDK interop. See [docs/guide/wallet-adapters.md](./docs/guide/wallet-adapters.md).
299
+
300
+ ## Testing
301
+
302
+ cantonjs provides first-class testing utilities. No `vi.mock()` needed &mdash; all dependencies are injected:
303
+
304
+ ```typescript
305
+ import { createLedgerClient } from 'cantonjs'
306
+ import { createMockTransport } from 'cantonjs/testing'
307
+
308
+ const transport = createMockTransport({
309
+ responses: [{ contractId: 'contract-1', templateId: '#pkg:Mod:T' }],
310
+ })
311
+
312
+ const client = createLedgerClient({ transport, actAs: 'Alice::1234' })
313
+ const created = await client.createContract('#pkg:Mod:T', { owner: 'Alice' })
314
+ ```
315
+
316
+ Integration testing with a real Canton sandbox:
317
+
318
+ ```typescript
319
+ import { setupCantonSandbox } from 'cantonjs/testing'
320
+
321
+ const sandbox = await setupCantonSandbox()
322
+ // sandbox.client is a fully configured TestClient
323
+ ```
324
+
325
+ ## Canton Concepts
326
+
327
+ | Concept | Description |
328
+ | ---------------- | ------------------------------------------------------------ |
329
+ | **Party** | Identity unit (not an address), permissions via JWT |
330
+ | **Template** | Daml contract definition (`packageId:moduleName:entityName`) |
331
+ | **Choice** | Operation on a contract (like a function call) |
332
+ | **ContractId** | Unique UTXO-style identifier for a contract instance |
333
+ | **DAR** | Daml Archive &mdash; the deployment artifact |
334
+ | **Synchronizer** | Consensus domain for transaction ordering |
335
+
336
+ ## Bundle Size
337
+
338
+ cantonjs is designed for minimal footprint:
339
+
340
+ | Entry Point | Size (minified + brotli) |
341
+ | ----------------- | ------------------------ |
342
+ | `cantonjs` | 5.78 kB |
343
+ | `cantonjs/ledger` | 1.1 KB |
344
+
345
+ ## Requirements
346
+
347
+ - Node.js >= 18
348
+ - TypeScript >= 5.0.4 (optional peer dependency)
349
+
350
+ ## Development
351
+
352
+ ```bash
353
+ git clone https://github.com/merged-one/cantonjs.git
354
+ cd cantonjs
355
+ npm install
356
+
357
+ npm test # Run root tests
358
+ npm run test:coverage # Enforced root coverage gate
359
+ npm run test:coverage:all # Root + package coverage gates
360
+ npm run verify:ci:pr # Full PR validation suite
361
+ npm run typecheck # Type-check
362
+ npm run lint # Lint
363
+ npm run build # Build ESM + CJS + types
364
+ npm run size # Bundle size audit
365
+ npm run docs:dev # Start docs dev server
366
+ ```
367
+
368
+ ## Contributing
369
+
370
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup, coding conventions, and pull request guidelines.
371
+
372
+ ## Architecture Decisions
373
+
374
+ Design decisions are documented as Architecture Decision Records (ADRs):
375
+
376
+ | ADR | Topic |
377
+ | ------------------------------------------------------ | -------------------------------- |
378
+ | [0001](./docs/adr/0001-typescript-function-exports.md) | TypeScript with function exports |
379
+ | [0002](./docs/adr/0002-transport-abstraction.md) | Transport abstraction |
380
+ | [0003](./docs/adr/0003-party-scoped-clients.md) | Party-scoped client architecture |
381
+ | [0004](./docs/adr/0004-structured-error-model.md) | Structured error model |
382
+ | [0005](./docs/adr/0005-streaming-architecture.md) | Streaming architecture |
383
+ | [0006](./docs/adr/0006-testing-strategy.md) | Testing strategy |
384
+ | [0007](./docs/adr/0007-codegen-architecture.md) | Codegen architecture |
385
+ | [0008](./docs/adr/0008-react-integration.md) | React integration |
386
+
387
+ ## Related
388
+
389
+ - [cantonctl](https://github.com/merged-one/cantonctl) &mdash; CLI tooling for Canton ("Hardhat for Canton")
390
+ - [Canton Network](https://www.canton.network/) &mdash; The Canton Network
391
+ - [Canton Docs](https://docs.digitalasset.com/) &mdash; Official Canton documentation
392
+
393
+ ## License
394
+
395
+ [Apache-2.0](./LICENSE)
@@ -0,0 +1,2 @@
1
+ export type { MaybePromise, AuthContext, AuthSession, AuthProvider, SessionProvider, } from './types.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ export type MaybePromise<T> = T | Promise<T>;
2
+ /** Request metadata exposed to auth/session providers. */
3
+ export type AuthContext = {
4
+ /** Transport type making the request, e.g. json-api or grpc. */
5
+ readonly transport: string;
6
+ /** Base URL for the target Canton endpoint. */
7
+ readonly url: string;
8
+ /** HTTP-style request metadata for the current transport call. */
9
+ readonly request: {
10
+ readonly method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
11
+ readonly path: string;
12
+ readonly headers?: Readonly<Record<string, string>>;
13
+ readonly signal?: AbortSignal;
14
+ };
15
+ };
16
+ /** A resolved auth session for a single request. */
17
+ export type AuthSession = {
18
+ /** Bearer token to attach as Authorization header. */
19
+ readonly token?: string;
20
+ /** Additional headers to attach for the current request. */
21
+ readonly headers?: Readonly<Record<string, string>>;
22
+ };
23
+ /** Per-request bearer token provider. */
24
+ export type AuthProvider = (context: AuthContext) => MaybePromise<string | undefined>;
25
+ /** Per-request session provider for auth headers and bearer tokens. */
26
+ export type SessionProvider = (context: AuthContext) => MaybePromise<AuthSession | undefined>;
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAE5C,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG;IACxB,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;QACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;QACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAC9B,CAAA;CACF,CAAA;AAED,oDAAoD;AACpD,MAAM,MAAM,WAAW,GAAG;IACxB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACpD,CAAA;AAED,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,YAAY,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;AAErF,uEAAuE;AACvE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,YAAY,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/auth/types.ts"],"names":[],"mappings":""}
@@ -1,18 +1,12 @@
1
1
  /**
2
2
  * Canton network chain definitions.
3
3
  *
4
- * Pre-configured connection details for Canton network environments.
5
- * Similar to viem's chain definitions (mainnet, sepolia, etc.).
4
+ * Public environments default to discovery-first metadata. Consumers can
5
+ * layer in deployment-specific participant, Scan, or validator URLs with
6
+ * `withChainOverrides()` without committing operator-specific endpoints.
6
7
  */
7
- export type CantonChain = {
8
- readonly id: string;
9
- readonly name: string;
10
- readonly network: 'localnet' | 'devnet' | 'testnet' | 'mainnet';
11
- readonly jsonApiUrl?: string;
12
- readonly grpcUrl?: string;
13
- readonly scanUrl?: string;
14
- readonly resetCycle?: string;
15
- };
8
+ import { type CantonChain } from './presets.js';
9
+ export type { CantonAuthAudienceHints, CantonChain, CantonChainOverrides, CantonChainPresetInput, CantonNetwork, CantonParticipantEndpoints, CantonScanEndpoints, CantonSpliceMetadata, CantonValidatorEndpoints, } from './presets.js';
16
10
  export declare const localNet: CantonChain;
17
11
  export declare const devNet: CantonChain;
18
12
  export declare const testNet: CantonChain;
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../../src/chains/definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAA;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,WAMtB,CAAA;AAED,eAAO,MAAM,MAAM,EAAE,WAKpB,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,WAIrB,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,WAIrB,CAAA"}
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../../src/chains/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAElE,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,EACb,0BAA0B,EAC1B,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAWrB,eAAO,MAAM,QAAQ,EAAE,WAWrB,CAAA;AAEF,eAAO,MAAM,MAAM,EAAE,WAiBnB,CAAA;AAEF,eAAO,MAAM,OAAO,EAAE,WAiBpB,CAAA;AAEF,eAAO,MAAM,OAAO,EAAE,WAepB,CAAA"}
@@ -2,32 +2,78 @@
2
2
  /**
3
3
  * Canton network chain definitions.
4
4
  *
5
- * Pre-configured connection details for Canton network environments.
6
- * Similar to viem's chain definitions (mainnet, sepolia, etc.).
5
+ * Public environments default to discovery-first metadata. Consumers can
6
+ * layer in deployment-specific participant, Scan, or validator URLs with
7
+ * `withChainOverrides()` without committing operator-specific endpoints.
7
8
  */
8
9
  Object.defineProperty(exports, "__esModule", { value: true });
9
10
  exports.mainNet = exports.testNet = exports.devNet = exports.localNet = void 0;
10
- exports.localNet = {
11
+ const presets_js_1 = require("./presets.js");
12
+ const SPLICE_DISCOVERY_ROOT = 'https://docs.global.canton.network.sync.global';
13
+ const SPLICE_RELEASE_LINE = '0.5';
14
+ const PARTICIPANT_AUDIENCE_HINT = 'https://daml.com/participant/jwt/aud/participant/<participant-id>';
15
+ const PUBLIC_SCAN_AUDIENCE_HINT = 'Public Scan is often anonymous; if a token is required, use the operator-published audience.';
16
+ const VALIDATOR_AUDIENCE_HINT = 'Validator API audiences are operator-specific and should come from your validator or wallet provider.';
17
+ exports.localNet = (0, presets_js_1.defineChainPreset)({
11
18
  id: 'canton-localnet',
12
19
  name: 'Canton LocalNet',
13
20
  network: 'localnet',
14
- jsonApiUrl: 'http://localhost:7575',
15
- grpcUrl: 'http://localhost:6865',
16
- };
17
- exports.devNet = {
21
+ participant: {
22
+ jsonApiUrl: 'http://localhost:7575',
23
+ grpcUrl: 'http://localhost:6865',
24
+ },
25
+ authAudiences: {
26
+ participant: PARTICIPANT_AUDIENCE_HINT,
27
+ },
28
+ });
29
+ exports.devNet = (0, presets_js_1.defineChainPreset)({
18
30
  id: 'canton-devnet',
19
31
  name: 'Canton DevNet',
20
32
  network: 'devnet',
21
- resetCycle: 'Every 3 months',
22
- };
23
- exports.testNet = {
33
+ scan: {
34
+ discoveryRoot: SPLICE_DISCOVERY_ROOT,
35
+ },
36
+ authAudiences: {
37
+ participant: PARTICIPANT_AUDIENCE_HINT,
38
+ scan: PUBLIC_SCAN_AUDIENCE_HINT,
39
+ validator: VALIDATOR_AUDIENCE_HINT,
40
+ },
41
+ splice: {
42
+ releaseLine: SPLICE_RELEASE_LINE,
43
+ resetCycleNote: 'Public dev deployments may reset during release-line rollovers or operator maintenance.',
44
+ },
45
+ });
46
+ exports.testNet = (0, presets_js_1.defineChainPreset)({
24
47
  id: 'canton-testnet',
25
48
  name: 'Canton TestNet',
26
49
  network: 'testnet',
27
- };
28
- exports.mainNet = {
50
+ scan: {
51
+ discoveryRoot: SPLICE_DISCOVERY_ROOT,
52
+ },
53
+ authAudiences: {
54
+ participant: PARTICIPANT_AUDIENCE_HINT,
55
+ scan: PUBLIC_SCAN_AUDIENCE_HINT,
56
+ validator: VALIDATOR_AUDIENCE_HINT,
57
+ },
58
+ splice: {
59
+ releaseLine: SPLICE_RELEASE_LINE,
60
+ resetCycleNote: 'Treat public test environments as resettable and resolve live endpoints from operator docs.',
61
+ },
62
+ });
63
+ exports.mainNet = (0, presets_js_1.defineChainPreset)({
29
64
  id: 'canton-mainnet',
30
65
  name: 'Canton MainNet',
31
66
  network: 'mainnet',
32
- };
67
+ scan: {
68
+ discoveryRoot: SPLICE_DISCOVERY_ROOT,
69
+ },
70
+ authAudiences: {
71
+ participant: PARTICIPANT_AUDIENCE_HINT,
72
+ scan: PUBLIC_SCAN_AUDIENCE_HINT,
73
+ validator: VALIDATOR_AUDIENCE_HINT,
74
+ },
75
+ splice: {
76
+ releaseLine: SPLICE_RELEASE_LINE,
77
+ },
78
+ });
33
79
  //# sourceMappingURL=definitions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../../src/chains/definitions.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAYU,QAAA,QAAQ,GAAgB;IACnC,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,UAAU;IACnB,UAAU,EAAE,uBAAuB;IACnC,OAAO,EAAE,uBAAuB;CACjC,CAAA;AAEY,QAAA,MAAM,GAAgB;IACjC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,QAAQ;IACjB,UAAU,EAAE,gBAAgB;CAC7B,CAAA;AAEY,QAAA,OAAO,GAAgB;IAClC,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;CACnB,CAAA;AAEY,QAAA,OAAO,GAAgB;IAClC,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;CACnB,CAAA"}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../../src/chains/definitions.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,6CAAkE;AAclE,MAAM,qBAAqB,GAAG,gDAAgD,CAAA;AAC9E,MAAM,mBAAmB,GAAG,KAAK,CAAA;AACjC,MAAM,yBAAyB,GAC7B,mEAAmE,CAAA;AACrE,MAAM,yBAAyB,GAC7B,8FAA8F,CAAA;AAChG,MAAM,uBAAuB,GAC3B,uGAAuG,CAAA;AAE5F,QAAA,QAAQ,GAAgB,IAAA,8BAAiB,EAAC;IACrD,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,UAAU;IACnB,WAAW,EAAE;QACX,UAAU,EAAE,uBAAuB;QACnC,OAAO,EAAE,uBAAuB;KACjC;IACD,aAAa,EAAE;QACb,WAAW,EAAE,yBAAyB;KACvC;CACF,CAAC,CAAA;AAEW,QAAA,MAAM,GAAgB,IAAA,8BAAiB,EAAC;IACnD,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE;QACJ,aAAa,EAAE,qBAAqB;KACrC;IACD,aAAa,EAAE;QACb,WAAW,EAAE,yBAAyB;QACtC,IAAI,EAAE,yBAAyB;QAC/B,SAAS,EAAE,uBAAuB;KACnC;IACD,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB;QAChC,cAAc,EACZ,yFAAyF;KAC5F;CACF,CAAC,CAAA;AAEW,QAAA,OAAO,GAAgB,IAAA,8BAAiB,EAAC;IACpD,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE;QACJ,aAAa,EAAE,qBAAqB;KACrC;IACD,aAAa,EAAE;QACb,WAAW,EAAE,yBAAyB;QACtC,IAAI,EAAE,yBAAyB;QAC/B,SAAS,EAAE,uBAAuB;KACnC;IACD,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB;QAChC,cAAc,EACZ,6FAA6F;KAChG;CACF,CAAC,CAAA;AAEW,QAAA,OAAO,GAAgB,IAAA,8BAAiB,EAAC;IACpD,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE;QACJ,aAAa,EAAE,qBAAqB;KACrC;IACD,aAAa,EAAE;QACb,WAAW,EAAE,yBAAyB;QACtC,IAAI,EAAE,yBAAyB;QAC/B,SAAS,EAAE,uBAAuB;KACnC;IACD,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB;KACjC;CACF,CAAC,CAAA"}
@@ -1,2 +1,3 @@
1
- export { localNet, devNet, testNet, mainNet, type CantonChain } from './definitions.js';
1
+ export * from './definitions.js';
2
+ export { defineChainPreset, withChainOverrides } from './presets.js';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/chains/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/chains/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA"}
@@ -1,9 +1,22 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mainNet = exports.testNet = exports.devNet = exports.localNet = void 0;
4
- var definitions_js_1 = require("./definitions.js");
5
- Object.defineProperty(exports, "localNet", { enumerable: true, get: function () { return definitions_js_1.localNet; } });
6
- Object.defineProperty(exports, "devNet", { enumerable: true, get: function () { return definitions_js_1.devNet; } });
7
- Object.defineProperty(exports, "testNet", { enumerable: true, get: function () { return definitions_js_1.testNet; } });
8
- Object.defineProperty(exports, "mainNet", { enumerable: true, get: function () { return definitions_js_1.mainNet; } });
17
+ exports.withChainOverrides = exports.defineChainPreset = void 0;
18
+ __exportStar(require("./definitions.js"), exports);
19
+ var presets_js_1 = require("./presets.js");
20
+ Object.defineProperty(exports, "defineChainPreset", { enumerable: true, get: function () { return presets_js_1.defineChainPreset; } });
21
+ Object.defineProperty(exports, "withChainOverrides", { enumerable: true, get: function () { return presets_js_1.withChainOverrides; } });
9
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/chains/index.ts"],"names":[],"mappings":";;;AAAA,mDAAuF;AAA9E,0GAAA,QAAQ,OAAA;AAAE,wGAAA,MAAM,OAAA;AAAE,yGAAA,OAAO,OAAA;AAAE,yGAAA,OAAO,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/chains/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,mDAAgC;AAChC,2CAAoE;AAA3D,+GAAA,iBAAiB,OAAA;AAAE,gHAAA,kBAAkB,OAAA"}