@ic-reactor/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.
package/LICENSE.md ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright © 2023 B3Pay
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # IC-ReActor - React
2
+
3
+ `@ic-reactor/react` is a comprehensive React library designed to streamline interactions with the Internet Computer (IC) blockchain. It provides React hooks and utilities for efficient state management, authentication, and interaction with IC actors.
4
+
5
+ ## Features
6
+
7
+ - **React Hooks Integration**: Custom hooks for managing blockchain actor states and authentication within React applications.
8
+ - **Efficient State Management**: Utilize the power of Zustand for global state management in React components.
9
+ - **Asynchronous Data Handling**: Easy handling of asynchronous operations related to IC actors.
10
+ - **Authentication Support**: Integrated hooks for managing authentication with the IC blockchain.
11
+ - **Auto-Refresh and Query Capabilities**: Support for auto-refreshing data and querying IC actors.
12
+
13
+ ## Installation
14
+
15
+ Install the package using npm:
16
+
17
+ ```bash
18
+ npm install @ic-reactor/react
19
+ ```
20
+
21
+ or using yarn:
22
+
23
+ ```bash
24
+ yarn add @ic-reactor/react
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ To use `@ic-reactor/react`, start by importing and setting up the `createReActor` function with your actor configurations:
30
+
31
+ ```javascript
32
+ import createReActor from '@ic-reactor/react';
33
+
34
+ const actorInitializer = /* Your actor initialization logic */;
35
+ const reActorConfig = /* Your ReActor configuration options */;
36
+
37
+ const { ReActorProvider, useReActorQuery, useReActorUpdate, ... } = createReActor(actorInitializer, reActorConfig);
38
+ ```
39
+
40
+ Then, wrap your React application with the `ReActorProvider` component:
41
+
42
+ ```javascript
43
+ const App = () => (
44
+ <ReActorProvider>
45
+ <YourApp />
46
+ </ReActorProvider>
47
+ )
48
+ ```
49
+
50
+ Finally, use the `useReActorQuery` and `useReActorUpdate` hooks to query and update actor state:
51
+
52
+ ### Example: Querying Actor State
53
+
54
+ ```javascript
55
+ const { recall, data, loading, error } = useQueryCall({
56
+ functionName: "fetchData",
57
+ args: ["arg1", "arg2"],
58
+ autoRefresh: true, // default: true
59
+ refreshInterval: 3000, // default: 5000
60
+ disableInitialCall: false, // default: false
61
+ })
62
+
63
+ // Use 'data', 'loading', 'error' in your component
64
+ ```
65
+
66
+ ### Example: Updating Actor State
67
+
68
+ ```javascript
69
+ const { call, data, loading, error } = useUpdateCall({
70
+ functionName: "updateData",
71
+ args: ["arg1", "arg2"],
72
+ })
73
+
74
+ // Call the 'call' function to trigger an update call
75
+ ```
76
+
77
+ ## API Reference
78
+
79
+ The library provides various hooks and utilities for interacting with IC actors:
80
+
81
+ - `useQueryCall`: Hook for querying data from an actor.
82
+ - `useUpdateCall`: Hook for updating data in an actor.
83
+ - `useReActor`: Hook to access the global actor state.
84
+ - `ReActorProvider`: React context provider for ReActor state.
85
+ - Additional hooks for handling loading, errors, authentication, and more.
86
+
87
+ For detailed API usage and options, please refer to the [documentation](#).
88
+
89
+ ## Contributing
90
+
91
+ Contributions to `@ic-reactor/react` are welcome! Please read our [contributing guidelines](#) for more information.
92
+
93
+ ## License
94
+
95
+ `@ic-reactor/react` is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
96
+
97
+ ---
98
+
99
+ This README provides a foundational overview of your package. You should expand it with more detailed documentation, examples, and links to additional resources or documentation as needed. Replace placeholders with actual information and links relevant to your project.
@@ -0,0 +1,23 @@
1
+ import { CallMethod, ExtractReActorMethodArgs, ReActorState } from "@ic-reactor/store";
2
+ import { StoreApi } from "zustand";
3
+ import { ReActorUseQueryArgs, ReActorUseUpdateArgs } from "./types";
4
+ export declare const getStateHooks: <A extends unknown>(store: StoreApi<ReActorState<A>>, callMethod: CallMethod<A>) => {
5
+ useReActor: () => ReActorState<A>;
6
+ useLoading: () => boolean;
7
+ useError: () => Error | undefined;
8
+ useInitialized: () => boolean;
9
+ useInitializing: () => boolean;
10
+ useActorState: () => import("@ic-reactor/store").ReActorActorState<A>;
11
+ useQueryCall: <M extends keyof A>({ autoRefresh, refreshInterval, disableInitialCall, ...rest }: ReActorUseQueryArgs<A, M>) => {
12
+ data: import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M]> | undefined;
13
+ error: Error | undefined;
14
+ loading: boolean;
15
+ recall: (replaceArgs?: ExtractReActorMethodArgs<A[M]> | undefined) => Promise<import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M]>>;
16
+ };
17
+ useUpdateCall: <M_1 extends keyof A>(args: ReActorUseUpdateArgs<A, M_1>) => {
18
+ data: import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M_1]> | undefined;
19
+ error: Error | undefined;
20
+ loading: boolean;
21
+ call: (replaceArgs?: ExtractReActorMethodArgs<A[M_1]> | undefined) => Promise<import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M_1]>>;
22
+ };
23
+ };
package/dist/hooks.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.getStateHooks = void 0;
24
+ const react_1 = require("react");
25
+ const zustand_1 = require("zustand");
26
+ const getStateHooks = (store, callMethod) => {
27
+ const useReActor = () => {
28
+ const state = (0, zustand_1.useStore)(store);
29
+ return state;
30
+ };
31
+ const useLoading = () => {
32
+ const loading = (0, zustand_1.useStore)(store, (state) => state.loading);
33
+ return loading;
34
+ };
35
+ const useError = () => {
36
+ const error = (0, zustand_1.useStore)(store, (state) => state.error);
37
+ return error;
38
+ };
39
+ const useInitialized = () => {
40
+ const initialized = (0, zustand_1.useStore)(store, (state) => state.initialized);
41
+ return initialized;
42
+ };
43
+ const useInitializing = () => {
44
+ const initializing = (0, zustand_1.useStore)(store, (state) => state.initializing);
45
+ return initializing;
46
+ };
47
+ const useActorState = () => {
48
+ const actorState = (0, zustand_1.useStore)(store, (state) => state.actorState);
49
+ return actorState;
50
+ };
51
+ const useReActorCall = ({ onError, onSuccess, onLoading, args = [], functionName, }) => {
52
+ const [state, setState] = (0, react_1.useState)({
53
+ data: undefined,
54
+ error: undefined,
55
+ loading: false,
56
+ });
57
+ const call = (0, react_1.useCallback)((replaceArgs) => __awaiter(void 0, void 0, void 0, function* () {
58
+ onLoading === null || onLoading === void 0 ? void 0 : onLoading(true);
59
+ onError === null || onError === void 0 ? void 0 : onError(undefined);
60
+ setState((prevState) => (Object.assign(Object.assign({}, prevState), { loading: true, error: undefined })));
61
+ try {
62
+ const data = yield callMethod(functionName, ...(replaceArgs !== null && replaceArgs !== void 0 ? replaceArgs : args));
63
+ onLoading === null || onLoading === void 0 ? void 0 : onLoading(false);
64
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(data);
65
+ setState((prevState) => (Object.assign(Object.assign({}, prevState), { data, loading: false })));
66
+ return data;
67
+ }
68
+ catch (error) {
69
+ onError === null || onError === void 0 ? void 0 : onError(error);
70
+ onLoading === null || onLoading === void 0 ? void 0 : onLoading(false);
71
+ setState((prevState) => (Object.assign(Object.assign({}, prevState), { error: error, loading: false })));
72
+ throw error;
73
+ }
74
+ }), [args, functionName, onError, onSuccess, onLoading]);
75
+ return Object.assign({ call }, state);
76
+ };
77
+ const useQueryCall = (_a) => {
78
+ var { autoRefresh, refreshInterval = 5000, disableInitialCall } = _a, rest = __rest(_a, ["autoRefresh", "refreshInterval", "disableInitialCall"]);
79
+ const _b = useReActorCall(rest), { call: recall } = _b, state = __rest(_b, ["call"]);
80
+ let intervalId = (0, react_1.useRef)(undefined);
81
+ (0, react_1.useEffect)(() => {
82
+ // Auto-refresh logic
83
+ if (autoRefresh) {
84
+ intervalId.current = setInterval(() => {
85
+ recall();
86
+ }, refreshInterval);
87
+ }
88
+ // Initial call logic
89
+ if (!disableInitialCall) {
90
+ recall();
91
+ }
92
+ return () => {
93
+ clearInterval(intervalId.current);
94
+ };
95
+ }, [disableInitialCall, autoRefresh, refreshInterval]);
96
+ return Object.assign({ recall }, state);
97
+ };
98
+ const useUpdateCall = (args) => {
99
+ return useReActorCall(args);
100
+ };
101
+ return {
102
+ useReActor,
103
+ useLoading,
104
+ useError,
105
+ useInitialized,
106
+ useInitializing,
107
+ useActorState,
108
+ useQueryCall,
109
+ useUpdateCall,
110
+ };
111
+ };
112
+ exports.getStateHooks = getStateHooks;
@@ -0,0 +1,50 @@
1
+ /// <reference types="react" />
2
+ import type { HttpAgent, HttpAgentOptions } from "@dfinity/agent";
3
+ import { AuthClientLoginOptions } from "@dfinity/auth-client";
4
+ import type { ActorSubclass, ReActorStore } from "@ic-reactor/store";
5
+ export type ReActorContextType<A = ActorSubclass<any>> = ReActorStore<A>;
6
+ export interface CreateReActorOptions extends HttpAgentOptions {
7
+ initializeOnMount?: boolean;
8
+ }
9
+ export declare const createReActor: <A extends unknown>(actorInitializer: (agent: HttpAgent) => A, options?: CreateReActorOptions) => {
10
+ useReActor: () => import("@ic-reactor/store").ReActorState<A>;
11
+ useLoading: () => boolean;
12
+ useError: () => Error | undefined;
13
+ useQueryCall: <M extends keyof A>({ autoRefresh, refreshInterval, disableInitialCall, ...rest }: import("./types").ReActorUseQueryArgs<A, M>) => {
14
+ data: import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M]> | undefined;
15
+ error: Error | undefined;
16
+ loading: boolean;
17
+ recall: (replaceArgs?: import("@ic-reactor/store").ExtractReActorMethodArgs<A[M]> | undefined) => Promise<import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M]>>;
18
+ };
19
+ useUpdateCall: <M_1 extends keyof A>(args: import("./types").ReActorUseUpdateArgs<A, M_1>) => {
20
+ data: import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M_1]> | undefined;
21
+ error: Error | undefined;
22
+ loading: boolean;
23
+ call: (replaceArgs?: import("@ic-reactor/store").ExtractReActorMethodArgs<A[M_1]> | undefined) => Promise<import("@ic-reactor/store").ExtractReActorMethodReturnType<A[M_1]>>;
24
+ };
25
+ useAuthClient: () => {
26
+ authClient: import("@dfinity/auth-client").AuthClient | null;
27
+ authenticated: boolean;
28
+ authenticating: boolean;
29
+ identity: import("@dfinity/agent").Identity | null;
30
+ login: (options?: AuthClientLoginOptions) => Promise<void>;
31
+ logout: (options?: {
32
+ returnTo?: string;
33
+ }) => Promise<void>;
34
+ authenticate: () => Promise<void>;
35
+ loginLoading: boolean;
36
+ loginError: unknown;
37
+ };
38
+ useActorState: () => import("@ic-reactor/store").ReActorActorState<A>;
39
+ useInitialized: () => boolean;
40
+ useInitializing: () => boolean;
41
+ initialize: (identity?: import("@dfinity/agent").Identity | undefined) => void;
42
+ authenticate: () => Promise<void>;
43
+ resetState: () => void;
44
+ updateState: (newState: Partial<import("@ic-reactor/store").ReActorState<A>>) => void;
45
+ callMethod: import("@ic-reactor/store").CallMethod<A>;
46
+ ReActorProvider: import("react").FC<{
47
+ children: React.ReactNode;
48
+ }>;
49
+ };
50
+ export default createReActor;
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.createReActor = void 0;
16
+ const store_1 = __importDefault(require("@ic-reactor/store"));
17
+ const react_1 = require("react");
18
+ const hooks_1 = require("./hooks");
19
+ const defaultCreateReActorOptions = {
20
+ initializeOnMount: true,
21
+ host: process.env.NODE_ENV === "production"
22
+ ? "https://icp-api.io"
23
+ : "http://localhost:4943",
24
+ };
25
+ const createReActor = (actorInitializer, options = {}) => {
26
+ const optionsWithDefaults = Object.assign(Object.assign({}, defaultCreateReActorOptions), options);
27
+ const Context = (0, react_1.createContext)(undefined);
28
+ const { actions, initializeActor, store } = (0, store_1.default)((agent) => actorInitializer(agent), optionsWithDefaults);
29
+ if (optionsWithDefaults.initializeOnMount) {
30
+ try {
31
+ initializeActor();
32
+ }
33
+ catch (e) {
34
+ console.error(e);
35
+ }
36
+ }
37
+ const ReActorProvider = ({ children, }) => {
38
+ (0, react_1.useEffect)(() => actions.resetState, [actions.resetState]);
39
+ return (0, react_1.createElement)(Context.Provider, { value: store }, children);
40
+ };
41
+ const { useReActor, useLoading, useError, useQueryCall, useUpdateCall, useInitialized, useInitializing, useActorState, } = (0, hooks_1.getStateHooks)(store, actions.callMethod);
42
+ const useAuthClient = () => {
43
+ const [loginLoading, setLoginLoading] = (0, react_1.useState)(false);
44
+ const [loginError, setLoginError] = (0, react_1.useState)(null);
45
+ const { authClient, authenticated, authenticating, identity } = useReActor();
46
+ const authenticate = () => __awaiter(void 0, void 0, void 0, function* () {
47
+ yield actions.authenticate();
48
+ });
49
+ const login = (options) => __awaiter(void 0, void 0, void 0, function* () {
50
+ setLoginLoading(true);
51
+ setLoginError(null);
52
+ try {
53
+ yield (authClient === null || authClient === void 0 ? void 0 : authClient.login(Object.assign(Object.assign({}, options), { onSuccess: () => __awaiter(void 0, void 0, void 0, function* () {
54
+ var _a;
55
+ setLoginLoading(false);
56
+ yield authenticate();
57
+ (_a = options === null || options === void 0 ? void 0 : options.onSuccess) === null || _a === void 0 ? void 0 : _a.call(options);
58
+ }), onError: (e) => {
59
+ var _a;
60
+ setLoginError(e);
61
+ setLoginLoading(false);
62
+ (_a = options === null || options === void 0 ? void 0 : options.onError) === null || _a === void 0 ? void 0 : _a.call(options, e);
63
+ } })));
64
+ }
65
+ catch (e) {
66
+ setLoginLoading(false);
67
+ setLoginError(e);
68
+ }
69
+ });
70
+ const logout = (options) => __awaiter(void 0, void 0, void 0, function* () {
71
+ yield (authClient === null || authClient === void 0 ? void 0 : authClient.logout(options));
72
+ yield authenticate();
73
+ });
74
+ (0, react_1.useEffect)(() => {
75
+ if (!authClient && !authenticating) {
76
+ authenticate();
77
+ }
78
+ }, [authClient, authenticating]);
79
+ return {
80
+ authClient,
81
+ authenticated,
82
+ authenticating,
83
+ identity,
84
+ login,
85
+ logout,
86
+ authenticate,
87
+ loginLoading,
88
+ loginError,
89
+ };
90
+ };
91
+ return Object.assign(Object.assign({ ReActorProvider }, actions), { useReActor,
92
+ useLoading,
93
+ useError,
94
+ useQueryCall,
95
+ useUpdateCall,
96
+ useAuthClient,
97
+ useActorState,
98
+ useInitialized,
99
+ useInitializing });
100
+ };
101
+ exports.createReActor = createReActor;
102
+ exports.default = exports.createReActor;
@@ -0,0 +1,20 @@
1
+ import { ExtractReActorMethodArgs, ExtractReActorMethodReturnType } from "@ic-reactor/store";
2
+ export type ReActorCallArgs<A, M extends keyof A> = {
3
+ functionName: M;
4
+ args?: ExtractReActorMethodArgs<A[M]>;
5
+ onLoading?: (loading: boolean) => void;
6
+ onError?: (error: Error | unknown) => void;
7
+ onSuccess?: (data: ExtractReActorMethodReturnType<A[M]> | undefined) => void;
8
+ };
9
+ export type ReActorHookState<A, M extends keyof A> = {
10
+ data: ExtractReActorMethodReturnType<A[M]> | undefined;
11
+ error: Error | undefined;
12
+ loading: boolean;
13
+ };
14
+ export interface ReActorUseQueryArgs<A, M extends keyof A> extends ReActorCallArgs<A, M> {
15
+ disableInitialCall?: boolean;
16
+ autoRefresh?: boolean;
17
+ refreshInterval?: number;
18
+ }
19
+ export interface ReActorUseUpdateArgs<A, M extends keyof A> extends ReActorCallArgs<A, M> {
20
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@ic-reactor/react",
3
+ "version": "0.0.1",
4
+ "description": "A React library for interacting with Dfinity actors",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist/*"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git@github.com:b3hr4d/ic-reactor.git"
14
+ },
15
+ "keywords": [
16
+ "actor",
17
+ "react",
18
+ "candid",
19
+ "dfinity",
20
+ "web3",
21
+ "dapp"
22
+ ],
23
+ "author": "b3hr4d",
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/b3hr4d/ic-reactor/issues"
27
+ },
28
+ "homepage": "https://github.com/b3hr4d/ic-reactor/tree/main/packages/react#readme",
29
+ "scripts": {
30
+ "test": "npx jest",
31
+ "start": "tsc watch",
32
+ "build": "npx tsc",
33
+ "clean": "rimraf dist"
34
+ },
35
+ "engines": {
36
+ "node": ">=10"
37
+ },
38
+ "dependencies": {
39
+ "@dfinity/agent": "^0.20",
40
+ "@dfinity/auth-client": "^0.20",
41
+ "@dfinity/candid": "0.20",
42
+ "@dfinity/identity": "^0.20",
43
+ "@dfinity/principal": "^0.20",
44
+ "@ic-reactor/store": "^0.0.1",
45
+ "zustand": "4.4"
46
+ },
47
+ "peerDependencies": {
48
+ "@peculiar/webcrypto": "1.4",
49
+ "react": ">=16.8"
50
+ },
51
+ "gitHead": "b1f673a150b591ad3cfbb8964794e4ea9b0ff1c2"
52
+ }