@ic-reactor/core 2.0.0 → 3.0.0-beta.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/dist/client.d.ts +161 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +499 -0
- package/dist/client.js.map +1 -0
- package/dist/display/helper.d.ts +10 -0
- package/dist/display/helper.d.ts.map +1 -0
- package/dist/display/helper.js +67 -0
- package/dist/display/helper.js.map +1 -0
- package/dist/display/index.d.ts +4 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +4 -0
- package/dist/display/index.js.map +1 -0
- package/dist/display/types.d.ts +31 -0
- package/dist/display/types.d.ts.map +1 -0
- package/dist/display/types.js +2 -0
- package/dist/display/types.js.map +1 -0
- package/dist/display/visitor.d.ts +28 -0
- package/dist/display/visitor.d.ts.map +1 -0
- package/dist/display/visitor.js +318 -0
- package/dist/display/visitor.js.map +1 -0
- package/dist/display-reactor.d.ts +245 -0
- package/dist/display-reactor.d.ts.map +1 -0
- package/dist/display-reactor.js +331 -0
- package/dist/display-reactor.js.map +1 -0
- package/dist/errors/index.d.ts +118 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +204 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -47
- package/dist/index.js.map +1 -0
- package/dist/reactor.d.ts +133 -0
- package/dist/reactor.d.ts.map +1 -0
- package/dist/reactor.js +325 -0
- package/dist/reactor.js.map +1 -0
- package/dist/types/client.d.ts +89 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +2 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/reactor.d.ts +117 -0
- package/dist/types/reactor.d.ts.map +1 -0
- package/dist/types/reactor.js +2 -0
- package/dist/types/reactor.js.map +1 -0
- package/dist/types/result.d.ts +48 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +2 -0
- package/dist/types/result.js.map +1 -0
- package/dist/types/transform.d.ts +7 -0
- package/dist/types/transform.d.ts.map +1 -0
- package/dist/types/transform.js +2 -0
- package/dist/types/transform.js.map +1 -0
- package/dist/types/variant.d.ts +18 -0
- package/dist/types/variant.d.ts.map +1 -0
- package/dist/types/variant.js +2 -0
- package/dist/types/variant.js.map +1 -0
- package/dist/utils/agent.d.ts +30 -1
- package/dist/utils/agent.d.ts.map +1 -0
- package/dist/utils/agent.js +118 -16
- package/dist/utils/agent.js.map +1 -0
- package/dist/utils/candid.d.ts +39 -1
- package/dist/utils/candid.d.ts.map +1 -0
- package/dist/utils/candid.js +76 -16
- package/dist/utils/candid.js.map +1 -0
- package/dist/utils/constants.d.ts +3 -4
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +7 -11
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/helper.d.ts +16 -39
- package/dist/utils/helper.d.ts.map +1 -0
- package/dist/utils/helper.js +53 -155
- package/dist/utils/helper.js.map +1 -0
- package/dist/utils/index.d.ts +4 -5
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -49
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/polling.d.ts +176 -0
- package/dist/utils/polling.d.ts.map +1 -0
- package/dist/utils/polling.js +170 -0
- package/dist/utils/polling.js.map +1 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +65 -39
- package/LICENSE.md +0 -8
- package/README.md +0 -283
- package/dist/classes/actor/index.d.ts +0 -34
- package/dist/classes/actor/index.js +0 -245
- package/dist/classes/actor/types.d.ts +0 -113
- package/dist/classes/actor/types.js +0 -2
- package/dist/classes/adapter/index.d.ts +0 -19
- package/dist/classes/adapter/index.js +0 -140
- package/dist/classes/adapter/types.d.ts +0 -14
- package/dist/classes/adapter/types.js +0 -2
- package/dist/classes/agent/index.d.ts +0 -36
- package/dist/classes/agent/index.js +0 -218
- package/dist/classes/agent/types.d.ts +0 -87
- package/dist/classes/agent/types.js +0 -2
- package/dist/classes/index.d.ts +0 -3
- package/dist/classes/index.js +0 -19
- package/dist/classes/types.d.ts +0 -15
- package/dist/classes/types.js +0 -20
- package/dist/createActorManager.d.ts +0 -12
- package/dist/createActorManager.js +0 -17
- package/dist/createAgentManager.d.ts +0 -12
- package/dist/createAgentManager.js +0 -17
- package/dist/createCandidAdapter.d.ts +0 -11
- package/dist/createCandidAdapter.js +0 -16
- package/dist/createReactorCore.d.ts +0 -10
- package/dist/createReactorCore.js +0 -112
- package/dist/createReactorStore.d.ts +0 -11
- package/dist/createReactorStore.js +0 -31
- package/dist/types.d.ts +0 -96
- package/dist/types.js +0 -17
- package/dist/utils/hash.d.ts +0 -12
- package/dist/utils/hash.js +0 -70
- package/dist/utils/principal.d.ts +0 -1
- package/dist/utils/principal.js +0 -17
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module polling
|
|
3
|
+
* @description
|
|
4
|
+
* Polling strategy for Internet Computer (Dfinity) agent update calls.
|
|
5
|
+
*
|
|
6
|
+
* This module provides a configurable, intelligent polling mechanism that:
|
|
7
|
+
* - Starts with rapid polling for quick responses (fast phase)
|
|
8
|
+
* - Gradually increases delay intervals (ramp phase)
|
|
9
|
+
* - Settles into steady-state polling (plateau phase)
|
|
10
|
+
* - Adds jitter to prevent thundering herd problems
|
|
11
|
+
* - Provides structured logging with elapsed time and status
|
|
12
|
+
* - Supports graceful cancellation via AbortSignal
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const strategy = createPollingStrategy({
|
|
17
|
+
* context: "signer-creation",
|
|
18
|
+
* fastAttempts: 10,
|
|
19
|
+
* plateauDelayMs: 5000
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* const result = await actor.createSigner(params, {
|
|
23
|
+
* pollingOptions: { strategy }
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { RequestStatusResponseStatus, } from "@icp-sdk/core/agent";
|
|
28
|
+
/**
|
|
29
|
+
* Creates an polling strategy for Internet Computer agent update calls.
|
|
30
|
+
*
|
|
31
|
+
* The strategy implements three phases:
|
|
32
|
+
* 1. **Fast Phase**: Initial rapid polling (default: 10 attempts @ 100ms intervals)
|
|
33
|
+
* 2. **Ramp Phase**: Exponential backoff growth (default: up to 20s elapsed)
|
|
34
|
+
* 3. **Plateau Phase**: Steady-state polling (default: 5s intervals)
|
|
35
|
+
*
|
|
36
|
+
* The strategy continues polling while request status is RECEIVED/PROCESSING,
|
|
37
|
+
* and only terminates on REPLIED/REJECTED/DONE status or when aborted.
|
|
38
|
+
*
|
|
39
|
+
* @param {PollingConfig} [cfg={}] - Configuration options
|
|
40
|
+
* @returns {PollStrategy} - Async strategy function compatible with agent pollingOptions.strategy
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // Basic usage
|
|
45
|
+
* const strategy = createPollingStrategy();
|
|
46
|
+
*
|
|
47
|
+
* // Custom configuration for long-running operations
|
|
48
|
+
* const strategy = createPollingStrategy({
|
|
49
|
+
* context: "blockchain-sync",
|
|
50
|
+
* fastAttempts: 5,
|
|
51
|
+
* fastDelayMs: 200,
|
|
52
|
+
* rampUntilMs: 30_000,
|
|
53
|
+
* plateauDelayMs: 10_000,
|
|
54
|
+
* jitterRatio: 0.3
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* // With abort signal
|
|
58
|
+
* const controller = new AbortController();
|
|
59
|
+
* const strategy = createPollingStrategy({
|
|
60
|
+
* context: "transaction-signing",
|
|
61
|
+
* abortSignal: controller.signal
|
|
62
|
+
* });
|
|
63
|
+
* // Later: controller.abort();
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @throws {Error} When abortSignal is triggered during polling
|
|
67
|
+
*/
|
|
68
|
+
export function createPollingStrategy(cfg = {}) {
|
|
69
|
+
const { context = "operation", logPrefix = "[Polling]", fastAttempts = 10, fastDelayMs = 100, rampUntilMs = 20000, plateauDelayMs = 5000, jitterRatio = 0.4, maxLogIntervalMs = 15000, abortSignal, } = cfg;
|
|
70
|
+
let attempt = 0;
|
|
71
|
+
const start = Date.now();
|
|
72
|
+
let lastLog = 0;
|
|
73
|
+
/**
|
|
74
|
+
* Structured logging function that outputs polling state information.
|
|
75
|
+
* Implements intelligent log throttling to prevent console spam while ensuring
|
|
76
|
+
* periodic heartbeat logs for long-running operations.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} phase - Current polling phase ("fast", "ramp", or "plateau")
|
|
79
|
+
* @param {string | undefined} statusKind - Request status from IC agent
|
|
80
|
+
* @param {number} nextDelay - Calculated delay until next poll (ms)
|
|
81
|
+
*/
|
|
82
|
+
const log = (phase, statusKind, nextDelay) => {
|
|
83
|
+
const now = Date.now();
|
|
84
|
+
// Suppress ultra-noisy logs: skip if < 1s since last log and not in fast phase
|
|
85
|
+
if (now - lastLog < 1000 && phase !== "fast" && nextDelay < 1000)
|
|
86
|
+
return;
|
|
87
|
+
// Force a heartbeat log if too much time has passed (prevents silent operations)
|
|
88
|
+
if (now - lastLog > maxLogIntervalMs) {
|
|
89
|
+
phase += "+heartbeat";
|
|
90
|
+
}
|
|
91
|
+
lastLog = now;
|
|
92
|
+
// eslint-disable-next-line no-console
|
|
93
|
+
console.info(`${logPrefix} ${context} attempt=${attempt} elapsed=${now - start}ms status=${statusKind} phase=${phase} nextDelay=${Math.round(nextDelay)}ms`);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Computes the next polling delay based on elapsed time and attempt count.
|
|
97
|
+
* Implements three-phase strategy:
|
|
98
|
+
* - Fast: Initial rapid polling
|
|
99
|
+
* - Ramp: Exponential growth with power curve
|
|
100
|
+
* - Plateau: Steady-state polling
|
|
101
|
+
*
|
|
102
|
+
* @param {number} elapsed - Milliseconds elapsed since start
|
|
103
|
+
* @param {number} a - Current attempt number
|
|
104
|
+
* @returns {{ delay: number; phase: string }} - Calculated delay and phase name
|
|
105
|
+
*/
|
|
106
|
+
const computeDelay = (elapsed, a) => {
|
|
107
|
+
// Phase 1: Fast initial polling
|
|
108
|
+
if (a < fastAttempts) {
|
|
109
|
+
return { delay: withJitter(fastDelayMs), phase: "fast" };
|
|
110
|
+
}
|
|
111
|
+
// Phase 2: Ramp with exponential growth (power curve 0.7 for smooth acceleration)
|
|
112
|
+
if (elapsed < rampUntilMs) {
|
|
113
|
+
const progress = elapsed / rampUntilMs; // Normalized progress: 0..1
|
|
114
|
+
const base = fastDelayMs + (plateauDelayMs - fastDelayMs) * Math.pow(progress, 0.7);
|
|
115
|
+
return { delay: withJitter(base), phase: "ramp" };
|
|
116
|
+
}
|
|
117
|
+
// Phase 3: Plateau - steady-state polling
|
|
118
|
+
return { delay: withJitter(plateauDelayMs), phase: "plateau" };
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Applies random jitter to prevent synchronized polling across multiple clients.
|
|
122
|
+
* Uses configured jitterRatio to add ±N% randomness to the base delay.
|
|
123
|
+
*
|
|
124
|
+
* @param {number} base - Base delay in milliseconds
|
|
125
|
+
* @returns {number} - Jittered delay, minimum 50ms
|
|
126
|
+
*/
|
|
127
|
+
const withJitter = (base) => {
|
|
128
|
+
const spread = base * jitterRatio;
|
|
129
|
+
return Math.max(50, base - spread + Math.random() * spread * 2);
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Async strategy function invoked by the IC agent on each polling cycle.
|
|
133
|
+
* Determines whether to continue waiting based on request status.
|
|
134
|
+
*
|
|
135
|
+
* @param {Principal} _canisterId - Target canister principal (unused but required by interface)
|
|
136
|
+
* @param {RequestId} _requestId - Request identifier (unused but required by interface)
|
|
137
|
+
* @param {RequestStatusResponseStatus} [rawStatus] - Current request status from IC
|
|
138
|
+
* @returns {Promise<void>} - Resolves after calculated delay, or immediately for terminal states
|
|
139
|
+
* @throws {Error} - If abortSignal is triggered
|
|
140
|
+
*/
|
|
141
|
+
return async function strategy(_canisterId, _requestId, rawStatus) {
|
|
142
|
+
// Check for external cancellation
|
|
143
|
+
if (abortSignal?.aborted) {
|
|
144
|
+
throw new Error(`${context} polling aborted`);
|
|
145
|
+
}
|
|
146
|
+
attempt++;
|
|
147
|
+
const statusKind = rawStatus;
|
|
148
|
+
// Terminal states: Stop polling immediately
|
|
149
|
+
// - Replied: Request completed successfully
|
|
150
|
+
// - Rejected: Request was rejected by canister
|
|
151
|
+
// - Done: Request processing complete
|
|
152
|
+
// Note: Agent typically stops before we reach here, but we handle defensively
|
|
153
|
+
if (statusKind === RequestStatusResponseStatus.Replied ||
|
|
154
|
+
statusKind === RequestStatusResponseStatus.Rejected ||
|
|
155
|
+
statusKind === RequestStatusResponseStatus.Done) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// Continue polling for:
|
|
159
|
+
// - Received: Request received but not yet processed
|
|
160
|
+
// - Processing: Request is being processed
|
|
161
|
+
// - Unknown: Status not yet available
|
|
162
|
+
// - undefined: No status information yet
|
|
163
|
+
const elapsed = Date.now() - start;
|
|
164
|
+
const { delay, phase } = computeDelay(elapsed, attempt);
|
|
165
|
+
log(phase, statusKind, delay);
|
|
166
|
+
// Sleep for calculated delay before next poll
|
|
167
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=polling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling.js","sourceRoot":"","sources":["../../src/utils/polling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,OAAO,UAAU,CAAA"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,60 +1,86 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/core",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
|
+
"description": "IC Reactor Core Library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
7
17
|
"files": [
|
|
8
|
-
"dist
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
9
20
|
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -b",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"version:sync": "node -e \"const pkg = require('./package.json'); const fs = require('fs'); fs.writeFileSync('./src/version.ts', '/**\\n * Library version - automatically synced from package.json.\\n */\\nexport const VERSION = \\\"' + pkg.version + '\\\"\\n');\"",
|
|
25
|
+
"size": "size-limit",
|
|
26
|
+
"analyze": "size-limit --why"
|
|
27
|
+
},
|
|
10
28
|
"repository": {
|
|
11
29
|
"type": "git",
|
|
12
|
-
"url": "
|
|
30
|
+
"url": "https://github.com/B3Pay/ic-reactor",
|
|
31
|
+
"directory": "packages/core"
|
|
13
32
|
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/B3Pay/ic-reactor/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://ic-reactor.dev",
|
|
14
37
|
"keywords": [
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"candid",
|
|
38
|
+
"internet-computer",
|
|
39
|
+
"icp",
|
|
18
40
|
"dfinity",
|
|
19
41
|
"web3",
|
|
20
|
-
"
|
|
42
|
+
"blockchain",
|
|
43
|
+
"canister",
|
|
44
|
+
"actor",
|
|
45
|
+
"reactor",
|
|
46
|
+
"tanstack-query"
|
|
21
47
|
],
|
|
22
|
-
"author": "
|
|
48
|
+
"author": "Behrad Deylami",
|
|
23
49
|
"license": "MIT",
|
|
24
|
-
"bugs": {
|
|
25
|
-
"url": "https://github.com/b3hr4d/ic-reactor/issues"
|
|
26
|
-
},
|
|
27
|
-
"homepage": "https://b3pay.github.io/ic-reactor/modules/core.html",
|
|
28
50
|
"dependencies": {
|
|
29
|
-
"@
|
|
30
|
-
"
|
|
31
|
-
"@dfinity/candid": "^3.1.0",
|
|
32
|
-
"@dfinity/identity": "^3.1.0",
|
|
33
|
-
"@dfinity/principal": "^3.1.0",
|
|
34
|
-
"zustand": "5.0.6"
|
|
51
|
+
"@noble/curves": "^2.0.1",
|
|
52
|
+
"zod": "^4.3.2"
|
|
35
53
|
},
|
|
36
54
|
"peerDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
"@icp-sdk/core": "^5.0.0",
|
|
56
|
+
"@icp-sdk/auth": "^5.0.0",
|
|
57
|
+
"@tanstack/query-core": "^5.0.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"@icp-sdk/auth": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"@tanstack/query-core": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
42
66
|
},
|
|
43
67
|
"devDependencies": {
|
|
44
|
-
"@
|
|
68
|
+
"@icp-sdk/auth": "^5.0.0",
|
|
69
|
+
"@icp-sdk/core": "^5.0.0",
|
|
70
|
+
"@size-limit/preset-small-lib": "^11.2.0",
|
|
71
|
+
"@tanstack/query-core": "^5.90",
|
|
72
|
+
"@tanstack/react-query": "^5.90",
|
|
73
|
+
"@types/node": "^24.10.1",
|
|
74
|
+
"fake-indexeddb": "^6.2.5",
|
|
75
|
+
"size-limit": "^11.2.0",
|
|
76
|
+
"vitest": "^4.0.16"
|
|
45
77
|
},
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"clean": "bun run rimraf dist && bun run rimraf umd && bun run rimraf node_modules"
|
|
55
|
-
},
|
|
56
|
-
"engines": {
|
|
57
|
-
"node": ">=22.0.0"
|
|
58
|
-
},
|
|
59
|
-
"gitHead": "2677a090df726dc4f4216eb406b135a32334507b"
|
|
78
|
+
"size-limit": [
|
|
79
|
+
{
|
|
80
|
+
"name": "Core Library",
|
|
81
|
+
"path": "dist/index.js",
|
|
82
|
+
"limit": "50 KB",
|
|
83
|
+
"gzip": true
|
|
84
|
+
}
|
|
85
|
+
]
|
|
60
86
|
}
|
package/LICENSE.md
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
The `@ic-reactor/core` package provides a streamlined way to interact with the Internet Computer (IC). It simplifies agent and actor management, ensuring type-safe communication with canisters. This package offers utilities for creating and managing IC agents, enabling seamless interaction through a friendly API.
|
|
2
|
-
|
|
3
|
-
## Installation
|
|
4
|
-
|
|
5
|
-
To get started with `@ic-reactor/core`, you can install the package using npm or Yarn:
|
|
6
|
-
|
|
7
|
-
**Using npm:**
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @ic-reactor/core
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
**Using Yarn:**
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
yarn add @ic-reactor/core
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
or you can use the UMD version:
|
|
20
|
-
|
|
21
|
-
```html
|
|
22
|
-
<script src="https://github.com/B3Pay/ic-reactor/releases/download/v1.15.0/ic-reactor-core.min.js"></script>
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Using `createReactorCore`
|
|
26
|
-
|
|
27
|
-
For ease of use, the `createReactorCore` factory function automatically sets up a new Reactor instance, managing the agent and its state internally, and providing a simple API for authenticating, querying, and updating actors.
|
|
28
|
-
|
|
29
|
-
**Example:**
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import { createReactorCore } from "@ic-reactor/core"
|
|
33
|
-
import { candid, canisterId, idlFactory } from "./declarations/candid"
|
|
34
|
-
|
|
35
|
-
type Candid = typeof candid
|
|
36
|
-
|
|
37
|
-
const { queryCall, updateCall, getPrincipal, login } =
|
|
38
|
-
createReactorCore<Candid>({
|
|
39
|
-
canisterId,
|
|
40
|
-
idlFactory,
|
|
41
|
-
withProcessEnv: true, // will use process.env.DFX_NETWORK
|
|
42
|
-
})
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
You can find All available methods are returned from the `createReactorCore` function [here](https://b3pay.github.io/ic-reactor/interfaces/core.types.CreateReactorCoreReturnType.html).
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
// later in your code
|
|
49
|
-
await login({
|
|
50
|
-
onSuccess: () => {
|
|
51
|
-
console.log("Logged in successfully")
|
|
52
|
-
},
|
|
53
|
-
onError: (error) => {
|
|
54
|
-
console.error("Failed to login:", error)
|
|
55
|
-
},
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
// queryCall, will automatically call and return a promise with the result
|
|
59
|
-
const { dataPromise, call } = queryCall({
|
|
60
|
-
functionName: "icrc1_balance_of",
|
|
61
|
-
args: [{ owner: getPrincipal(), subaccount: [] }],
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
console.log(await dataPromise)
|
|
65
|
-
|
|
66
|
-
// updateCall
|
|
67
|
-
const { call, subscribe } = updateCall({
|
|
68
|
-
functionName: "icrc1_transfer",
|
|
69
|
-
args: [
|
|
70
|
-
{
|
|
71
|
-
to: { owner: getPrincipal(), subaccount: [] },
|
|
72
|
-
amount: BigInt(10000000000),
|
|
73
|
-
fee: [],
|
|
74
|
-
memo: [],
|
|
75
|
-
created_at_time: [],
|
|
76
|
-
from_subaccount: [],
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
})
|
|
80
|
-
// subscribe to the update call
|
|
81
|
-
subscribe(({ loading, error, data }) => {
|
|
82
|
-
console.log({ loading, error, data })
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
const result = await call()
|
|
86
|
-
console.log(result)
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Managing Multiple Actors
|
|
90
|
-
|
|
91
|
-
When interacting with multiple canisters using `@ic-reactor/core`, you need one agent manager for each canister. This way, you can create separate reactor for each canister. This enables modular interaction with different services on the Internet Computer,
|
|
92
|
-
and allows you to manage the state of each actor independently.
|
|
93
|
-
Here's how to adjust the example to handle methods that require multiple arguments:
|
|
94
|
-
|
|
95
|
-
Fist you need to create a agent manager:
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
// agent.ts
|
|
99
|
-
import { createAgentManager } from "@ic-reactor/core"
|
|
100
|
-
|
|
101
|
-
export const agentManager = createAgentManager() // Connects to IC network by default
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
Then you can create a Actor for each canister:
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// Assuming you've already set up `candidA`, `candidB`, and `agentManager`
|
|
108
|
-
import { createActorManager } from "@ic-reactor/core"
|
|
109
|
-
import * as candidA from "./declarations/candidA"
|
|
110
|
-
import * as candidB from "./declarations/candidB"
|
|
111
|
-
import { agentManager } from "./agent"
|
|
112
|
-
|
|
113
|
-
type CandidA = typeof candidA.candidA
|
|
114
|
-
type CandidB = typeof candidB.candidB
|
|
115
|
-
|
|
116
|
-
const actorA = createActorManager<CandidA>({
|
|
117
|
-
agentManager,
|
|
118
|
-
canisterId: candidA.canisterId,
|
|
119
|
-
idlFactory: candidA.idlFactory,
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
const actorB = createActorManager<CandidB>({
|
|
123
|
-
agentManager,
|
|
124
|
-
canisterId: candidB.canisterId,
|
|
125
|
-
idlFactory: candidB.idlFactory,
|
|
126
|
-
})
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
You can now use the `actorA` and `actorB` instances to interact with their respective canisters:
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
const { dataPromise: version } = actorA.queryCall({
|
|
133
|
-
functionName: "version",
|
|
134
|
-
})
|
|
135
|
-
console.log("Response from CanisterA method:", await version)
|
|
136
|
-
|
|
137
|
-
const { dataPromise: balance } = actorB.queryCall({
|
|
138
|
-
functionName: "balance",
|
|
139
|
-
args: [principal, []],
|
|
140
|
-
})
|
|
141
|
-
console.log("Response from CanisterB method:", await balance)
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Using Candid Adapter
|
|
145
|
-
|
|
146
|
-
The `CandidAdapter` class is used to interact with a canister and retrieve its Candid interface definition. It provides methods to fetch the Candid definition either from the canister's metadata or by using a temporary hack method.
|
|
147
|
-
If both methods fail, it throws an error.
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
import { createCandidAdapter } from "@ic-reactor/core"
|
|
151
|
-
import { agentManager } from "./agent"
|
|
152
|
-
|
|
153
|
-
const candidAdapter = createCandidAdapter({ agentManager })
|
|
154
|
-
|
|
155
|
-
const canisterId = "ryjl3-tyaaa-aaaaa-aaaba-cai"
|
|
156
|
-
|
|
157
|
-
// Usage example
|
|
158
|
-
try {
|
|
159
|
-
const definition = await candidAdapter.getCandidDefinition(canisterId)
|
|
160
|
-
console.log(definition)
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error(error)
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Using `createReactorCore` with `CandidAdapter`
|
|
167
|
-
|
|
168
|
-
You can use the `candidAdapter` to fetch the Candid definition and then pass it to the `createReactorCore` function.
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
import { createReactorCore, createCandidAdapter } from "@ic-reactor/core"
|
|
172
|
-
import { agentManager } from "./agent"
|
|
173
|
-
|
|
174
|
-
const candidAdapter = createCandidAdapter({ agentManager })
|
|
175
|
-
|
|
176
|
-
const canisterId = "ryjl3-tyaaa-aaaaa-aaaba-cai" // NNS ICP Ledger Canister
|
|
177
|
-
|
|
178
|
-
// Usage example
|
|
179
|
-
try {
|
|
180
|
-
const { idlFactory } = await candidAdapter.getCandidDefinition(canisterId)
|
|
181
|
-
const { callMethod } = createReactorCore({
|
|
182
|
-
agentManager,
|
|
183
|
-
canisterId,
|
|
184
|
-
idlFactory,
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
const name = await callMethod("name")
|
|
188
|
-
console.log(name) // { name: 'Internet Computer' }
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.error(error)
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Using store to lower level control
|
|
195
|
-
|
|
196
|
-
If you require more control over the state management, you can use the `createReactorStore` function to create a store that provides methods for querying and updating actors.
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
import { createReactorStore } from "@ic-reactor/core"
|
|
200
|
-
import { candid, canisterId, idlFactory } from "./declarations/candid"
|
|
201
|
-
|
|
202
|
-
type Candid = typeof candid
|
|
203
|
-
|
|
204
|
-
const { agentManager, callMethod } = createReactorStore<Candid>({
|
|
205
|
-
canisterId,
|
|
206
|
-
idlFactory,
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
// Usage example
|
|
210
|
-
await agentManager.authenticate()
|
|
211
|
-
const authClient = agentManager.getAuth()
|
|
212
|
-
|
|
213
|
-
authClient?.login({
|
|
214
|
-
onSuccess: () => {
|
|
215
|
-
console.log("Logged in successfully")
|
|
216
|
-
},
|
|
217
|
-
onError: (error) => {
|
|
218
|
-
console.error("Failed to login:", error)
|
|
219
|
-
},
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
// Call a method
|
|
223
|
-
const version = callMethod("version")
|
|
224
|
-
|
|
225
|
-
console.log("Response from version method:", await version)
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**IC Agent Example:**
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
// agent.ts
|
|
232
|
-
import { createAgentManager } from "@ic-reactor/core"
|
|
233
|
-
|
|
234
|
-
export const agentManager = createAgentManager() // Connects to IC network by default
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
**Local Agent Example:**
|
|
238
|
-
|
|
239
|
-
For development purposes, you might want to connect to a local instance of the IC network:
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
// agent.ts
|
|
243
|
-
import { createAgentManager } from "@ic-reactor/core"
|
|
244
|
-
|
|
245
|
-
export const agentManager = createAgentManager({
|
|
246
|
-
withLocalEnv: true,
|
|
247
|
-
port: 8000, // Default port is 4943
|
|
248
|
-
})
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Alternatively, you can specify a host directly:
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
// agent.ts
|
|
255
|
-
import { createAgentManager } from "@ic-reactor/core"
|
|
256
|
-
|
|
257
|
-
export const agentManager = createAgentManager({
|
|
258
|
-
host: "http://localhost:8000",
|
|
259
|
-
})
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Creating an Actor Manager
|
|
263
|
-
|
|
264
|
-
You can use Actor Managers to create your implementation of an actor. This allows you to manage the actor's lifecycle and state, as well as interact with the actor's methods.
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
// actor.ts
|
|
268
|
-
import { createActorManager } from "@ic-reactor/core"
|
|
269
|
-
import { candid, canisterId, idlFactory } from "./declarations/candid"
|
|
270
|
-
import { agentManager } from "./agent"
|
|
271
|
-
|
|
272
|
-
type Candid = typeof candid
|
|
273
|
-
|
|
274
|
-
const candidActor = createActorManager<Candid>({
|
|
275
|
-
agentManager,
|
|
276
|
-
canisterId,
|
|
277
|
-
idlFactory,
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
// Usage example
|
|
281
|
-
const data = await candidActor.callMethod("version")
|
|
282
|
-
console.log(data)
|
|
283
|
-
```
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { CallConfig } from "@dfinity/agent";
|
|
2
|
-
import type { ActorMethodParameters, ActorMethodReturnType, ActorStore, ActorManagerParameters, FunctionName, VisitService, BaseActor, ActorMethodState, MethodAttributes } from "./types";
|
|
3
|
-
import { IDL } from "@dfinity/candid";
|
|
4
|
-
import type { AgentManager } from "../agent";
|
|
5
|
-
import type { UpdateAgentParameters } from "../types";
|
|
6
|
-
export declare class ActorManager<A = BaseActor> {
|
|
7
|
-
private _actor;
|
|
8
|
-
private _idlFactory;
|
|
9
|
-
private _agentManager;
|
|
10
|
-
private _unsubscribeAgent;
|
|
11
|
-
private _subscribers;
|
|
12
|
-
canisterId: string;
|
|
13
|
-
actorStore: ActorStore<A>;
|
|
14
|
-
visitFunction: VisitService<A>;
|
|
15
|
-
methodAttributes: MethodAttributes<A>;
|
|
16
|
-
private updateState;
|
|
17
|
-
updateMethodState: (method: FunctionName<A>, hash: string, newState: Partial<ActorMethodState<A, typeof method>[string]>) => void;
|
|
18
|
-
constructor(actorConfig: ActorManagerParameters);
|
|
19
|
-
initialize: (options?: UpdateAgentParameters) => Promise<void>;
|
|
20
|
-
extractInterface: () => IDL.ServiceClass;
|
|
21
|
-
extractMethodAttributes: () => MethodAttributes<A>;
|
|
22
|
-
extractVisitor: () => VisitService<A>;
|
|
23
|
-
private initializeActor;
|
|
24
|
-
private _getActorMethod;
|
|
25
|
-
callMethod: <M extends FunctionName<A>>(functionName: M, ...args: ActorMethodParameters<A[M]>) => Promise<ActorMethodReturnType<A[M]>>;
|
|
26
|
-
callMethodWithOptions: (options: CallConfig) => <M extends FunctionName<A>>(functionName: M, ...args: ActorMethodParameters<A[M]>) => Promise<ActorMethodReturnType<A[M]>>;
|
|
27
|
-
call: <M extends FunctionName<A>>(functionName: M, ...args: ActorMethodParameters<A[M]>) => Promise<ActorMethodReturnType<A[M]>>;
|
|
28
|
-
get agentManager(): AgentManager;
|
|
29
|
-
getActor: () => A | null;
|
|
30
|
-
getState: ActorStore<A>["getState"];
|
|
31
|
-
subscribeActorState: ActorStore<A>["subscribe"];
|
|
32
|
-
setState: ActorStore<A>["setState"];
|
|
33
|
-
cleanup: () => void;
|
|
34
|
-
}
|