cantonjs-react 0.0.1

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.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Canton React context and provider.
3
+ *
4
+ * CantonProvider wraps a TanStack QueryClientProvider and supplies the
5
+ * LedgerClient to all child hooks via React context.
6
+ */
7
+ import { QueryClient } from '@tanstack/react-query';
8
+ import type { ReactNode } from 'react';
9
+ import type { LedgerClient } from './types.js';
10
+ /** Context value holding the LedgerClient. */
11
+ type CantonContextValue = {
12
+ readonly client: LedgerClient;
13
+ };
14
+ /** Props for CantonProvider. */
15
+ export type CantonProviderProps = {
16
+ /** The LedgerClient instance to provide to hooks. */
17
+ readonly client: LedgerClient;
18
+ /** Optional TanStack QueryClient. A default one is created if not provided. */
19
+ readonly queryClient?: QueryClient;
20
+ readonly children?: ReactNode;
21
+ };
22
+ /**
23
+ * Provider component that supplies a LedgerClient to all cantonjs-react hooks.
24
+ *
25
+ * Must wrap any component tree that uses cantonjs-react hooks.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * import { CantonProvider } from 'cantonjs-react'
30
+ * import { createLedgerClient, jsonApi } from 'cantonjs'
31
+ *
32
+ * const client = createLedgerClient({
33
+ * transport: jsonApi({ url: 'http://localhost:7575', token: jwt }),
34
+ * actAs: 'Alice::1234',
35
+ * })
36
+ *
37
+ * function App() {
38
+ * return (
39
+ * <CantonProvider client={client}>
40
+ * <MyDApp />
41
+ * </CantonProvider>
42
+ * )
43
+ * }
44
+ * ```
45
+ */
46
+ export declare function CantonProvider({ client, queryClient, children }: CantonProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<CantonContextValue | null>>;
47
+ /**
48
+ * Access the LedgerClient from context.
49
+ *
50
+ * @throws If called outside a CantonProvider.
51
+ */
52
+ export declare function useCantonClient(): LedgerClient;
53
+ /**
54
+ * Access the current party identity.
55
+ *
56
+ * @returns The `actAs` party from the LedgerClient.
57
+ */
58
+ export declare function useParty(): string;
59
+ export {};
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Canton React context and provider.
3
+ *
4
+ * CantonProvider wraps a TanStack QueryClientProvider and supplies the
5
+ * LedgerClient to all child hooks via React context.
6
+ */
7
+ import { createContext, useContext, createElement } from 'react';
8
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
9
+ const CantonContext = createContext(null);
10
+ const defaultQueryClient = new QueryClient({
11
+ defaultOptions: {
12
+ queries: {
13
+ staleTime: 5_000,
14
+ refetchOnWindowFocus: false,
15
+ },
16
+ },
17
+ });
18
+ /**
19
+ * Provider component that supplies a LedgerClient to all cantonjs-react hooks.
20
+ *
21
+ * Must wrap any component tree that uses cantonjs-react hooks.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * import { CantonProvider } from 'cantonjs-react'
26
+ * import { createLedgerClient, jsonApi } from 'cantonjs'
27
+ *
28
+ * const client = createLedgerClient({
29
+ * transport: jsonApi({ url: 'http://localhost:7575', token: jwt }),
30
+ * actAs: 'Alice::1234',
31
+ * })
32
+ *
33
+ * function App() {
34
+ * return (
35
+ * <CantonProvider client={client}>
36
+ * <MyDApp />
37
+ * </CantonProvider>
38
+ * )
39
+ * }
40
+ * ```
41
+ */
42
+ export function CantonProvider({ client, queryClient, children }) {
43
+ return createElement(CantonContext.Provider, { value: { client } }, createElement(QueryClientProvider, { client: queryClient ?? defaultQueryClient }, children));
44
+ }
45
+ /**
46
+ * Access the LedgerClient from context.
47
+ *
48
+ * @throws If called outside a CantonProvider.
49
+ */
50
+ export function useCantonClient() {
51
+ const ctx = useContext(CantonContext);
52
+ if (!ctx) {
53
+ throw new Error('useCantonClient must be used within a CantonProvider');
54
+ }
55
+ return ctx.client;
56
+ }
57
+ /**
58
+ * Access the current party identity.
59
+ *
60
+ * @returns The `actAs` party from the LedgerClient.
61
+ */
62
+ export function useParty() {
63
+ return useCantonClient().actAs;
64
+ }
65
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AASxE,MAAM,aAAa,GAAG,aAAa,CAA4B,IAAI,CAAC,CAAA;AAWpE,MAAM,kBAAkB,GAAG,IAAI,WAAW,CAAC;IACzC,cAAc,EAAE;QACd,OAAO,EAAE;YACP,SAAS,EAAE,KAAK;YAChB,oBAAoB,EAAE,KAAK;SAC5B;KACF;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAuB;IACnF,OAAO,aAAa,CAClB,aAAa,CAAC,QAAQ,EACtB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EACrB,aAAa,CACX,mBAAmB,EACnB,EAAE,MAAM,EAAE,WAAW,IAAI,kBAAkB,EAAE,EAC7C,QAAQ,CACT,CACF,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAA;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,eAAe,EAAE,CAAC,KAAK,CAAA;AAChC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * cantonjs-react — React hooks for Canton Network dApps.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { CantonProvider, useCantonClient, useParty } from './context.js';
7
+ export type { CantonProviderProps } from './context.js';
8
+ export { useContracts } from './useContracts.js';
9
+ export type { UseContractsOptions } from './useContracts.js';
10
+ export { useCreateContract } from './useCreateContract.js';
11
+ export type { UseCreateContractOptions, CreateContractVariables } from './useCreateContract.js';
12
+ export { useExercise } from './useExercise.js';
13
+ export type { UseExerciseOptions, ExerciseVariables } from './useExercise.js';
14
+ export { useStreamContracts } from './useStreamContracts.js';
15
+ export type { UseStreamContractsOptions, UseStreamContractsResult } from './useStreamContracts.js';
16
+ export type { LedgerClient, ActiveContract, CreatedEvent, JsTransaction } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * cantonjs-react — React hooks for Canton Network dApps.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { CantonProvider, useCantonClient, useParty } from './context.js';
7
+ export { useContracts } from './useContracts.js';
8
+ export { useCreateContract } from './useCreateContract.js';
9
+ export { useExercise } from './useExercise.js';
10
+ export { useStreamContracts } from './useStreamContracts.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGxE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAG9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Minimal type interfaces matching cantonjs exports.
3
+ *
4
+ * These are defined locally so cantonjs-react can be developed and tested
5
+ * without requiring the cantonjs package to be published. At runtime,
6
+ * users pass their actual cantonjs client instances.
7
+ */
8
+ /** Minimal Transport interface matching cantonjs Transport. */
9
+ export type Transport = {
10
+ readonly type: string;
11
+ readonly url: string;
12
+ request: <TResponse = unknown>(args: TransportRequest) => Promise<TResponse>;
13
+ };
14
+ /** Minimal TransportRequest. */
15
+ export type TransportRequest = {
16
+ method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
17
+ path: string;
18
+ body?: unknown;
19
+ headers?: Record<string, string>;
20
+ signal?: AbortSignal;
21
+ timeout?: number;
22
+ };
23
+ /** Minimal LedgerClient interface. */
24
+ export type LedgerClient = {
25
+ readonly actAs: string;
26
+ readonly readAs: readonly string[];
27
+ createContract: (templateId: string, createArguments: Record<string, unknown>, options?: {
28
+ commandId?: string;
29
+ workflowId?: string;
30
+ signal?: AbortSignal;
31
+ }) => Promise<CreatedEvent>;
32
+ exerciseChoice: (templateId: string, contractId: string, choice: string, choiceArgument: Record<string, unknown>, options?: {
33
+ commandId?: string;
34
+ workflowId?: string;
35
+ signal?: AbortSignal;
36
+ }) => Promise<JsTransaction>;
37
+ queryContracts: (templateId: string, options?: {
38
+ signal?: AbortSignal;
39
+ }) => Promise<readonly ActiveContract[]>;
40
+ };
41
+ /** Minimal CreatedEvent. */
42
+ export type CreatedEvent = {
43
+ readonly contractId: string;
44
+ readonly templateId: string;
45
+ readonly createArgument: Record<string, unknown>;
46
+ readonly [key: string]: unknown;
47
+ };
48
+ /** Minimal JsTransaction. */
49
+ export type JsTransaction = {
50
+ readonly updateId: string;
51
+ readonly events: readonly Record<string, unknown>[];
52
+ readonly [key: string]: unknown;
53
+ };
54
+ /** Minimal ActiveContract. */
55
+ export type ActiveContract = {
56
+ readonly createdEvent: CreatedEvent;
57
+ readonly synchronizerId: string;
58
+ readonly reassignmentCounter: number;
59
+ };
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Minimal type interfaces matching cantonjs exports.
3
+ *
4
+ * These are defined locally so cantonjs-react can be developed and tested
5
+ * without requiring the cantonjs package to be published. At runtime,
6
+ * users pass their actual cantonjs client instances.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Query hook for active contracts.
3
+ *
4
+ * Wraps LedgerClient.queryContracts with TanStack Query for caching,
5
+ * deduplication, and automatic refetching.
6
+ */
7
+ import type { UseQueryResult } from '@tanstack/react-query';
8
+ import type { ActiveContract } from './types.js';
9
+ /** Options for the useContracts hook. */
10
+ export type UseContractsOptions = {
11
+ /** Template ID to query. */
12
+ readonly templateId: string;
13
+ /** Whether to enable the query. Defaults to true. */
14
+ readonly enabled?: boolean;
15
+ /** Refetch interval in milliseconds. */
16
+ readonly refetchInterval?: number;
17
+ };
18
+ /**
19
+ * Query active contracts matching a template.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * function AssetList() {
24
+ * const { data: contracts, isLoading } = useContracts({
25
+ * templateId: '#my-pkg:Main:Asset',
26
+ * })
27
+ *
28
+ * if (isLoading) return <div>Loading...</div>
29
+ * return <ul>{contracts?.map(c => <li key={c.createdEvent.contractId}>...</li>)}</ul>
30
+ * }
31
+ * ```
32
+ */
33
+ export declare function useContracts(options: UseContractsOptions): UseQueryResult<readonly ActiveContract[]>;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Query hook for active contracts.
3
+ *
4
+ * Wraps LedgerClient.queryContracts with TanStack Query for caching,
5
+ * deduplication, and automatic refetching.
6
+ */
7
+ import { useQuery } from '@tanstack/react-query';
8
+ import { useCantonClient } from './context.js';
9
+ /**
10
+ * Query active contracts matching a template.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * function AssetList() {
15
+ * const { data: contracts, isLoading } = useContracts({
16
+ * templateId: '#my-pkg:Main:Asset',
17
+ * })
18
+ *
19
+ * if (isLoading) return <div>Loading...</div>
20
+ * return <ul>{contracts?.map(c => <li key={c.createdEvent.contractId}>...</li>)}</ul>
21
+ * }
22
+ * ```
23
+ */
24
+ export function useContracts(options) {
25
+ const client = useCantonClient();
26
+ return useQuery({
27
+ queryKey: ['canton', 'contracts', options.templateId, client.actAs],
28
+ queryFn: ({ signal }) => client.queryContracts(options.templateId, { signal }),
29
+ enabled: options.enabled,
30
+ refetchInterval: options.refetchInterval,
31
+ });
32
+ }
33
+ //# sourceMappingURL=useContracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useContracts.js","sourceRoot":"","sources":["../src/useContracts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAa9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAC1B,OAA4B;IAE5B,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAEhC,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC;QACnE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC;QAC9E,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,eAAe,EAAE,OAAO,CAAC,eAAe;KACzC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Mutation hook for creating contracts.
3
+ *
4
+ * Wraps LedgerClient.createContract with TanStack Query's useMutation
5
+ * for loading state, error handling, and cache invalidation.
6
+ */
7
+ import type { UseMutationResult } from '@tanstack/react-query';
8
+ import type { CreatedEvent } from './types.js';
9
+ /** Variables for creating a contract. */
10
+ export type CreateContractVariables = {
11
+ readonly createArguments: Record<string, unknown>;
12
+ readonly commandId?: string;
13
+ readonly workflowId?: string;
14
+ };
15
+ /** Options for the useCreateContract hook. */
16
+ export type UseCreateContractOptions = {
17
+ /** Template ID for the contract to create. */
18
+ readonly templateId: string;
19
+ /** Callback after successful creation. */
20
+ readonly onSuccess?: (event: CreatedEvent) => void;
21
+ };
22
+ /**
23
+ * Mutation hook for creating a contract.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * function CreateAsset() {
28
+ * const { mutate: create, isPending } = useCreateContract({
29
+ * templateId: '#my-pkg:Main:Asset',
30
+ * })
31
+ *
32
+ * return (
33
+ * <button
34
+ * disabled={isPending}
35
+ * onClick={() => create({ createArguments: { owner: 'Alice', value: 100 } })}
36
+ * >
37
+ * Create Asset
38
+ * </button>
39
+ * )
40
+ * }
41
+ * ```
42
+ */
43
+ export declare function useCreateContract(options: UseCreateContractOptions): UseMutationResult<CreatedEvent, Error, CreateContractVariables>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Mutation hook for creating contracts.
3
+ *
4
+ * Wraps LedgerClient.createContract with TanStack Query's useMutation
5
+ * for loading state, error handling, and cache invalidation.
6
+ */
7
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
8
+ import { useCantonClient } from './context.js';
9
+ /**
10
+ * Mutation hook for creating a contract.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * function CreateAsset() {
15
+ * const { mutate: create, isPending } = useCreateContract({
16
+ * templateId: '#my-pkg:Main:Asset',
17
+ * })
18
+ *
19
+ * return (
20
+ * <button
21
+ * disabled={isPending}
22
+ * onClick={() => create({ createArguments: { owner: 'Alice', value: 100 } })}
23
+ * >
24
+ * Create Asset
25
+ * </button>
26
+ * )
27
+ * }
28
+ * ```
29
+ */
30
+ export function useCreateContract(options) {
31
+ const client = useCantonClient();
32
+ const queryClient = useQueryClient();
33
+ return useMutation({
34
+ mutationFn: (variables) => client.createContract(options.templateId, variables.createArguments, {
35
+ commandId: variables.commandId,
36
+ workflowId: variables.workflowId,
37
+ }),
38
+ onSuccess: (event) => {
39
+ // Invalidate contract queries for this template
40
+ void queryClient.invalidateQueries({
41
+ queryKey: ['canton', 'contracts', options.templateId],
42
+ });
43
+ options.onSuccess?.(event);
44
+ },
45
+ });
46
+ }
47
+ //# sourceMappingURL=useCreateContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCreateContract.js","sourceRoot":"","sources":["../src/useCreateContract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAkB9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAiC;IAEjC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IAEpC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,SAAkC,EAAE,EAAE,CACjD,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,eAAe,EAAE;YACnE,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,UAAU,EAAE,SAAS,CAAC,UAAU;SACjC,CAAC;QACJ,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,gDAAgD;YAChD,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;aACtD,CAAC,CAAA;YACF,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Mutation hook for exercising choices on contracts.
3
+ *
4
+ * Wraps LedgerClient.exerciseChoice with TanStack Query's useMutation.
5
+ */
6
+ import type { UseMutationResult } from '@tanstack/react-query';
7
+ import type { JsTransaction } from './types.js';
8
+ /** Variables for exercising a choice. */
9
+ export type ExerciseVariables = {
10
+ readonly contractId: string;
11
+ readonly choiceArgument: Record<string, unknown>;
12
+ readonly commandId?: string;
13
+ readonly workflowId?: string;
14
+ };
15
+ /** Options for the useExercise hook. */
16
+ export type UseExerciseOptions = {
17
+ /** Template ID of the contract. */
18
+ readonly templateId: string;
19
+ /** Choice name to exercise. */
20
+ readonly choice: string;
21
+ /** Callback after successful exercise. */
22
+ readonly onSuccess?: (tx: JsTransaction) => void;
23
+ };
24
+ /**
25
+ * Mutation hook for exercising a choice on a contract.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * function TransferButton({ contractId }: { contractId: string }) {
30
+ * const { mutate: exercise, isPending } = useExercise({
31
+ * templateId: '#my-pkg:Main:Asset',
32
+ * choice: 'Transfer',
33
+ * })
34
+ *
35
+ * return (
36
+ * <button
37
+ * disabled={isPending}
38
+ * onClick={() => exercise({
39
+ * contractId,
40
+ * choiceArgument: { newOwner: 'Bob' },
41
+ * })}
42
+ * >
43
+ * Transfer
44
+ * </button>
45
+ * )
46
+ * }
47
+ * ```
48
+ */
49
+ export declare function useExercise(options: UseExerciseOptions): UseMutationResult<JsTransaction, Error, ExerciseVariables>;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Mutation hook for exercising choices on contracts.
3
+ *
4
+ * Wraps LedgerClient.exerciseChoice with TanStack Query's useMutation.
5
+ */
6
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
7
+ import { useCantonClient } from './context.js';
8
+ /**
9
+ * Mutation hook for exercising a choice on a contract.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * function TransferButton({ contractId }: { contractId: string }) {
14
+ * const { mutate: exercise, isPending } = useExercise({
15
+ * templateId: '#my-pkg:Main:Asset',
16
+ * choice: 'Transfer',
17
+ * })
18
+ *
19
+ * return (
20
+ * <button
21
+ * disabled={isPending}
22
+ * onClick={() => exercise({
23
+ * contractId,
24
+ * choiceArgument: { newOwner: 'Bob' },
25
+ * })}
26
+ * >
27
+ * Transfer
28
+ * </button>
29
+ * )
30
+ * }
31
+ * ```
32
+ */
33
+ export function useExercise(options) {
34
+ const client = useCantonClient();
35
+ const queryClient = useQueryClient();
36
+ return useMutation({
37
+ mutationFn: (variables) => client.exerciseChoice(options.templateId, variables.contractId, options.choice, variables.choiceArgument, {
38
+ commandId: variables.commandId,
39
+ workflowId: variables.workflowId,
40
+ }),
41
+ onSuccess: (tx) => {
42
+ // Invalidate all contract queries for this template
43
+ void queryClient.invalidateQueries({
44
+ queryKey: ['canton', 'contracts', options.templateId],
45
+ });
46
+ options.onSuccess?.(tx);
47
+ },
48
+ });
49
+ }
50
+ //# sourceMappingURL=useExercise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExercise.js","sourceRoot":"","sources":["../src/useExercise.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAqB9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,WAAW,CACzB,OAA2B;IAE3B,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IAEpC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,SAA4B,EAAE,EAAE,CAC3C,MAAM,CAAC,cAAc,CACnB,OAAO,CAAC,UAAU,EAClB,SAAS,CAAC,UAAU,EACpB,OAAO,CAAC,MAAM,EACd,SAAS,CAAC,cAAc,EACxB;YACE,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,UAAU,EAAE,SAAS,CAAC,UAAU;SACjC,CACF;QACH,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE;YAChB,oDAAoD;YACpD,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;aACtD,CAAC,CAAA;YACF,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAA;QACzB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Streaming hook for live contract updates.
3
+ *
4
+ * Uses useEffect + AsyncIterator to subscribe to contract changes
5
+ * and update React state in real-time.
6
+ */
7
+ import type { ActiveContract } from './types.js';
8
+ /** Options for the useStreamContracts hook. */
9
+ export type UseStreamContractsOptions = {
10
+ /** Template ID to stream. */
11
+ readonly templateId: string;
12
+ /** Whether to enable the stream. Defaults to true. */
13
+ readonly enabled?: boolean;
14
+ };
15
+ /** Result of the useStreamContracts hook. */
16
+ export type UseStreamContractsResult = {
17
+ /** Current list of active contracts. */
18
+ readonly contracts: readonly ActiveContract[];
19
+ /** Whether the initial query is loading. */
20
+ readonly isLoading: boolean;
21
+ /** Any error from the query or stream. */
22
+ readonly error: Error | null;
23
+ };
24
+ /**
25
+ * Stream active contracts with live updates.
26
+ *
27
+ * Performs an initial query for active contracts, then polls at a regular
28
+ * interval to pick up changes. For true real-time updates, integrate with
29
+ * cantonjs's streamUpdates WebSocket API.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * function LiveAssets() {
34
+ * const { contracts, isLoading, error } = useStreamContracts({
35
+ * templateId: '#my-pkg:Main:Asset',
36
+ * })
37
+ *
38
+ * if (isLoading) return <div>Loading...</div>
39
+ * if (error) return <div>Error: {error.message}</div>
40
+ * return <ul>{contracts.map(c => <li key={c.createdEvent.contractId}>...</li>)}</ul>
41
+ * }
42
+ * ```
43
+ */
44
+ export declare function useStreamContracts(options: UseStreamContractsOptions): UseStreamContractsResult;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Streaming hook for live contract updates.
3
+ *
4
+ * Uses useEffect + AsyncIterator to subscribe to contract changes
5
+ * and update React state in real-time.
6
+ */
7
+ import { useState, useEffect, useRef } from 'react';
8
+ import { useCantonClient } from './context.js';
9
+ /**
10
+ * Stream active contracts with live updates.
11
+ *
12
+ * Performs an initial query for active contracts, then polls at a regular
13
+ * interval to pick up changes. For true real-time updates, integrate with
14
+ * cantonjs's streamUpdates WebSocket API.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * function LiveAssets() {
19
+ * const { contracts, isLoading, error } = useStreamContracts({
20
+ * templateId: '#my-pkg:Main:Asset',
21
+ * })
22
+ *
23
+ * if (isLoading) return <div>Loading...</div>
24
+ * if (error) return <div>Error: {error.message}</div>
25
+ * return <ul>{contracts.map(c => <li key={c.createdEvent.contractId}>...</li>)}</ul>
26
+ * }
27
+ * ```
28
+ */
29
+ export function useStreamContracts(options) {
30
+ const client = useCantonClient();
31
+ const [contracts, setContracts] = useState([]);
32
+ const [isLoading, setIsLoading] = useState(true);
33
+ const [error, setError] = useState(null);
34
+ const enabled = options.enabled ?? true;
35
+ const templateIdRef = useRef(options.templateId);
36
+ templateIdRef.current = options.templateId;
37
+ useEffect(() => {
38
+ if (!enabled)
39
+ return;
40
+ let cancelled = false;
41
+ const controller = new AbortController();
42
+ async function poll() {
43
+ try {
44
+ const result = await client.queryContracts(templateIdRef.current, {
45
+ signal: controller.signal,
46
+ });
47
+ if (!cancelled) {
48
+ setContracts(result);
49
+ setIsLoading(false);
50
+ setError(null);
51
+ }
52
+ }
53
+ catch (err) {
54
+ if (!cancelled && !controller.signal.aborted) {
55
+ setError(err instanceof Error ? err : new Error(String(err)));
56
+ setIsLoading(false);
57
+ }
58
+ }
59
+ }
60
+ void poll();
61
+ const interval = setInterval(() => void poll(), 5_000);
62
+ return () => {
63
+ cancelled = true;
64
+ controller.abort();
65
+ clearInterval(interval);
66
+ };
67
+ }, [client, enabled]);
68
+ return { contracts, isLoading, error };
69
+ }
70
+ //# sourceMappingURL=useStreamContracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStreamContracts.js","sourceRoot":"","sources":["../src/useStreamContracts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAqB9C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAkC;IAElC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAA4B,EAAE,CAAC,CAAA;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAChD,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAA;IAE1C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QAExC,KAAK,UAAU,IAAI;YACjB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,OAAO,EAAE;oBAChE,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAA;gBACF,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,YAAY,CAAC,MAAM,CAAC,CAAA;oBACpB,YAAY,CAAC,KAAK,CAAC,CAAA;oBACnB,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAChB,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC7C,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;oBAC7D,YAAY,CAAC,KAAK,CAAC,CAAA;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QAED,KAAK,IAAI,EAAE,CAAA;QACX,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,CAAC,CAAA;QAEtD,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;YAChB,UAAU,CAAC,KAAK,EAAE,CAAA;YAClB,aAAa,CAAC,QAAQ,CAAC,CAAA;QACzB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAErB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AACxC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "cantonjs-react",
3
+ "version": "0.0.1",
4
+ "description": "React hooks for Canton Network dApps — built on cantonjs",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest",
14
+ "lint": "eslint src",
15
+ "clean": "rm -rf dist",
16
+ "prepublishOnly": "npm run clean && npm run build"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "keywords": [
22
+ "canton",
23
+ "daml",
24
+ "react",
25
+ "hooks",
26
+ "blockchain",
27
+ "ledger"
28
+ ],
29
+ "author": "Charles Dusek",
30
+ "license": "Apache-2.0",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/merged-one/cantonjs.git",
34
+ "directory": "packages/cantonjs-react"
35
+ },
36
+ "peerDependencies": {
37
+ "@tanstack/react-query": "^5.0.0",
38
+ "cantonjs": "^0.0.1",
39
+ "react": "^18.0.0 || ^19.0.0"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "cantonjs": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "devDependencies": {
47
+ "@tanstack/react-query": "^5.0.0",
48
+ "@testing-library/dom": "^10.4.1",
49
+ "@testing-library/react": "^16.0.0",
50
+ "@types/react": "^18.0.0",
51
+ "jsdom": "^29.0.1",
52
+ "react": "^18.0.0",
53
+ "react-dom": "^18.0.0",
54
+ "typescript": "^5.5.0",
55
+ "vitest": "^3.0.0"
56
+ },
57
+ "engines": {
58
+ "node": ">=18"
59
+ }
60
+ }