cantonjs-react 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 (2) hide show
  1. package/README.md +213 -0
  2. package/package.json +4 -2
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # cantonjs-react
2
+
3
+ React hooks for Canton Network dApps, powered by [TanStack Query](https://tanstack.com/query).
4
+
5
+ [![npm version](https://img.shields.io/npm/v/cantonjs-react.svg)](https://www.npmjs.com/package/cantonjs-react)
6
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/merged-one/cantonjs/blob/main/LICENSE)
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install cantonjs cantonjs-react @tanstack/react-query
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```tsx
17
+ import { CantonProvider, useContracts, useCreateContract } from 'cantonjs-react'
18
+ import { createLedgerClient, jsonApi } from 'cantonjs'
19
+
20
+ const client = createLedgerClient({
21
+ transport: jsonApi({ url: 'http://localhost:7575', token: jwt }),
22
+ actAs: 'Alice::1234',
23
+ })
24
+
25
+ function App() {
26
+ return (
27
+ <CantonProvider client={client}>
28
+ <AssetList />
29
+ </CantonProvider>
30
+ )
31
+ }
32
+
33
+ function AssetList() {
34
+ const { data: assets, isLoading } = useContracts({
35
+ templateId: '#my-pkg:Main:Asset',
36
+ })
37
+
38
+ const { mutate: create, isPending } = useCreateContract({
39
+ templateId: '#my-pkg:Main:Asset',
40
+ })
41
+
42
+ if (isLoading) return <div>Loading...</div>
43
+
44
+ return (
45
+ <div>
46
+ <button
47
+ disabled={isPending}
48
+ onClick={() => create({ createArguments: { owner: 'Alice', value: 100 } })}
49
+ >
50
+ Create Asset
51
+ </button>
52
+ <ul>
53
+ {assets?.map(c => (
54
+ <li key={c.createdEvent.contractId}>
55
+ {JSON.stringify(c.createdEvent.createArgument)}
56
+ </li>
57
+ ))}
58
+ </ul>
59
+ </div>
60
+ )
61
+ }
62
+ ```
63
+
64
+ ## Public Scan Data Alongside Ledger Hooks
65
+
66
+ `cantonjs-react` stays focused on participant-private ledger state. For public Splice data, use TanStack Query directly with `cantonjs-splice-scan`:
67
+
68
+ ```tsx
69
+ import { useQuery } from '@tanstack/react-query'
70
+ import { useContracts } from 'cantonjs-react'
71
+ import { createScanClient } from 'cantonjs-splice-scan'
72
+
73
+ const scan = createScanClient({
74
+ url: import.meta.env.VITE_SPLICE_SCAN_URL,
75
+ })
76
+
77
+ function NetworkDashboard() {
78
+ const { data: dso } = useQuery({
79
+ queryKey: ['scan', 'dso'],
80
+ queryFn: () => scan.getDsoInfo(),
81
+ })
82
+
83
+ const { data: assets } = useContracts({
84
+ templateId: '#my-pkg:Main:Asset',
85
+ })
86
+
87
+ return (
88
+ <div>
89
+ <pre>{JSON.stringify(dso, null, 2)}</pre>
90
+ <pre>{JSON.stringify(assets, null, 2)}</pre>
91
+ </div>
92
+ )
93
+ }
94
+ ```
95
+
96
+ This keeps public Scan reads and party-private ledger reads clearly separated. See [`../../docs/examples/react.md`](../../docs/examples/react.md) for the full example.
97
+
98
+ ## Hooks
99
+
100
+ ### `useContracts(options)`
101
+
102
+ Query active contracts with automatic caching and deduplication.
103
+
104
+ ```tsx
105
+ const { data, isLoading, error } = useContracts({
106
+ templateId: '#my-pkg:Main:Asset',
107
+ enabled: true, // optional, default true
108
+ refetchInterval: 5000, // optional, auto-refetch in ms
109
+ })
110
+ ```
111
+
112
+ ### `useCreateContract(options)`
113
+
114
+ Mutation hook for creating contracts. Automatically invalidates related queries on success.
115
+
116
+ ```tsx
117
+ const { mutate: create, isPending, error } = useCreateContract({
118
+ templateId: '#my-pkg:Main:Asset',
119
+ onSuccess: (event) => console.log('Created:', event.contractId),
120
+ })
121
+
122
+ create({ createArguments: { owner: 'Alice', value: 100 } })
123
+ ```
124
+
125
+ ### `useExercise(options)`
126
+
127
+ Mutation hook for exercising choices. Automatically invalidates related queries on success.
128
+
129
+ ```tsx
130
+ const { mutate: exercise, isPending } = useExercise({
131
+ templateId: '#my-pkg:Main:Asset',
132
+ choice: 'Transfer',
133
+ })
134
+
135
+ exercise({
136
+ contractId: 'contract-id',
137
+ choiceArgument: { newOwner: 'Bob' },
138
+ })
139
+ ```
140
+
141
+ ### `useStreamContracts(options)`
142
+
143
+ Polling-based live contract updates (5-second interval).
144
+
145
+ ```tsx
146
+ const { contracts, isLoading, error } = useStreamContracts({
147
+ templateId: '#my-pkg:Main:Asset',
148
+ enabled: true, // optional
149
+ })
150
+ ```
151
+
152
+ ### `useCantonClient()`
153
+
154
+ Access the `LedgerClient` directly for advanced use cases.
155
+
156
+ ```tsx
157
+ const client = useCantonClient()
158
+ ```
159
+
160
+ ### `useParty()`
161
+
162
+ Get the current `actAs` party identity.
163
+
164
+ ```tsx
165
+ const party = useParty()
166
+ // 'Alice::1234'
167
+ ```
168
+
169
+ ## Provider
170
+
171
+ Wrap your app with `CantonProvider`. Optionally pass a custom `QueryClient`:
172
+
173
+ ```tsx
174
+ import { QueryClient } from '@tanstack/react-query'
175
+
176
+ const queryClient = new QueryClient({
177
+ defaultOptions: { queries: { staleTime: 10_000 } },
178
+ })
179
+
180
+ <CantonProvider client={ledgerClient} queryClient={queryClient}>
181
+ <App />
182
+ </CantonProvider>
183
+ ```
184
+
185
+ ## Cache Invalidation
186
+
187
+ Mutations automatically invalidate contract queries for the same template:
188
+
189
+ - `useCreateContract` invalidates `['canton', 'contracts', templateId]`
190
+ - `useExercise` invalidates `['canton', 'contracts', templateId]`
191
+
192
+ This means `useContracts` queries refresh automatically after mutations complete.
193
+
194
+ ## Peer Dependencies
195
+
196
+ | Package | Version |
197
+ |---------|---------|
198
+ | `react` | ^18.0.0 \|\| ^19.0.0 |
199
+ | `@tanstack/react-query` | ^5.0.0 |
200
+
201
+ ## Requirements
202
+
203
+ - Node.js >= 18
204
+ - React 18 or 19
205
+
206
+ ## Related
207
+
208
+ - [cantonjs](https://github.com/merged-one/cantonjs) &mdash; Core TypeScript library for Canton
209
+ - [cantonjs-codegen](https://github.com/merged-one/cantonjs/tree/main/packages/cantonjs-codegen) &mdash; DAR-to-TypeScript code generation
210
+
211
+ ## License
212
+
213
+ [Apache-2.0](https://github.com/merged-one/cantonjs/blob/main/LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cantonjs-react",
3
- "version": "0.0.1",
3
+ "version": "0.3.0",
4
4
  "description": "React hooks for Canton Network dApps — built on cantonjs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,6 +11,7 @@
11
11
  "typecheck": "tsc --noEmit",
12
12
  "test": "vitest run",
13
13
  "test:watch": "vitest",
14
+ "test:coverage": "node ../../scripts/verify-coverage-exclusions.mjs && vitest run --coverage",
14
15
  "lint": "eslint src",
15
16
  "clean": "rm -rf dist",
16
17
  "prepublishOnly": "npm run clean && npm run build"
@@ -35,7 +36,7 @@
35
36
  },
36
37
  "peerDependencies": {
37
38
  "@tanstack/react-query": "^5.0.0",
38
- "cantonjs": "^0.0.1",
39
+ "cantonjs": "^0.3.0",
39
40
  "react": "^18.0.0 || ^19.0.0"
40
41
  },
41
42
  "peerDependenciesMeta": {
@@ -48,6 +49,7 @@
48
49
  "@testing-library/dom": "^10.4.1",
49
50
  "@testing-library/react": "^16.0.0",
50
51
  "@types/react": "^18.0.0",
52
+ "@vitest/coverage-v8": "^3.0.0",
51
53
  "jsdom": "^29.0.1",
52
54
  "react": "^18.0.0",
53
55
  "react-dom": "^18.0.0",