@ic-reactor/core 3.6.0 → 3.7.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.
- package/README.md +4 -4
- package/dist/client.d.ts +17 -79
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +49 -527
- package/dist/client.js.map +1 -1
- package/dist/display/visitor.d.ts.map +1 -1
- package/dist/display/visitor.js +6 -1
- package/dist/display/visitor.js.map +1 -1
- package/dist/display-reactor.d.ts +3 -0
- package/dist/display-reactor.d.ts.map +1 -1
- package/dist/display-reactor.js +3 -0
- package/dist/display-reactor.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/reactor.d.ts +4 -4
- package/dist/reactor.d.ts.map +1 -1
- package/dist/reactor.js +27 -10
- package/dist/reactor.js.map +1 -1
- package/dist/types/client.d.ts +1 -120
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/display-reactor.d.ts.map +1 -1
- package/dist/types/reactor.d.ts +8 -0
- package/dist/types/reactor.d.ts.map +1 -1
- package/dist/types/variant.d.ts.map +1 -1
- package/dist/utils/agent.d.ts +3 -2
- package/dist/utils/agent.d.ts.map +1 -1
- package/dist/utils/agent.js +9 -3
- package/dist/utils/agent.js.map +1 -1
- package/dist/utils/constants.d.ts +0 -2
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +0 -2
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/helper.d.ts +14 -1
- package/dist/utils/helper.d.ts.map +1 -1
- package/dist/utils/helper.js +48 -9
- package/dist/utils/helper.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/polling.d.ts.map +1 -1
- package/dist/utils/polling.js +2 -2
- package/dist/utils/polling.js.map +1 -1
- package/dist/utils/query-data.d.ts +4 -0
- package/dist/utils/query-data.d.ts.map +1 -0
- package/dist/utils/query-data.js +3 -0
- package/dist/utils/query-data.js.map +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/llms.txt +43 -0
- package/package.json +15 -17
- package/src/client.ts +53 -626
- package/src/display/visitor.ts +10 -1
- package/src/display-reactor.ts +3 -0
- package/src/index.ts +0 -1
- package/src/reactor.ts +48 -18
- package/src/types/client.ts +1 -138
- package/src/types/display-reactor.ts +1 -2
- package/src/types/reactor.ts +15 -0
- package/src/types/variant.ts +8 -6
- package/src/utils/agent.ts +12 -3
- package/src/utils/constants.ts +0 -5
- package/src/utils/helper.ts +52 -7
- package/src/utils/index.ts +1 -0
- package/src/utils/polling.ts +3 -3
- package/src/utils/query-data.ts +5 -0
- package/src/version.ts +2 -2
- package/dist/identity-attributes.d.ts +0 -19
- package/dist/identity-attributes.d.ts.map +0 -1
- package/dist/identity-attributes.js +0 -167
- package/dist/identity-attributes.js.map +0 -1
- package/src/identity-attributes.ts +0 -263
package/dist/client.js
CHANGED
|
@@ -9,31 +9,38 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _ClientManager_agent,
|
|
12
|
+
var _ClientManager_agent, _ClientManager_identitySubscribers, _ClientManager_agentStateSubscribers, _ClientManager_targetCanisterIds;
|
|
13
13
|
import { HttpAgent } from "@icp-sdk/core/agent";
|
|
14
14
|
import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env";
|
|
15
|
-
import { IC_HOST_NETWORK_URI
|
|
16
|
-
import { getNetworkByHostname, getProcessEnvNetwork, isDev, } from "./utils/helper";
|
|
17
|
-
import { decodeIdentityAttributeValues, identityAttributeKeys, normalizeSignedIdentityAttributes, } from "./identity-attributes";
|
|
15
|
+
import { IC_HOST_NETWORK_URI } from "./utils/constants";
|
|
16
|
+
import { getNetworkByHostname, getProcessEnvNetwork, isDev, isMainnetHost, } from "./utils/helper";
|
|
18
17
|
/**
|
|
19
|
-
* ClientManager is a central class for managing the Internet Computer (IC) agent
|
|
18
|
+
* ClientManager is a central class for managing the Internet Computer (IC) agent.
|
|
20
19
|
*
|
|
21
|
-
* It initializes the agent (connecting to local or mainnet)
|
|
22
|
-
*
|
|
20
|
+
* It initializes the agent (connecting to local or mainnet) and integrates
|
|
21
|
+
* with TanStack Query's QueryClient for state management.
|
|
22
|
+
* Use this as a singleton shared by all reactors in an app.
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```typescript
|
|
26
26
|
* import { ClientManager } from "@ic-reactor/core";
|
|
27
|
-
* import { QueryClient } from "@tanstack/
|
|
27
|
+
* import { QueryClient } from "@tanstack/query-core";
|
|
28
28
|
*
|
|
29
29
|
* const queryClient = new QueryClient();
|
|
30
30
|
* const clientManager = new ClientManager({
|
|
31
31
|
* queryClient,
|
|
32
|
-
*
|
|
32
|
+
* agentOptions: { host: "http://127.0.0.1:4943" },
|
|
33
33
|
* });
|
|
34
34
|
*
|
|
35
35
|
* await clientManager.initialize();
|
|
36
36
|
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Reuse the same ClientManager across multiple canisters
|
|
41
|
+
* const backend = new Reactor<BackendService>({ clientManager, idlFactory: backendIdl, name: "backend" })
|
|
42
|
+
* const ledger = new Reactor<LedgerService>({ clientManager, idlFactory: ledgerIdl, name: "ledger" })
|
|
43
|
+
* ```
|
|
37
44
|
*/
|
|
38
45
|
export class ClientManager {
|
|
39
46
|
/**
|
|
@@ -41,12 +48,10 @@ export class ClientManager {
|
|
|
41
48
|
*
|
|
42
49
|
* @param parameters - Configuration options for the agent and network environment.
|
|
43
50
|
*/
|
|
44
|
-
constructor({
|
|
51
|
+
constructor({ agentOptions = {}, queryClient }) {
|
|
45
52
|
_ClientManager_agent.set(this, void 0);
|
|
46
|
-
_ClientManager_authClient.set(this, void 0);
|
|
47
53
|
_ClientManager_identitySubscribers.set(this, []);
|
|
48
54
|
_ClientManager_agentStateSubscribers.set(this, []);
|
|
49
|
-
_ClientManager_authStateSubscribers.set(this, []);
|
|
50
55
|
_ClientManager_targetCanisterIds.set(this, new Set()
|
|
51
56
|
/**
|
|
52
57
|
* The TanStack QueryClient used for managing cached canister data and invalidating queries on identity changes.
|
|
@@ -70,294 +75,12 @@ export class ClientManager {
|
|
|
70
75
|
writable: true,
|
|
71
76
|
value: void 0
|
|
72
77
|
});
|
|
73
|
-
/**
|
|
74
|
-
* Current authentication state, including the active identity, authentication progress, and errors.
|
|
75
|
-
*/
|
|
76
|
-
Object.defineProperty(this, "authState", {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
configurable: true,
|
|
79
|
-
writable: true,
|
|
80
|
-
value: void 0
|
|
81
|
-
});
|
|
82
78
|
Object.defineProperty(this, "initPromise", {
|
|
83
79
|
enumerable: true,
|
|
84
80
|
configurable: true,
|
|
85
81
|
writable: true,
|
|
86
82
|
value: void 0
|
|
87
83
|
});
|
|
88
|
-
Object.defineProperty(this, "authPromise", {
|
|
89
|
-
enumerable: true,
|
|
90
|
-
configurable: true,
|
|
91
|
-
writable: true,
|
|
92
|
-
value: void 0
|
|
93
|
-
});
|
|
94
|
-
Object.defineProperty(this, "authClientConstructor", {
|
|
95
|
-
enumerable: true,
|
|
96
|
-
configurable: true,
|
|
97
|
-
writable: true,
|
|
98
|
-
value: void 0
|
|
99
|
-
});
|
|
100
|
-
Object.defineProperty(this, "authClientConstructorPromise", {
|
|
101
|
-
enumerable: true,
|
|
102
|
-
configurable: true,
|
|
103
|
-
writable: true,
|
|
104
|
-
value: void 0
|
|
105
|
-
});
|
|
106
|
-
Object.defineProperty(this, "authStateRevision", {
|
|
107
|
-
enumerable: true,
|
|
108
|
-
configurable: true,
|
|
109
|
-
writable: true,
|
|
110
|
-
value: 0
|
|
111
|
-
});
|
|
112
|
-
Object.defineProperty(this, "authClientWasProvided", {
|
|
113
|
-
enumerable: true,
|
|
114
|
-
configurable: true,
|
|
115
|
-
writable: true,
|
|
116
|
-
value: false
|
|
117
|
-
});
|
|
118
|
-
Object.defineProperty(this, "port", {
|
|
119
|
-
enumerable: true,
|
|
120
|
-
configurable: true,
|
|
121
|
-
writable: true,
|
|
122
|
-
value: void 0
|
|
123
|
-
});
|
|
124
|
-
Object.defineProperty(this, "internetIdentityId", {
|
|
125
|
-
enumerable: true,
|
|
126
|
-
configurable: true,
|
|
127
|
-
writable: true,
|
|
128
|
-
value: void 0
|
|
129
|
-
});
|
|
130
|
-
Object.defineProperty(this, "authModuleMissing", {
|
|
131
|
-
enumerable: true,
|
|
132
|
-
configurable: true,
|
|
133
|
-
writable: true,
|
|
134
|
-
value: false
|
|
135
|
-
});
|
|
136
|
-
/**
|
|
137
|
-
* Attempts to initialize the authentication client and restore a previous session.
|
|
138
|
-
*
|
|
139
|
-
* If an `AuthClient` is already initialized (passed in constructor or previously created),
|
|
140
|
-
* it uses that instance. Otherwise, it dynamically imports the `@icp-sdk/auth` module
|
|
141
|
-
* and creates a new AuthClient.
|
|
142
|
-
*
|
|
143
|
-
* If the module is missing and no client is provided, it fails gracefully by marking authentication as unavailable.
|
|
144
|
-
*
|
|
145
|
-
* @returns A promise that resolves to the restored Identity, or undefined if auth fails or is unavailable.
|
|
146
|
-
*/
|
|
147
|
-
Object.defineProperty(this, "authenticate", {
|
|
148
|
-
enumerable: true,
|
|
149
|
-
configurable: true,
|
|
150
|
-
writable: true,
|
|
151
|
-
value: async () => {
|
|
152
|
-
if (this.authState.isAuthenticated) {
|
|
153
|
-
return this.authState.identity || undefined;
|
|
154
|
-
}
|
|
155
|
-
if (this.authPromise) {
|
|
156
|
-
return this.authPromise;
|
|
157
|
-
}
|
|
158
|
-
if (this.authModuleMissing) {
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
this.authPromise = (async () => {
|
|
162
|
-
if (isDev() && typeof window !== "undefined") {
|
|
163
|
-
console.info(`%cic-reactor:%c Authenticating...`, "color: #3b82f6; font-weight: bold", "color: inherit", {
|
|
164
|
-
network: this.network,
|
|
165
|
-
authClient: __classPrivateFieldGet(this, _ClientManager_authClient, "f") ? "Shared Instance" : "Dynamic Import",
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
this.updateAuthState({ isAuthenticating: true });
|
|
169
|
-
try {
|
|
170
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
171
|
-
const authClient = await this.initializeAuthClient();
|
|
172
|
-
if (!authClient) {
|
|
173
|
-
this.updateAuthState({ isAuthenticating: false });
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
const identity = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity();
|
|
178
|
-
const isAuthenticated = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").isAuthenticated();
|
|
179
|
-
this.updateAgent(identity);
|
|
180
|
-
this.updateAuthState({
|
|
181
|
-
identity,
|
|
182
|
-
isAuthenticated,
|
|
183
|
-
isAuthenticating: false,
|
|
184
|
-
});
|
|
185
|
-
return identity;
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
this.updateAuthState({ error: error, isAuthenticating: false });
|
|
189
|
-
console.error("Authentication failed:", error);
|
|
190
|
-
throw error;
|
|
191
|
-
}
|
|
192
|
-
finally {
|
|
193
|
-
this.authPromise = undefined;
|
|
194
|
-
}
|
|
195
|
-
})();
|
|
196
|
-
return this.authPromise;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
/**
|
|
200
|
-
* Triggers the login flow using the Internet Identity provider.
|
|
201
|
-
*
|
|
202
|
-
* @param loginOptions - Options for the login flow, including identity provider and callbacks.
|
|
203
|
-
* @throws An error if the authentication module is not installed.
|
|
204
|
-
*/
|
|
205
|
-
Object.defineProperty(this, "login", {
|
|
206
|
-
enumerable: true,
|
|
207
|
-
configurable: true,
|
|
208
|
-
writable: true,
|
|
209
|
-
value: async (loginOptions) => {
|
|
210
|
-
let didCompleteSignIn = false;
|
|
211
|
-
try {
|
|
212
|
-
const identityProvider = loginOptions?.identityProvider || this.getDefaultIdentityProvider();
|
|
213
|
-
const authClientOptions = getAuthClientOptions({
|
|
214
|
-
...loginOptions,
|
|
215
|
-
identityProvider,
|
|
216
|
-
});
|
|
217
|
-
if (!this.ensurePreparedAuthClient(authClientOptions)) {
|
|
218
|
-
await this.initializeAuthClient(authClientOptions);
|
|
219
|
-
}
|
|
220
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
221
|
-
await this.authenticate();
|
|
222
|
-
}
|
|
223
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
224
|
-
throw new Error("Authentication module is missing or failed to initialize. To use login, please install the auth package: npm install @icp-sdk/auth");
|
|
225
|
-
}
|
|
226
|
-
this.updateAuthState({ isAuthenticating: true, error: undefined });
|
|
227
|
-
const identity = await this.signInOrRecoverAuthenticatedIdentity(getSignInOptions(loginOptions));
|
|
228
|
-
if (!this.agentState.isInitialized) {
|
|
229
|
-
await this.initializeAgent();
|
|
230
|
-
}
|
|
231
|
-
this.updateAgent(identity);
|
|
232
|
-
this.updateAuthState({
|
|
233
|
-
identity,
|
|
234
|
-
isAuthenticated: true,
|
|
235
|
-
isAuthenticating: false,
|
|
236
|
-
});
|
|
237
|
-
didCompleteSignIn = true;
|
|
238
|
-
try {
|
|
239
|
-
await loginOptions?.onSuccess?.();
|
|
240
|
-
}
|
|
241
|
-
catch (callbackError) {
|
|
242
|
-
this.updateAuthState({ error: callbackError });
|
|
243
|
-
await loginOptions?.onError?.(callbackError.message);
|
|
244
|
-
throw callbackError;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
catch (error) {
|
|
248
|
-
if (!didCompleteSignIn) {
|
|
249
|
-
await loginOptions?.onError?.(error.message);
|
|
250
|
-
this.updateAuthState({
|
|
251
|
-
error: error,
|
|
252
|
-
isAuthenticating: false,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
throw error;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
/**
|
|
260
|
-
* Logs out the user and reverts the agent to an anonymous identity.
|
|
261
|
-
*
|
|
262
|
-
* @throws An error if the authentication module is not installed.
|
|
263
|
-
*/
|
|
264
|
-
Object.defineProperty(this, "logout", {
|
|
265
|
-
enumerable: true,
|
|
266
|
-
configurable: true,
|
|
267
|
-
writable: true,
|
|
268
|
-
value: async (options) => {
|
|
269
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
270
|
-
throw new Error("Authentication module is missing or failed to initialize. To use logout, please install the auth package: npm install @icp-sdk/auth");
|
|
271
|
-
}
|
|
272
|
-
this.updateAuthState({ isAuthenticating: true, error: undefined });
|
|
273
|
-
await __classPrivateFieldGet(this, _ClientManager_authClient, "f").signOut(options);
|
|
274
|
-
const identity = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity();
|
|
275
|
-
this.updateAgent(identity);
|
|
276
|
-
this.updateAuthState({
|
|
277
|
-
identity,
|
|
278
|
-
isAuthenticated: false,
|
|
279
|
-
isAuthenticating: false,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
Object.defineProperty(this, "requestIdentityAttributes", {
|
|
284
|
-
enumerable: true,
|
|
285
|
-
configurable: true,
|
|
286
|
-
writable: true,
|
|
287
|
-
value: async ({ keys, nonce, identityProvider, openIdProvider, windowOpenerFeatures, signIn = true, maxTimeToLive, targets, }) => {
|
|
288
|
-
const authClientOptions = getAuthClientOptions({
|
|
289
|
-
identityProvider: identityProvider ?? this.getDefaultIdentityProvider(),
|
|
290
|
-
windowOpenerFeatures,
|
|
291
|
-
openIdProvider,
|
|
292
|
-
});
|
|
293
|
-
if (!this.ensurePreparedAuthClient(authClientOptions)) {
|
|
294
|
-
await this.initializeAuthClient(authClientOptions);
|
|
295
|
-
}
|
|
296
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
297
|
-
await this.authenticate();
|
|
298
|
-
}
|
|
299
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
300
|
-
throw new Error("Authentication module is missing or failed to initialize. To request identity attributes, please install @icp-sdk/auth v7 or provide a compatible authClient.");
|
|
301
|
-
}
|
|
302
|
-
this.updateAuthState({ isAuthenticating: true, error: undefined });
|
|
303
|
-
try {
|
|
304
|
-
const identityPromise = signIn
|
|
305
|
-
? this.signInOrRecoverAuthenticatedIdentity({
|
|
306
|
-
maxTimeToLive,
|
|
307
|
-
targets,
|
|
308
|
-
})
|
|
309
|
-
: Promise.resolve(__classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity());
|
|
310
|
-
const requestPromise = __classPrivateFieldGet(this, _ClientManager_authClient, "f").requestAttributes({
|
|
311
|
-
keys,
|
|
312
|
-
nonce,
|
|
313
|
-
});
|
|
314
|
-
const [signedAttributes, identity] = await Promise.all([
|
|
315
|
-
requestPromise,
|
|
316
|
-
identityPromise,
|
|
317
|
-
]);
|
|
318
|
-
const finalIdentity = identity ?? (await __classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity());
|
|
319
|
-
const isAuthenticated = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").isAuthenticated();
|
|
320
|
-
if (!this.agentState.isInitialized) {
|
|
321
|
-
await this.initializeAgent();
|
|
322
|
-
}
|
|
323
|
-
this.updateAgent(finalIdentity);
|
|
324
|
-
this.updateAuthState({
|
|
325
|
-
identity: finalIdentity,
|
|
326
|
-
isAuthenticated,
|
|
327
|
-
isAuthenticating: false,
|
|
328
|
-
});
|
|
329
|
-
const normalizedSignedAttributes = normalizeSignedIdentityAttributes(signedAttributes);
|
|
330
|
-
return {
|
|
331
|
-
principal: finalIdentity.getPrincipal().toText(),
|
|
332
|
-
requestedKeys: keys,
|
|
333
|
-
signedAttributes: normalizedSignedAttributes,
|
|
334
|
-
decodedAttributes: decodeIdentityAttributeValues(normalizedSignedAttributes.data, keys),
|
|
335
|
-
completedAt: new Date().toISOString(),
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
catch (error) {
|
|
339
|
-
this.updateAuthState({ error: error, isAuthenticating: false });
|
|
340
|
-
throw error;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
Object.defineProperty(this, "requestOpenIdIdentityAttributes", {
|
|
345
|
-
enumerable: true,
|
|
346
|
-
configurable: true,
|
|
347
|
-
writable: true,
|
|
348
|
-
value: async ({ nonce, openIdProvider, keys, identityProvider, windowOpenerFeatures, signIn, maxTimeToLive, targets, }) => {
|
|
349
|
-
return this.requestIdentityAttributes({
|
|
350
|
-
keys: identityAttributeKeys({ openIdProvider, keys }),
|
|
351
|
-
nonce,
|
|
352
|
-
identityProvider,
|
|
353
|
-
openIdProvider,
|
|
354
|
-
windowOpenerFeatures,
|
|
355
|
-
signIn,
|
|
356
|
-
maxTimeToLive,
|
|
357
|
-
targets,
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
84
|
this.queryClient = queryClient;
|
|
362
85
|
this.agentState = {
|
|
363
86
|
isInitialized: false,
|
|
@@ -366,109 +89,61 @@ export class ClientManager {
|
|
|
366
89
|
network: undefined,
|
|
367
90
|
isLocalhost: false,
|
|
368
91
|
};
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (withCanisterEnv) {
|
|
379
|
-
const canisterEnv = typeof window !== "undefined" ? safeGetCanisterEnv() : undefined;
|
|
380
|
-
if (canisterEnv) {
|
|
381
|
-
this.internetIdentityId =
|
|
382
|
-
canisterEnv["internet_identity"] ||
|
|
383
|
-
canisterEnv["PUBLIC_CANISTER_ID:internet_identity"] ||
|
|
384
|
-
canisterEnv["CANISTER_ID_INTERNET_IDENTITY"];
|
|
385
|
-
}
|
|
386
|
-
if (isDev() && typeof window !== "undefined") {
|
|
387
|
-
agentOptions.host = agentOptions.host ?? window.location.origin;
|
|
388
|
-
if (agentOptions.verifyQuerySignatures == null) {
|
|
389
|
-
agentOptions.verifyQuerySignatures = false;
|
|
390
|
-
console.warn("[ic-reactor] Query signature verification is DISABLED in development. " +
|
|
391
|
-
"Never use withCanisterEnv in production without explicitly setting verifyQuerySignatures: true.");
|
|
392
|
-
}
|
|
92
|
+
const canisterEnv = typeof window !== "undefined" ? safeGetCanisterEnv() : undefined;
|
|
93
|
+
// Locally deployed asset-canister pages and IC boundary domains can route
|
|
94
|
+
// agent traffic through their serving origin. Ordinary web hosts (Vercel,
|
|
95
|
+
// Cloudflare, etc.) cannot, so they retain the default IC API fallback.
|
|
96
|
+
if (typeof window !== "undefined") {
|
|
97
|
+
const browserOrigin = window.location.origin;
|
|
98
|
+
const browserNetwork = getNetworkByHostname(new URL(browserOrigin).hostname);
|
|
99
|
+
if (browserNetwork === "local" || isMainnetHost(browserOrigin)) {
|
|
100
|
+
agentOptions.host = agentOptions.host ?? browserOrigin;
|
|
393
101
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
// Root key must NOT be sourced from the ic_env cookie: cookies are
|
|
399
|
-
// user-controllable and accepting a root key from them would allow an
|
|
400
|
-
// attacker to bypass all IC certificate verification.
|
|
401
|
-
// If a custom root key is required (e.g. local replica), pass it via
|
|
402
|
-
// agentOptions.rootKey in your application code instead.
|
|
403
|
-
if (canisterEnv?.IC_ROOT_KEY) {
|
|
404
|
-
console.error("[ic-reactor] IC_ROOT_KEY in the ic_env cookie is ignored for security reasons. " +
|
|
405
|
-
"Pass agentOptions.rootKey explicitly if you need a custom root key.");
|
|
102
|
+
}
|
|
103
|
+
if (isDev() && typeof window !== "undefined") {
|
|
104
|
+
if (agentOptions.verifyQuerySignatures == null) {
|
|
105
|
+
agentOptions.verifyQuerySignatures = false;
|
|
406
106
|
}
|
|
407
107
|
}
|
|
408
|
-
|
|
108
|
+
else {
|
|
109
|
+
agentOptions.verifyQuerySignatures =
|
|
110
|
+
agentOptions.verifyQuerySignatures ?? true;
|
|
111
|
+
}
|
|
112
|
+
if (!agentOptions.host) {
|
|
409
113
|
const processNetwork = getProcessEnvNetwork();
|
|
410
|
-
if (processNetwork === "
|
|
411
|
-
|
|
114
|
+
if (processNetwork === "local") {
|
|
115
|
+
const envHost = typeof process !== "undefined"
|
|
116
|
+
? process.env.ICP_HOST || process.env.IC_HOST
|
|
117
|
+
: undefined;
|
|
118
|
+
agentOptions.host = envHost ?? "http://127.0.0.1:4943";
|
|
412
119
|
}
|
|
413
|
-
else
|
|
414
|
-
agentOptions.host =
|
|
415
|
-
typeof process !== "undefined" && process.env.IC_HOST
|
|
416
|
-
? process.env.IC_HOST
|
|
417
|
-
: `http://127.0.0.1:${port}`;
|
|
120
|
+
else {
|
|
121
|
+
agentOptions.host = IC_HOST_NETWORK_URI;
|
|
418
122
|
}
|
|
419
123
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
agentOptions.host = agentOptions.host ?? IC_HOST_NETWORK_URI;
|
|
124
|
+
// For security reasons, the root key from the ic_env cookie is only accepted
|
|
125
|
+
// on non-mainnet environments (e.g. local replicas or custom testnets).
|
|
126
|
+
// On the mainnet ("ic"), we must use the pinned root key inside the agent.
|
|
127
|
+
if (!isMainnetHost(agentOptions.host) && canisterEnv?.IC_ROOT_KEY) {
|
|
128
|
+
agentOptions.rootKey = agentOptions.rootKey ?? canisterEnv.IC_ROOT_KEY;
|
|
426
129
|
}
|
|
427
130
|
__classPrivateFieldSet(this, _ClientManager_agent, HttpAgent.createSync(agentOptions), "f");
|
|
428
131
|
this.updateAgentState({
|
|
429
132
|
isLocalhost: this.isLocal,
|
|
430
133
|
network: this.network,
|
|
431
134
|
});
|
|
432
|
-
if (authClient) {
|
|
433
|
-
this.authClientWasProvided = true;
|
|
434
|
-
__classPrivateFieldSet(this, _ClientManager_authClient, authClient, "f");
|
|
435
|
-
this.syncAuthStateFromClient(this.authStateRevision).catch((error) => {
|
|
436
|
-
this.updateAuthState({ error: error, isAuthenticating: false });
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
else if (typeof window !== "undefined") {
|
|
440
|
-
this.loadAuthClientConstructor().catch(() => {
|
|
441
|
-
// Optional auth support is reported when an auth method is used.
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
135
|
}
|
|
445
136
|
/**
|
|
446
137
|
* Orchestrates the complete initialization of the ClientManager.
|
|
447
138
|
* This method awaits the agent's core initialization (e.g., fetching root keys)
|
|
448
|
-
*
|
|
139
|
+
* Authentication session restoration is handled by AuthenticationManager.
|
|
449
140
|
*
|
|
450
141
|
* @returns A promise that resolves to the ClientManager instance when core initialization is complete.
|
|
451
142
|
*/
|
|
452
143
|
async initialize() {
|
|
453
144
|
await this.initializeAgent();
|
|
454
|
-
this.authenticate();
|
|
455
145
|
return this;
|
|
456
146
|
}
|
|
457
|
-
/**
|
|
458
|
-
* Preloads and creates an AuthClient before a user gesture is needed.
|
|
459
|
-
*
|
|
460
|
-
* Browser signer transports must open their channel directly from a click
|
|
461
|
-
* handler. Apps that pass dynamic auth options, such as OpenID provider
|
|
462
|
-
* aliases, can call this from hover/focus/effect code so the later click path
|
|
463
|
-
* can call signIn/requestAttributes without first awaiting a dynamic import.
|
|
464
|
-
*/
|
|
465
|
-
async prepareAuthClient(options) {
|
|
466
|
-
if (__classPrivateFieldGet(this, _ClientManager_authClient, "f") &&
|
|
467
|
-
(!this.shouldRecreateAuthClient(options) || this.authClientWasProvided)) {
|
|
468
|
-
return __classPrivateFieldGet(this, _ClientManager_authClient, "f");
|
|
469
|
-
}
|
|
470
|
-
return this.initializeAuthClient(options);
|
|
471
|
-
}
|
|
472
147
|
/**
|
|
473
148
|
* Specifically initializes the HttpAgent.
|
|
474
149
|
* On local networks, this includes fetching the root key for certificate verification.
|
|
@@ -513,96 +188,6 @@ export class ClientManager {
|
|
|
513
188
|
get agent() {
|
|
514
189
|
return __classPrivateFieldGet(this, _ClientManager_agent, "f");
|
|
515
190
|
}
|
|
516
|
-
/**
|
|
517
|
-
* The AuthClient instance used for authentication, if available.
|
|
518
|
-
*/
|
|
519
|
-
get authClient() {
|
|
520
|
-
return __classPrivateFieldGet(this, _ClientManager_authClient, "f");
|
|
521
|
-
}
|
|
522
|
-
async initializeAuthClient(options) {
|
|
523
|
-
const AuthClient = await this.loadAuthClientConstructor();
|
|
524
|
-
if (!AuthClient) {
|
|
525
|
-
return undefined;
|
|
526
|
-
}
|
|
527
|
-
__classPrivateFieldSet(this, _ClientManager_authClient, this.createAuthClient(AuthClient, options), "f");
|
|
528
|
-
return __classPrivateFieldGet(this, _ClientManager_authClient, "f");
|
|
529
|
-
}
|
|
530
|
-
async signInOrRecoverAuthenticatedIdentity(options) {
|
|
531
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
532
|
-
throw new Error("Authentication module is missing or failed to initialize. To use login, please install the auth package: npm install @icp-sdk/auth");
|
|
533
|
-
}
|
|
534
|
-
try {
|
|
535
|
-
return await __classPrivateFieldGet(this, _ClientManager_authClient, "f").signIn(options);
|
|
536
|
-
}
|
|
537
|
-
catch (error) {
|
|
538
|
-
const identity = await Promise.resolve(__classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity()).catch(() => null);
|
|
539
|
-
const isAuthenticated = await Promise.resolve(__classPrivateFieldGet(this, _ClientManager_authClient, "f").isAuthenticated()).catch(() => false);
|
|
540
|
-
if (identity && isAuthenticated) {
|
|
541
|
-
return identity;
|
|
542
|
-
}
|
|
543
|
-
throw error;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
async loadAuthClientConstructor() {
|
|
547
|
-
if (this.authClientConstructor) {
|
|
548
|
-
return this.authClientConstructor;
|
|
549
|
-
}
|
|
550
|
-
if (!this.authClientConstructorPromise) {
|
|
551
|
-
this.authClientConstructorPromise = import("@icp-sdk/auth/client")
|
|
552
|
-
.then((authModule) => {
|
|
553
|
-
const AuthClient = authModule.AuthClient;
|
|
554
|
-
if (!AuthClient) {
|
|
555
|
-
throw new Error("@icp-sdk/auth/client did not export AuthClient");
|
|
556
|
-
}
|
|
557
|
-
this.authClientConstructor = AuthClient;
|
|
558
|
-
return AuthClient;
|
|
559
|
-
})
|
|
560
|
-
.catch((error) => {
|
|
561
|
-
this.authModuleMissing = true;
|
|
562
|
-
this.authClientConstructorPromise = undefined;
|
|
563
|
-
if (error instanceof Error &&
|
|
564
|
-
error.message.includes("did not export AuthClient")) {
|
|
565
|
-
throw error;
|
|
566
|
-
}
|
|
567
|
-
return undefined;
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
return this.authClientConstructorPromise;
|
|
571
|
-
}
|
|
572
|
-
createAuthClient(AuthClient, options) {
|
|
573
|
-
return new AuthClient(options);
|
|
574
|
-
}
|
|
575
|
-
ensurePreparedAuthClient(options) {
|
|
576
|
-
if (__classPrivateFieldGet(this, _ClientManager_authClient, "f") &&
|
|
577
|
-
(!this.shouldRecreateAuthClient(options) || this.authClientWasProvided)) {
|
|
578
|
-
return __classPrivateFieldGet(this, _ClientManager_authClient, "f");
|
|
579
|
-
}
|
|
580
|
-
if (!this.authClientConstructor || this.authClientWasProvided) {
|
|
581
|
-
return undefined;
|
|
582
|
-
}
|
|
583
|
-
__classPrivateFieldSet(this, _ClientManager_authClient, this.createAuthClient(this.authClientConstructor, options), "f");
|
|
584
|
-
return __classPrivateFieldGet(this, _ClientManager_authClient, "f");
|
|
585
|
-
}
|
|
586
|
-
shouldRecreateAuthClient(options) {
|
|
587
|
-
return !this.authClientWasProvided && hasAuthClientOptions(options);
|
|
588
|
-
}
|
|
589
|
-
async syncAuthStateFromClient(revision = this.authStateRevision) {
|
|
590
|
-
if (!__classPrivateFieldGet(this, _ClientManager_authClient, "f")) {
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
const identity = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").getIdentity();
|
|
594
|
-
const isAuthenticated = await __classPrivateFieldGet(this, _ClientManager_authClient, "f").isAuthenticated();
|
|
595
|
-
if (revision !== this.authStateRevision) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
this.updateAgent(identity);
|
|
599
|
-
this.updateAuthState({
|
|
600
|
-
identity,
|
|
601
|
-
isAuthenticated,
|
|
602
|
-
isAuthenticating: false,
|
|
603
|
-
error: undefined,
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
191
|
/**
|
|
607
192
|
* The host URL of the current IC agent.
|
|
608
193
|
*/
|
|
@@ -667,17 +252,6 @@ export class ClientManager {
|
|
|
667
252
|
syncTimeWithSubnet(subnetId) {
|
|
668
253
|
return __classPrivateFieldGet(this, _ClientManager_agent, "f").syncTimeWithSubnet(subnetId);
|
|
669
254
|
}
|
|
670
|
-
getDefaultIdentityProvider() {
|
|
671
|
-
if (this.isLocal) {
|
|
672
|
-
if (this.internetIdentityId) {
|
|
673
|
-
return `http://${this.internetIdentityId}.localhost:${this.port}/authorize`;
|
|
674
|
-
}
|
|
675
|
-
return LOCAL_INTERNET_IDENTITY_PROVIDER;
|
|
676
|
-
}
|
|
677
|
-
else {
|
|
678
|
-
return IC_INTERNET_IDENTITY_PROVIDER;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
255
|
/**
|
|
682
256
|
* Subscribes to identity changes (e.g., after login/logout).
|
|
683
257
|
* @param callback - Function called with the new identity.
|
|
@@ -700,17 +274,6 @@ export class ClientManager {
|
|
|
700
274
|
__classPrivateFieldSet(this, _ClientManager_agentStateSubscribers, __classPrivateFieldGet(this, _ClientManager_agentStateSubscribers, "f").filter((sub) => sub !== callback), "f");
|
|
701
275
|
};
|
|
702
276
|
}
|
|
703
|
-
/**
|
|
704
|
-
* Subscribes to changes in the authentication state.
|
|
705
|
-
* @param callback - Function called with the updated authentication state.
|
|
706
|
-
* @returns An unsubscribe function.
|
|
707
|
-
*/
|
|
708
|
-
subscribeAuthState(callback) {
|
|
709
|
-
__classPrivateFieldGet(this, _ClientManager_authStateSubscribers, "f").push(callback);
|
|
710
|
-
return () => {
|
|
711
|
-
__classPrivateFieldSet(this, _ClientManager_authStateSubscribers, __classPrivateFieldGet(this, _ClientManager_authStateSubscribers, "f").filter((sub) => sub !== callback), "f");
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
277
|
/**
|
|
715
278
|
* Replaces the current agent's identity and invalidates TanStack queries.
|
|
716
279
|
* @param identity - The new identity to use.
|
|
@@ -738,51 +301,10 @@ export class ClientManager {
|
|
|
738
301
|
notifyAgentStateSubscribers(state) {
|
|
739
302
|
__classPrivateFieldGet(this, _ClientManager_agentStateSubscribers, "f").forEach((sub) => sub(state));
|
|
740
303
|
}
|
|
741
|
-
notifyAuthStateSubscribers(state) {
|
|
742
|
-
__classPrivateFieldGet(this, _ClientManager_authStateSubscribers, "f").forEach((sub) => sub(state));
|
|
743
|
-
}
|
|
744
304
|
updateAgentState(newState) {
|
|
745
305
|
this.agentState = { ...this.agentState, ...newState };
|
|
746
306
|
this.notifyAgentStateSubscribers(this.agentState);
|
|
747
307
|
}
|
|
748
|
-
updateAuthState(newState) {
|
|
749
|
-
if (isDev())
|
|
750
|
-
console.debug("[ic-reactor] Updating Auth State:", newState);
|
|
751
|
-
this.authStateRevision += 1;
|
|
752
|
-
this.authState = { ...this.authState, ...newState };
|
|
753
|
-
this.notifyAuthStateSubscribers(this.authState);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
_ClientManager_agent = new WeakMap(), _ClientManager_authClient = new WeakMap(), _ClientManager_identitySubscribers = new WeakMap(), _ClientManager_agentStateSubscribers = new WeakMap(), _ClientManager_authStateSubscribers = new WeakMap(), _ClientManager_targetCanisterIds = new WeakMap();
|
|
757
|
-
function getAuthClientOptions(options) {
|
|
758
|
-
if (!options) {
|
|
759
|
-
return undefined;
|
|
760
|
-
}
|
|
761
|
-
return {
|
|
762
|
-
identityProvider: options.identityProvider,
|
|
763
|
-
windowOpenerFeatures: options.windowOpenerFeatures,
|
|
764
|
-
openIdProvider: getAuthClientOpenIdProvider(options.openIdProvider),
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
function getAuthClientOpenIdProvider(openIdProvider) {
|
|
768
|
-
return openIdProvider === "google" ||
|
|
769
|
-
openIdProvider === "apple" ||
|
|
770
|
-
openIdProvider === "microsoft"
|
|
771
|
-
? openIdProvider
|
|
772
|
-
: undefined;
|
|
773
|
-
}
|
|
774
|
-
function hasAuthClientOptions(options) {
|
|
775
|
-
return Boolean(options?.identityProvider ||
|
|
776
|
-
options?.windowOpenerFeatures ||
|
|
777
|
-
options?.openIdProvider);
|
|
778
|
-
}
|
|
779
|
-
function getSignInOptions(options) {
|
|
780
|
-
if (!options) {
|
|
781
|
-
return undefined;
|
|
782
|
-
}
|
|
783
|
-
return {
|
|
784
|
-
maxTimeToLive: options.maxTimeToLive,
|
|
785
|
-
targets: options.targets,
|
|
786
|
-
};
|
|
787
308
|
}
|
|
309
|
+
_ClientManager_agent = new WeakMap(), _ClientManager_identitySubscribers = new WeakMap(), _ClientManager_agentStateSubscribers = new WeakMap(), _ClientManager_targetCanisterIds = new WeakMap();
|
|
788
310
|
//# sourceMappingURL=client.js.map
|