@ic-reactor/core 3.5.1 → 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 +6 -11
- 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 +16 -18
- package/src/client.ts +53 -627
- 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 -14
- package/dist/identity-attributes.d.ts.map +0 -1
- package/dist/identity-attributes.js +0 -161
- package/dist/identity-attributes.js.map +0 -1
- package/src/identity-attributes.ts +0 -256
package/src/display/visitor.ts
CHANGED
|
@@ -154,7 +154,16 @@ export class DisplayCodecVisitor extends IDL.Visitor<unknown, z.ZodTypeAny> {
|
|
|
154
154
|
decode: (val) => {
|
|
155
155
|
if (val instanceof Principal) return val.toText()
|
|
156
156
|
if (typeof val === "string") return val
|
|
157
|
-
|
|
157
|
+
if (
|
|
158
|
+
val &&
|
|
159
|
+
typeof val === "object" &&
|
|
160
|
+
typeof (val as { toText?: unknown }).toText === "function"
|
|
161
|
+
) {
|
|
162
|
+
return (val as { toText: () => string }).toText()
|
|
163
|
+
}
|
|
164
|
+
throw new TypeError(
|
|
165
|
+
`[ic-reactor] Cannot decode value as Principal display text: expected a string or Principal instance, got ${typeof val}`
|
|
166
|
+
)
|
|
158
167
|
},
|
|
159
168
|
encode: (val) => {
|
|
160
169
|
if (typeof val === "string") return Principal.fromText(val)
|
package/src/display-reactor.ts
CHANGED
|
@@ -44,6 +44,9 @@ import {
|
|
|
44
44
|
* Validators receive **display types** (strings), making them perfect for
|
|
45
45
|
* form validation.
|
|
46
46
|
*
|
|
47
|
+
* Use `DisplayReactor` for UI/forms where principals and numeric values should
|
|
48
|
+
* be string-friendly. Use `Reactor` when you need raw Candid types directly.
|
|
49
|
+
*
|
|
47
50
|
* @typeParam A - The actor service type
|
|
48
51
|
*
|
|
49
52
|
* @example
|
package/src/index.ts
CHANGED
package/src/reactor.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
TransformKey,
|
|
15
15
|
ReactorArgs,
|
|
16
16
|
ReactorReturnOk,
|
|
17
|
+
ReactorQueryData,
|
|
17
18
|
ReactorQueryParams,
|
|
18
19
|
ReactorCallParams,
|
|
19
20
|
CanisterId,
|
|
@@ -23,6 +24,7 @@ import { DEFAULT_POLLING_OPTIONS } from "@icp-sdk/core/agent"
|
|
|
23
24
|
import { IDL } from "@icp-sdk/core/candid"
|
|
24
25
|
import { Principal } from "@icp-sdk/core/principal"
|
|
25
26
|
import { generateKey, extractOkResult } from "./utils/helper"
|
|
27
|
+
import { toReactorQueryData } from "./utils/query-data"
|
|
26
28
|
import {
|
|
27
29
|
processQueryCallResponse,
|
|
28
30
|
processUpdateCallResponse,
|
|
@@ -206,13 +208,23 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
206
208
|
: this.canisterId.toString()
|
|
207
209
|
const queryKeys: any[] = [resolvedCanisterId, params.functionName]
|
|
208
210
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
const effectiveTarget =
|
|
212
|
+
callConfig?.effectiveTarget ??
|
|
213
|
+
(callConfig?.effectiveCanisterId
|
|
214
|
+
? { canisterId: callConfig.effectiveCanisterId }
|
|
215
|
+
: undefined)
|
|
216
|
+
|
|
217
|
+
if (effectiveTarget) {
|
|
218
|
+
const targetKey =
|
|
219
|
+
"canisterId" in effectiveTarget
|
|
220
|
+
? { canisterId: effectiveTarget.canisterId.toString() }
|
|
221
|
+
: { subnetId: effectiveTarget.subnetId.toString() }
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
!("canisterId" in targetKey) ||
|
|
225
|
+
targetKey.canisterId !== resolvedCanisterId
|
|
226
|
+
) {
|
|
227
|
+
queryKeys.push({ effectiveTarget: targetKey })
|
|
216
228
|
}
|
|
217
229
|
}
|
|
218
230
|
|
|
@@ -232,10 +244,15 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
232
244
|
|
|
233
245
|
public getQueryOptions<M extends FunctionName<A>>(
|
|
234
246
|
params: ReactorCallParams<A, M, T>
|
|
235
|
-
): FetchQueryOptions<ReactorReturnOk<A, M, T
|
|
247
|
+
): FetchQueryOptions<ReactorQueryData<ReactorReturnOk<A, M, T>>> {
|
|
236
248
|
return {
|
|
237
249
|
queryKey: this.generateQueryKey(params, params.callConfig),
|
|
238
|
-
queryFn: () =>
|
|
250
|
+
queryFn: async () => {
|
|
251
|
+
const result = await this.callMethod(params)
|
|
252
|
+
return toReactorQueryData<ReactorReturnOk<A, M, T>>(
|
|
253
|
+
result as ReactorReturnOk<A, M, T>
|
|
254
|
+
)
|
|
255
|
+
},
|
|
239
256
|
}
|
|
240
257
|
}
|
|
241
258
|
|
|
@@ -376,9 +393,11 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
376
393
|
*/
|
|
377
394
|
public async fetchQuery<M extends FunctionName<A>>(
|
|
378
395
|
params: ReactorCallParams<A, M, T>
|
|
379
|
-
): Promise<ReactorReturnOk<A, M, T
|
|
396
|
+
): Promise<ReactorQueryData<ReactorReturnOk<A, M, T>>> {
|
|
380
397
|
const options = this.getQueryOptions(params)
|
|
381
|
-
return this.queryClient.ensureQueryData<
|
|
398
|
+
return this.queryClient.ensureQueryData<
|
|
399
|
+
ReactorQueryData<ReactorReturnOk<A, M, T>>
|
|
400
|
+
>(options)
|
|
382
401
|
}
|
|
383
402
|
|
|
384
403
|
/**
|
|
@@ -387,9 +406,11 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
387
406
|
public getQueryData<M extends FunctionName<A>>(
|
|
388
407
|
params: ReactorQueryParams<A, M, T>,
|
|
389
408
|
callConfig?: CallConfig
|
|
390
|
-
): ReactorReturnOk<A, M, T
|
|
409
|
+
): ReactorQueryData<ReactorReturnOk<A, M, T>> | undefined {
|
|
391
410
|
const queryKey = this.generateQueryKey(params, callConfig)
|
|
392
|
-
return this.queryClient.getQueryData<
|
|
411
|
+
return this.queryClient.getQueryData<
|
|
412
|
+
ReactorQueryData<ReactorReturnOk<A, M, T>>
|
|
413
|
+
>(queryKey)
|
|
393
414
|
}
|
|
394
415
|
|
|
395
416
|
/**
|
|
@@ -404,12 +425,16 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
404
425
|
const canisterId = callConfig?.canisterId
|
|
405
426
|
? Principal.from(callConfig.canisterId)
|
|
406
427
|
: this.canisterId
|
|
407
|
-
const
|
|
428
|
+
const effectiveTarget =
|
|
429
|
+
callConfig?.effectiveTarget ??
|
|
430
|
+
(callConfig?.effectiveCanisterId
|
|
431
|
+
? { canisterId: callConfig.effectiveCanisterId }
|
|
432
|
+
: { canisterId })
|
|
408
433
|
|
|
409
434
|
const response = await agent.query(canisterId, {
|
|
410
435
|
methodName,
|
|
411
436
|
arg,
|
|
412
|
-
|
|
437
|
+
effectiveTarget,
|
|
413
438
|
})
|
|
414
439
|
|
|
415
440
|
return processQueryCallResponse(response, canisterId, methodName)
|
|
@@ -427,13 +452,17 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
427
452
|
const canisterId = callConfig?.canisterId
|
|
428
453
|
? Principal.from(callConfig.canisterId)
|
|
429
454
|
: this.canisterId
|
|
430
|
-
const
|
|
455
|
+
const effectiveTarget =
|
|
456
|
+
callConfig?.effectiveTarget ??
|
|
457
|
+
(callConfig?.effectiveCanisterId
|
|
458
|
+
? { canisterId: callConfig.effectiveCanisterId }
|
|
459
|
+
: { canisterId })
|
|
431
460
|
const pollingOptions = callConfig?.pollingOptions ?? this.pollingOptions
|
|
432
461
|
|
|
433
462
|
const response = await agent.call(canisterId, {
|
|
434
463
|
methodName,
|
|
435
464
|
arg,
|
|
436
|
-
|
|
465
|
+
effectiveTarget,
|
|
437
466
|
nonce: callConfig?.nonce,
|
|
438
467
|
})
|
|
439
468
|
|
|
@@ -442,7 +471,8 @@ export class Reactor<A = BaseActor, T extends TransformKey = "candid"> {
|
|
|
442
471
|
canisterId,
|
|
443
472
|
methodName,
|
|
444
473
|
agent,
|
|
445
|
-
pollingOptions
|
|
474
|
+
pollingOptions,
|
|
475
|
+
effectiveTarget
|
|
446
476
|
)
|
|
447
477
|
}
|
|
448
478
|
|
package/src/types/client.ts
CHANGED
|
@@ -1,96 +1,12 @@
|
|
|
1
|
-
import type { HttpAgent, HttpAgentOptions
|
|
2
|
-
import type { Principal } from "@icp-sdk/core/principal"
|
|
1
|
+
import type { HttpAgent, HttpAgentOptions } from "@icp-sdk/core/agent"
|
|
3
2
|
import type { QueryClient } from "@tanstack/query-core"
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Parameters for configuring a ClientManager instance.
|
|
7
6
|
*
|
|
8
7
|
* @property {QueryClient} queryClient - The TanStack QueryClient used for caching and state management.
|
|
9
|
-
* @property {number} [port] - The port used for the local IC replica (default is 4943).
|
|
10
8
|
* @property {HttpAgentOptions} [agentOptions] - Optional configuration for the underlying HttpAgent.
|
|
11
|
-
* @property {boolean} [withLocalEnv] - If true, configures the agent for a local environment.
|
|
12
|
-
* @property {boolean} [withProcessEnv] - If true, auto-configures the agent based on process.env settings.
|
|
13
9
|
*/
|
|
14
|
-
export interface SignedIdentityAttributes {
|
|
15
|
-
data: Uint8Array
|
|
16
|
-
signature: Uint8Array
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface IdentityAttributeRequest {
|
|
20
|
-
keys: string[]
|
|
21
|
-
nonce: Uint8Array
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface IdentityAttributeValues {
|
|
25
|
-
email?: string
|
|
26
|
-
name?: string
|
|
27
|
-
verified_email?: string
|
|
28
|
-
[key: string]: string | undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface IdentityAttributeResult {
|
|
32
|
-
principal: string
|
|
33
|
-
requestedKeys: string[]
|
|
34
|
-
signedAttributes: SignedIdentityAttributes
|
|
35
|
-
decodedAttributes: IdentityAttributeValues
|
|
36
|
-
completedAt: string
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
type IdentityAttributeOpenIdProviderAlias = "google" | "apple" | "microsoft"
|
|
40
|
-
|
|
41
|
-
export type IdentityAttributeOpenIdProvider =
|
|
42
|
-
| IdentityAttributeOpenIdProviderAlias
|
|
43
|
-
| (string & {})
|
|
44
|
-
|
|
45
|
-
export interface ClientManagerAuthClientOptions {
|
|
46
|
-
identityProvider?: string | URL
|
|
47
|
-
windowOpenerFeatures?: string
|
|
48
|
-
openIdProvider?: IdentityAttributeOpenIdProvider
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface AuthClientSignInOptions {
|
|
52
|
-
maxTimeToLive?: bigint
|
|
53
|
-
targets?: Principal[]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface ClientManagerSignInOptions
|
|
57
|
-
extends AuthClientSignInOptions, ClientManagerAuthClientOptions {
|
|
58
|
-
onSuccess?: () => void | Promise<void>
|
|
59
|
-
onError?: (error?: string) => void | Promise<void>
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface RequestIdentityAttributesParameters {
|
|
63
|
-
keys: string[]
|
|
64
|
-
nonce: Uint8Array
|
|
65
|
-
identityProvider?: string | URL
|
|
66
|
-
openIdProvider?: IdentityAttributeOpenIdProvider
|
|
67
|
-
windowOpenerFeatures?: string
|
|
68
|
-
signIn?: boolean
|
|
69
|
-
maxTimeToLive?: bigint
|
|
70
|
-
targets?: Principal[]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface RequestOpenIdIdentityAttributesParameters {
|
|
74
|
-
nonce: Uint8Array
|
|
75
|
-
openIdProvider: IdentityAttributeOpenIdProvider
|
|
76
|
-
keys: string[]
|
|
77
|
-
identityProvider?: string | URL
|
|
78
|
-
windowOpenerFeatures?: string
|
|
79
|
-
signIn?: boolean
|
|
80
|
-
maxTimeToLive?: bigint
|
|
81
|
-
targets?: Principal[]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface AuthClientLike {
|
|
85
|
-
getIdentity(): Promise<Identity> | Identity
|
|
86
|
-
isAuthenticated(): Promise<boolean> | boolean
|
|
87
|
-
signIn(options?: AuthClientSignInOptions): Promise<Identity>
|
|
88
|
-
logout(options?: { returnTo?: string }): Promise<void>
|
|
89
|
-
requestAttributes(
|
|
90
|
-
params: IdentityAttributeRequest
|
|
91
|
-
): Promise<SignedIdentityAttributes>
|
|
92
|
-
}
|
|
93
|
-
|
|
94
10
|
export interface ClientManagerParameters {
|
|
95
11
|
/**
|
|
96
12
|
* The TanStack QueryClient used for caching and state management.
|
|
@@ -100,37 +16,6 @@ export interface ClientManagerParameters {
|
|
|
100
16
|
* Optional configuration for the underlying HttpAgent.
|
|
101
17
|
*/
|
|
102
18
|
agentOptions?: HttpAgentOptions
|
|
103
|
-
/**
|
|
104
|
-
* The port used for the local IC replica (default is 4943).
|
|
105
|
-
*/
|
|
106
|
-
port?: number
|
|
107
|
-
/**
|
|
108
|
-
* If true, configures the agent for a local environment.
|
|
109
|
-
*/
|
|
110
|
-
withLocalEnv?: boolean
|
|
111
|
-
/**
|
|
112
|
-
* If true, auto-configures the agent based on process.env settings.
|
|
113
|
-
*/
|
|
114
|
-
withProcessEnv?: boolean
|
|
115
|
-
/**
|
|
116
|
-
* Optional pre-initialized AuthClient instance.
|
|
117
|
-
* If provided, the manager will use this instance instead of dynamically importing
|
|
118
|
-
* and creating a new one from `@icp-sdk/auth`.
|
|
119
|
-
* This is useful for environments where dynamic imports are not supported or
|
|
120
|
-
* when you want to share an AuthClient instance across multiple managers.
|
|
121
|
-
*/
|
|
122
|
-
authClient?: AuthClientLike
|
|
123
|
-
/**
|
|
124
|
-
* **EXPERIMENTAL** - If true, uses the canister environment from `@icp-sdk/core/agent/canister-env`
|
|
125
|
-
* to automatically configure the agent host and root key based on the `ic_env` cookie.
|
|
126
|
-
*
|
|
127
|
-
* ⚠️ This feature is experimental and may cause issues with update calls on localhost development.
|
|
128
|
-
* Use with caution and only when you need automatic environment detection from the IC SDK.
|
|
129
|
-
*
|
|
130
|
-
* @experimental
|
|
131
|
-
* @default false
|
|
132
|
-
*/
|
|
133
|
-
withCanisterEnv?: boolean
|
|
134
19
|
}
|
|
135
20
|
|
|
136
21
|
/**
|
|
@@ -163,28 +48,6 @@ export interface AgentState {
|
|
|
163
48
|
isLocalhost: boolean
|
|
164
49
|
}
|
|
165
50
|
|
|
166
|
-
/**
|
|
167
|
-
* Represents the authentication state of an agent.
|
|
168
|
-
*/
|
|
169
|
-
export interface AuthState {
|
|
170
|
-
identity: Identity | null
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Indicates whether the authentication process is ongoing.
|
|
174
|
-
*/
|
|
175
|
-
isAuthenticating: boolean
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Indicates whether the agent is authenticated.
|
|
179
|
-
*/
|
|
180
|
-
isAuthenticated: boolean
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Represents any error that occurred during authentication.
|
|
184
|
-
*/
|
|
185
|
-
error: Error | undefined
|
|
186
|
-
}
|
|
187
|
-
|
|
188
51
|
export interface UpdateAgentParameters extends HttpAgentOptions {
|
|
189
52
|
agent?: HttpAgent
|
|
190
53
|
}
|
|
@@ -15,8 +15,7 @@ import {
|
|
|
15
15
|
* Either success (true) or failure with issues.
|
|
16
16
|
*/
|
|
17
17
|
export type ValidationResult =
|
|
18
|
-
| { success:
|
|
19
|
-
| { success: false; issues: ValidationIssue[] }
|
|
18
|
+
{ success: true } | { success: false; issues: ValidationIssue[] }
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* A validator function that validates method arguments.
|
package/src/types/reactor.ts
CHANGED
|
@@ -130,6 +130,21 @@ export type ReactorReturnOk<
|
|
|
130
130
|
Transform extends TransformKey = "candid",
|
|
131
131
|
> = TransformReturnRegistry<OkResult<ActorMethodReturnType<A[M]>>, A>[Transform]
|
|
132
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Data stored by TanStack Query for a reactor call.
|
|
135
|
+
*
|
|
136
|
+
* TanStack Query reserves `undefined` for a missing cache entry, so successful
|
|
137
|
+
* canister results that contain only `undefined` are represented as `null` at
|
|
138
|
+
* the query boundary. Direct `callMethod` calls keep their original result.
|
|
139
|
+
*/
|
|
140
|
+
export type ReactorQueryData<T> = 0 extends 1 & T
|
|
141
|
+
? T
|
|
142
|
+
: [T] extends [void]
|
|
143
|
+
? null
|
|
144
|
+
: undefined extends T
|
|
145
|
+
? Exclude<T, undefined> | null
|
|
146
|
+
: T
|
|
147
|
+
|
|
133
148
|
export type ReactorReturnErr<
|
|
134
149
|
A,
|
|
135
150
|
M extends FunctionName<A>,
|
package/src/types/variant.ts
CHANGED
|
@@ -20,12 +20,14 @@ export type CandidVariant<T> =
|
|
|
20
20
|
? {
|
|
21
21
|
_type: CandidVariantKey<T> & string
|
|
22
22
|
} & {
|
|
23
|
-
[
|
|
24
|
-
T
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
[
|
|
24
|
+
K in CandidVariantKey<T> & string as CandidVariantValue<
|
|
25
|
+
T,
|
|
26
|
+
K
|
|
27
|
+
> extends null
|
|
28
|
+
? never
|
|
29
|
+
: K
|
|
30
|
+
]: CandidVariantValue<T, K>
|
|
29
31
|
}
|
|
30
32
|
: T
|
|
31
33
|
|
package/src/utils/agent.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
HttpDetailsResponse,
|
|
5
5
|
PollingOptions,
|
|
6
6
|
SubmitResponse,
|
|
7
|
+
TargetPrincipal,
|
|
7
8
|
} from "@icp-sdk/core/agent"
|
|
8
9
|
import { Principal } from "@icp-sdk/core/principal"
|
|
9
10
|
|
|
@@ -40,6 +41,8 @@ export function processQueryCallResponse(
|
|
|
40
41
|
canisterId: Principal,
|
|
41
42
|
methodName: string
|
|
42
43
|
): Uint8Array {
|
|
44
|
+
const effectiveTarget = { canisterId }
|
|
45
|
+
|
|
43
46
|
switch (response.status) {
|
|
44
47
|
case QueryResponseStatus.Rejected: {
|
|
45
48
|
const uncertifiedRejectErrorCode = new UncertifiedRejectErrorCode(
|
|
@@ -51,6 +54,7 @@ export function processQueryCallResponse(
|
|
|
51
54
|
)
|
|
52
55
|
uncertifiedRejectErrorCode.callContext = {
|
|
53
56
|
canisterId,
|
|
57
|
+
effectiveTarget,
|
|
54
58
|
methodName,
|
|
55
59
|
httpDetails: response.httpDetails,
|
|
56
60
|
}
|
|
@@ -79,6 +83,7 @@ export function processQueryCallResponse(
|
|
|
79
83
|
* @param methodName - The method name being called
|
|
80
84
|
* @param agent - The HTTP agent
|
|
81
85
|
* @param pollingOptions - Options for polling
|
|
86
|
+
* @param effectiveTarget - Canister or subnet used to route and verify the call
|
|
82
87
|
* @returns The raw reply bytes
|
|
83
88
|
* @throws RejectError if the call was rejected
|
|
84
89
|
* @throws UnknownError if the response format is unexpected
|
|
@@ -88,7 +93,8 @@ export async function processUpdateCallResponse(
|
|
|
88
93
|
canisterId: Principal,
|
|
89
94
|
methodName: string,
|
|
90
95
|
agent: Agent,
|
|
91
|
-
pollingOptions: PollingOptions
|
|
96
|
+
pollingOptions: PollingOptions,
|
|
97
|
+
effectiveTarget: TargetPrincipal
|
|
92
98
|
): Promise<Uint8Array> {
|
|
93
99
|
let reply: Uint8Array | undefined
|
|
94
100
|
let certificate: Certificate | undefined
|
|
@@ -101,7 +107,7 @@ export async function processUpdateCallResponse(
|
|
|
101
107
|
certificate = await Certificate.create({
|
|
102
108
|
certificate: cert,
|
|
103
109
|
rootKey: agent.rootKey,
|
|
104
|
-
principal:
|
|
110
|
+
principal: effectiveTarget,
|
|
105
111
|
agent,
|
|
106
112
|
})
|
|
107
113
|
|
|
@@ -144,6 +150,7 @@ export async function processUpdateCallResponse(
|
|
|
144
150
|
)
|
|
145
151
|
certifiedRejectErrorCode.callContext = {
|
|
146
152
|
canisterId,
|
|
153
|
+
effectiveTarget,
|
|
147
154
|
methodName,
|
|
148
155
|
httpDetails: result.response,
|
|
149
156
|
}
|
|
@@ -160,6 +167,7 @@ export async function processUpdateCallResponse(
|
|
|
160
167
|
)
|
|
161
168
|
errorCode.callContext = {
|
|
162
169
|
canisterId,
|
|
170
|
+
effectiveTarget,
|
|
163
171
|
methodName,
|
|
164
172
|
httpDetails: result.response,
|
|
165
173
|
}
|
|
@@ -171,7 +179,7 @@ export async function processUpdateCallResponse(
|
|
|
171
179
|
// Contains the certificate and the reply from the boundary node
|
|
172
180
|
const response = await pollForResponse(
|
|
173
181
|
agent,
|
|
174
|
-
|
|
182
|
+
effectiveTarget,
|
|
175
183
|
result.requestId,
|
|
176
184
|
pollingOptions
|
|
177
185
|
)
|
|
@@ -193,6 +201,7 @@ export async function processUpdateCallResponse(
|
|
|
193
201
|
)
|
|
194
202
|
errorCode.callContext = {
|
|
195
203
|
canisterId,
|
|
204
|
+
effectiveTarget,
|
|
196
205
|
methodName,
|
|
197
206
|
httpDetails,
|
|
198
207
|
}
|
package/src/utils/constants.ts
CHANGED
|
@@ -5,8 +5,3 @@ export const LOCAL_HOSTS = ["localhost", "127.0.0.1"]
|
|
|
5
5
|
export const IC_HOST_NETWORK_URI = "https://ic0.app"
|
|
6
6
|
|
|
7
7
|
export const LOCAL_HOST_NETWORK_URI = "http://127.0.0.1:4943"
|
|
8
|
-
|
|
9
|
-
export const IC_INTERNET_IDENTITY_PROVIDER = "https://id.ai/authorize"
|
|
10
|
-
|
|
11
|
-
export const LOCAL_INTERNET_IDENTITY_PROVIDER =
|
|
12
|
-
"http://rdmx6-jaaaa-aaaaa-aaadq-cai.localhost:4943"
|
package/src/utils/helper.ts
CHANGED
|
@@ -8,23 +8,37 @@ export const generateKey = (args: any[]) => {
|
|
|
8
8
|
)
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
const getEnv = () => {
|
|
12
|
+
try {
|
|
13
|
+
return process.env
|
|
14
|
+
} catch {
|
|
15
|
+
return undefined
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
/**
|
|
12
20
|
* Checks if the current environment is local or development.
|
|
13
21
|
*
|
|
22
|
+
* Honors both legacy `DFX_NETWORK` (dfx) and `ICP_NETWORK` (icp-cli).
|
|
23
|
+
*
|
|
14
24
|
* @returns `true` if running in a local or development environment, otherwise `false`.
|
|
15
25
|
*/
|
|
16
26
|
export const isInLocalOrDevelopment = () => {
|
|
17
|
-
|
|
27
|
+
const env = getEnv()
|
|
28
|
+
return env?.DFX_NETWORK === "local" || env?.ICP_NETWORK === "local"
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
/**
|
|
21
32
|
* Retrieves the network from the process environment variables.
|
|
22
33
|
*
|
|
34
|
+
* Honors both legacy `DFX_NETWORK` (dfx) and `ICP_NETWORK` (icp-cli),
|
|
35
|
+
* with `ICP_NETWORK` taking precedence when both are set.
|
|
36
|
+
*
|
|
23
37
|
* @returns The network name, defaulting to "ic" if not specified.
|
|
24
38
|
*/
|
|
25
39
|
export const getProcessEnvNetwork = () => {
|
|
26
|
-
|
|
27
|
-
|
|
40
|
+
const env = getEnv()
|
|
41
|
+
return env?.ICP_NETWORK ?? env?.DFX_NETWORK ?? "ic"
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
/**
|
|
@@ -33,19 +47,50 @@ export const getProcessEnvNetwork = () => {
|
|
|
33
47
|
* Checks in order:
|
|
34
48
|
* - `import.meta.env?.DEV` (Vite / ESM environments)
|
|
35
49
|
* - `process.env.NODE_ENV === 'development'` (Node)
|
|
36
|
-
* - `process.env.DFX_NETWORK === 'local'` (local
|
|
50
|
+
* - `process.env.DFX_NETWORK === 'local'` (dfx local replica)
|
|
51
|
+
* - `process.env.ICP_NETWORK === 'local'` (icp-cli local network)
|
|
37
52
|
*/
|
|
38
53
|
export const isDev = (): boolean => {
|
|
39
54
|
const importMetaDev =
|
|
40
55
|
typeof import.meta !== "undefined" && (import.meta as any).env?.DEV
|
|
56
|
+
const env = getEnv()
|
|
41
57
|
const nodeDev =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
58
|
+
env?.NODE_ENV === "development" ||
|
|
59
|
+
env?.DFX_NETWORK === "local" ||
|
|
60
|
+
env?.ICP_NETWORK === "local"
|
|
45
61
|
|
|
46
62
|
return Boolean(importMetaDev || nodeDev)
|
|
47
63
|
}
|
|
48
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Checks if a given host URL is a mainnet Internet Computer boundary node host.
|
|
67
|
+
*
|
|
68
|
+
* @param host - The host URL to evaluate.
|
|
69
|
+
* @returns `true` if the host is a mainnet host, default to true if host is undefined, otherwise `false`.
|
|
70
|
+
*/
|
|
71
|
+
export const isMainnetHost = (host?: string): boolean => {
|
|
72
|
+
if (!host) return true
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const url = new URL(
|
|
76
|
+
host.startsWith("http")
|
|
77
|
+
? host
|
|
78
|
+
: `${typeof window !== "undefined" ? window.location.protocol : "https:"}//${host}`
|
|
79
|
+
)
|
|
80
|
+
const hostname = url.hostname
|
|
81
|
+
return (
|
|
82
|
+
hostname === "ic0.app" ||
|
|
83
|
+
hostname.endsWith(".ic0.app") ||
|
|
84
|
+
hostname === "icp0.io" ||
|
|
85
|
+
hostname.endsWith(".icp0.io") ||
|
|
86
|
+
hostname === "icp-api.io" ||
|
|
87
|
+
hostname.endsWith(".icp-api.io")
|
|
88
|
+
)
|
|
89
|
+
} catch {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
49
94
|
/**
|
|
50
95
|
* Determines the network type based on the provided hostname.
|
|
51
96
|
*
|
package/src/utils/index.ts
CHANGED
package/src/utils/polling.ts
CHANGED
|
@@ -29,8 +29,8 @@ import {
|
|
|
29
29
|
PollStrategy,
|
|
30
30
|
RequestId,
|
|
31
31
|
RequestStatusResponseStatus,
|
|
32
|
+
TargetPrincipal,
|
|
32
33
|
} from "@icp-sdk/core/agent"
|
|
33
|
-
import { Principal } from "@icp-sdk/core/principal"
|
|
34
34
|
|
|
35
35
|
export interface PollingConfig {
|
|
36
36
|
/**
|
|
@@ -283,14 +283,14 @@ export function createPollingStrategy(cfg: PollingConfig = {}): PollStrategy {
|
|
|
283
283
|
* Async strategy function invoked by the IC agent on each polling cycle.
|
|
284
284
|
* Determines whether to continue waiting based on request status.
|
|
285
285
|
*
|
|
286
|
-
* @param {
|
|
286
|
+
* @param {TargetPrincipal} _effectiveTarget - Target canister or subnet (unused but required by interface)
|
|
287
287
|
* @param {RequestId} _requestId - Request identifier (unused but required by interface)
|
|
288
288
|
* @param {RequestStatusResponseStatus} [rawStatus] - Current request status from IC
|
|
289
289
|
* @returns {Promise<void>} - Resolves after calculated delay, or immediately for terminal states
|
|
290
290
|
* @throws {Error} - If abortSignal is triggered
|
|
291
291
|
*/
|
|
292
292
|
return async function strategy(
|
|
293
|
-
|
|
293
|
+
_effectiveTarget: TargetPrincipal,
|
|
294
294
|
_requestId: RequestId,
|
|
295
295
|
rawStatus?: RequestStatusResponseStatus
|
|
296
296
|
): Promise<void> {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReactorQueryData } from "../types/reactor"
|
|
2
|
+
|
|
3
|
+
/** Convert a direct reactor result into a value TanStack Query can cache. */
|
|
4
|
+
export const toReactorQueryData = <T>(value: T): ReactorQueryData<T> =>
|
|
5
|
+
(value === undefined ? null : value) as ReactorQueryData<T>
|
package/src/version.ts
CHANGED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { IdentityAttributeOpenIdProvider, IdentityAttributeValues, SignedIdentityAttributes } from "./types/client";
|
|
2
|
-
export declare const IDENTITY_ATTRIBUTES_BETA_PROVIDER = "https://beta.id.ai/authorize";
|
|
3
|
-
export declare function identityAttributeKeys({ openIdProvider, keys, }: {
|
|
4
|
-
openIdProvider: IdentityAttributeOpenIdProvider;
|
|
5
|
-
keys: string[];
|
|
6
|
-
}): string[];
|
|
7
|
-
export declare function normalizeOpenIdProvider(openIdProvider: IdentityAttributeOpenIdProvider): string;
|
|
8
|
-
export declare function resolveIdentityAttributeKeys({ openIdProvider, keys, }: {
|
|
9
|
-
openIdProvider: IdentityAttributeOpenIdProvider;
|
|
10
|
-
keys: string[];
|
|
11
|
-
}): Promise<string[]>;
|
|
12
|
-
export declare function decodeIdentityAttributeValues(data: Uint8Array, requestedKeys: string[]): IdentityAttributeValues;
|
|
13
|
-
export declare function normalizeSignedIdentityAttributes(attributes: SignedIdentityAttributes): SignedIdentityAttributes;
|
|
14
|
-
//# sourceMappingURL=identity-attributes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"identity-attributes.d.ts","sourceRoot":"","sources":["../src/identity-attributes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,+BAA+B,EAC/B,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,gBAAgB,CAAA;AAEvB,eAAO,MAAM,iCAAiC,iCAAiC,CAAA;AAQ/E,wBAAgB,qBAAqB,CAAC,EACpC,cAAc,EACd,IAAI,GACL,EAAE;IACD,cAAc,EAAE,+BAA+B,CAAA;IAC/C,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,GAAG,MAAM,EAAE,CAGX;AAED,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,+BAA+B,GAC9C,MAAM,CAMR;AAED,wBAAsB,4BAA4B,CAAC,EACjD,cAAc,EACd,IAAI,GACL,EAAE;IACD,cAAc,EAAE,+BAA+B,CAAA;IAC/C,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEpB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,MAAM,EAAE,GACtB,uBAAuB,CAgBzB;AAsLD,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,wBAAwB,GACnC,wBAAwB,CAK1B"}
|