@holochain/client 0.19.0-dev.1 → 0.19.0-dev.3
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/lib/api/app/types.d.ts +210 -4
- package/lib/api/app/types.js +47 -0
- package/lib/api/app/websocket.d.ts +86 -6
- package/lib/api/app/websocket.js +97 -10
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +0 -1
- package/lib/environments/launcher.d.ts +2 -2
- package/lib/hdk/action.d.ts +7 -0
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +3 -3
package/lib/api/app/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnsubscribeFunction } from "emittery";
|
|
2
|
-
import { AgentPubKey, AppAuthenticationToken, AppInfo, CapSecret, CellId, ClonedCell, DnaHash, DnaProperties, EntryHash, FunctionName, InstalledAppId, MembraneProof, MemproofMap, NetworkInfo, NetworkSeed, Nonce256Bit, RoleName, Timestamp, Transformer, WebsocketConnectionOptions, ZomeName } from "../../index.js";
|
|
2
|
+
import { AgentPubKey, AppAuthenticationToken, AppInfo, CapSecret, CellId, ClonedCell, DnaHash, DnaProperties, EntryHash, FunctionName, InstalledAppId, MembraneProof, MemproofMap, NetworkInfo, NetworkSeed, Nonce256Bit, RoleName, Timestamp, Transformer, WebsocketConnectionOptions, ZomeName, PreflightRequest, SignedAction, SignedActionHashed } from "../../index.js";
|
|
3
3
|
/**
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
@@ -19,7 +19,7 @@ export type RoleNameCallZomeRequestSigned = Omit<CallZomeRequestSigned, "cell_id
|
|
|
19
19
|
/**
|
|
20
20
|
* @public
|
|
21
21
|
*/
|
|
22
|
-
export type AppCallZomeRequest = NonProvenanceCallZomeRequest | RoleNameCallZomeRequest |
|
|
22
|
+
export type AppCallZomeRequest = NonProvenanceCallZomeRequest | RoleNameCallZomeRequest | CallZomeRequest;
|
|
23
23
|
/**
|
|
24
24
|
* @public
|
|
25
25
|
*/
|
|
@@ -45,7 +45,7 @@ export interface AppEvents {
|
|
|
45
45
|
/**
|
|
46
46
|
* @public
|
|
47
47
|
*/
|
|
48
|
-
export interface
|
|
48
|
+
export interface CallZomeRequestParams extends CallZomeRequest {
|
|
49
49
|
cap_secret: CapSecret | null;
|
|
50
50
|
nonce: Nonce256Bit;
|
|
51
51
|
expires_at: number;
|
|
@@ -53,7 +53,8 @@ export interface CallZomeRequestUnsigned extends CallZomeRequest {
|
|
|
53
53
|
/**
|
|
54
54
|
* @public
|
|
55
55
|
*/
|
|
56
|
-
export interface CallZomeRequestSigned
|
|
56
|
+
export interface CallZomeRequestSigned {
|
|
57
|
+
bytes: Uint8Array;
|
|
57
58
|
signature: Uint8Array;
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
@@ -183,6 +184,211 @@ export interface NetworkInfoRequest {
|
|
|
183
184
|
*/
|
|
184
185
|
last_time_queried?: number;
|
|
185
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Cell id for which the countersigning session state is requested.
|
|
189
|
+
*
|
|
190
|
+
* @public
|
|
191
|
+
*/
|
|
192
|
+
export type GetCountersigningSessionStateRequest = CellId;
|
|
193
|
+
/**
|
|
194
|
+
* @public
|
|
195
|
+
*/
|
|
196
|
+
export type GetCountersigningSessionStateResponse = null | CountersigningSessionState;
|
|
197
|
+
/**
|
|
198
|
+
* Cell id for which the countersigning session should be abandoned.
|
|
199
|
+
*
|
|
200
|
+
* @public
|
|
201
|
+
*/
|
|
202
|
+
export type AbandonCountersigningSessionStateRequest = CellId;
|
|
203
|
+
/**
|
|
204
|
+
* @public
|
|
205
|
+
*/
|
|
206
|
+
export type AbandonCountersigningSessionStateResponse = null;
|
|
207
|
+
/**
|
|
208
|
+
* Cell id for which the countersigning session should be published.
|
|
209
|
+
*
|
|
210
|
+
* @public
|
|
211
|
+
*/
|
|
212
|
+
export type PublishCountersigningSessionStateRequest = CellId;
|
|
213
|
+
/**
|
|
214
|
+
* @public
|
|
215
|
+
*/
|
|
216
|
+
export type PublishCountersigningSessionStateResponse = null;
|
|
217
|
+
/**
|
|
218
|
+
* @public
|
|
219
|
+
*/
|
|
220
|
+
export declare enum CountersigningSessionStateType {
|
|
221
|
+
Accepted = "Accepted",
|
|
222
|
+
SignaturesCollected = "SignaturesCollected",
|
|
223
|
+
Unknown = "Unknown"
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
export type CountersigningSessionState =
|
|
229
|
+
/**
|
|
230
|
+
* This is the entry state. Accepting a countersigning session through the HDK will immediately
|
|
231
|
+
* register the countersigning session in this state, for management by the countersigning workflow.
|
|
232
|
+
*
|
|
233
|
+
* The session will stay in this state even when the agent commits their countersigning entry and only
|
|
234
|
+
* move to the next state when the first signature bundle is received.
|
|
235
|
+
*/
|
|
236
|
+
{
|
|
237
|
+
[CountersigningSessionStateType.Accepted]: PreflightRequest;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* This is the state where we have collected one or more signatures for a countersigning session.
|
|
241
|
+
*
|
|
242
|
+
* This state can be entered from the [CountersigningSessionState::Accepted] state, which happens
|
|
243
|
+
* when a witness returns a signature bundle to us. While the session has not timed out, we will
|
|
244
|
+
* stay in this state and wait until one of the signatures bundles we have received is valid for
|
|
245
|
+
* the session to be completed.
|
|
246
|
+
*
|
|
247
|
+
* If we entered this state from the [CountersigningSessionState::Accepted] state, we will either
|
|
248
|
+
* complete the session successfully or the session will time out. On a timeout we will move
|
|
249
|
+
* to the [CountersigningSessionState::Unknown] for a limited number of attempts to recover the session.
|
|
250
|
+
*
|
|
251
|
+
* This state can also be entered from the [CountersigningSessionState::Unknown] state, which happens when we
|
|
252
|
+
* have been able to recover the session from the source chain and have requested signed actions
|
|
253
|
+
* from agent authorities to build a signature bundle.
|
|
254
|
+
*
|
|
255
|
+
* If we entered this state from the [CountersigningSessionState::Unknown] state, we will either
|
|
256
|
+
* complete the session successfully, or if the signatures are invalid, we will return to the
|
|
257
|
+
* [CountersigningSessionState::Unknown] state.
|
|
258
|
+
*/
|
|
259
|
+
| {
|
|
260
|
+
[CountersigningSessionStateType.SignaturesCollected]: {
|
|
261
|
+
/** The preflight request that has been exchanged among countersigning peers. */
|
|
262
|
+
preflight_request: PreflightRequest;
|
|
263
|
+
/** Signed actions of the committed countersigned entries of all participating peers. */
|
|
264
|
+
signature_bundles: SignedAction[][];
|
|
265
|
+
/**
|
|
266
|
+
* This field is set when the signature bundle came from querying agent activity authorities
|
|
267
|
+
* in the unknown state. If we started from that state, we should return to it if the
|
|
268
|
+
* signature bundle is invalid. Otherwise, stay in this state and wait for more signatures.
|
|
269
|
+
*/
|
|
270
|
+
resolution?: SessionResolutionSummary;
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The session is in an unknown state and needs to be resolved.
|
|
275
|
+
*
|
|
276
|
+
* This state is used when we have lost track of the countersigning session. This happens if
|
|
277
|
+
* we have got far enough to create the countersigning entry but have crashed or restarted
|
|
278
|
+
* before we could complete the session. In this case we need to try to discover what the other
|
|
279
|
+
* agent or agents involved in the session have done.
|
|
280
|
+
*
|
|
281
|
+
* This state is also entered temporarily when we have published a signature and then the
|
|
282
|
+
* session has timed out. To avoid deadlocking with two parties both waiting for each other to
|
|
283
|
+
* proceed, we cannot stay in this state indefinitely. We will make a limited number of attempts
|
|
284
|
+
* to recover and if we cannot, we will abandon the session.
|
|
285
|
+
*
|
|
286
|
+
* The only exception to the attempt limiting is if we are unable to reach agent activity authorities
|
|
287
|
+
* to progress resolving the session. In this case, the attempts are not counted towards the
|
|
288
|
+
* configured limit. This does not protect us against a network partition where we can only see
|
|
289
|
+
* a subset of the network, but it does protect us against Holochain forcing a decision while
|
|
290
|
+
* it is unable to reach any peers.
|
|
291
|
+
*
|
|
292
|
+
* Note that because the [PreflightRequest] is stored here, we only ever enter the unknown state
|
|
293
|
+
* if we managed to keep the preflight request in memory, or if we have been able to recover it
|
|
294
|
+
* from the source chain as part of the committed [CounterSigningSessionData]. Otherwise, we
|
|
295
|
+
* are unable to discover what session we were participating in, and we must abandon the session
|
|
296
|
+
* without going through this recovery state.
|
|
297
|
+
*/
|
|
298
|
+
| {
|
|
299
|
+
[CountersigningSessionStateType.Unknown]: {
|
|
300
|
+
/** The preflight request that has been exchanged. */
|
|
301
|
+
preflight_request: PreflightRequest;
|
|
302
|
+
/** Summary of the attempts to resolve this session. */
|
|
303
|
+
resolution: SessionResolutionSummary;
|
|
304
|
+
/** Flag if the session is programmed to be force-abandoned on the next countersigning workflow run. */
|
|
305
|
+
force_abandon: boolean;
|
|
306
|
+
/** Flag if the session is programmed to be force-published on the next countersigning workflow run. */
|
|
307
|
+
force_publish: boolean;
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* Summary of the workflow's attempts to resolve the outcome a failed countersigning session.
|
|
312
|
+
* This tracks the numbers of attempts and the outcome of the most recent attempt.
|
|
313
|
+
*
|
|
314
|
+
* @public
|
|
315
|
+
*/
|
|
316
|
+
export interface SessionResolutionSummary {
|
|
317
|
+
/** The reason why session resolution is required. */
|
|
318
|
+
required_reason: ResolutionRequiredReason;
|
|
319
|
+
/**
|
|
320
|
+
* How many attempts have been made to resolve the session.
|
|
321
|
+
*
|
|
322
|
+
* Attempts are made according to the frequency specified by [RETRY_UNKNOWN_SESSION_STATE_DELAY].
|
|
323
|
+
*
|
|
324
|
+
* This count is only correct for the current run of the Holochain conductor. If the conductor
|
|
325
|
+
* is restarted then this counter is also reset.
|
|
326
|
+
*/
|
|
327
|
+
attempts: number;
|
|
328
|
+
/** The time of the last attempt to resolve the session. */
|
|
329
|
+
last_attempt_at?: Timestamp;
|
|
330
|
+
/** The outcome of the most recent attempt to resolve the session. */
|
|
331
|
+
outcomes: SessionResolutionOutcome[];
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* The reason why a countersigning session can not be resolved automatically and requires manual resolution.
|
|
335
|
+
*
|
|
336
|
+
* @public
|
|
337
|
+
*/
|
|
338
|
+
export declare enum ResolutionRequiredReason {
|
|
339
|
+
/** The session has timed out, so we should try to resolve its state before abandoning. */
|
|
340
|
+
Timeout = "Timeout",
|
|
341
|
+
/** Something happened, like a conductor restart, and we lost track of the session. */
|
|
342
|
+
Unknown = "Unknown"
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* The outcome for a single agent who participated in a countersigning session.
|
|
346
|
+
*
|
|
347
|
+
* [NUM_AUTHORITIES_TO_QUERY] authorities are made to agent activity authorities for each agent,
|
|
348
|
+
* and the decisions are collected into [SessionResolutionOutcome::decisions].
|
|
349
|
+
*
|
|
350
|
+
* @public
|
|
351
|
+
*/
|
|
352
|
+
export interface SessionResolutionOutcome {
|
|
353
|
+
/**
|
|
354
|
+
* The agent who participated in the countersigning session and is the subject of this
|
|
355
|
+
* resolution outcome.
|
|
356
|
+
*/
|
|
357
|
+
agent: AgentPubKey;
|
|
358
|
+
/** The resolved decision for each authority for the subject agent. */
|
|
359
|
+
decisions: SessionCompletionDecision[];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Decision about an incomplete countersigning session.
|
|
363
|
+
*
|
|
364
|
+
* @public
|
|
365
|
+
*/
|
|
366
|
+
export declare enum SessionCompletionDecisionType {
|
|
367
|
+
/** Evidence found on the network that this session completed successfully. */
|
|
368
|
+
Complete = "Complete",
|
|
369
|
+
/**
|
|
370
|
+
* Evidence found on the network that this session was abandoned and other agents have
|
|
371
|
+
* added to their chain without completing the session.
|
|
372
|
+
*/
|
|
373
|
+
Abandoned = "Abandoned",
|
|
374
|
+
/**
|
|
375
|
+
* No evidence, or inconclusive evidence, was found on the network. Holochain will not make an
|
|
376
|
+
* automatic decision until the evidence is conclusive.
|
|
377
|
+
*/
|
|
378
|
+
Indeterminate = "Indeterminate",
|
|
379
|
+
/**There were errors encountered while trying to resolve the session. Errors such as network
|
|
380
|
+
* errors are treated differently to inconclusive evidence. We don't want to force a decision
|
|
381
|
+
* when we're offline, for example. In this case, the resolution must be retried later and this
|
|
382
|
+
* attempt should not be counted.
|
|
383
|
+
*/
|
|
384
|
+
Failed = "Failed"
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* @public
|
|
388
|
+
*/
|
|
389
|
+
export type SessionCompletionDecision = {
|
|
390
|
+
[SessionCompletionDecisionType.Complete]: SignedActionHashed;
|
|
391
|
+
} | SessionCompletionDecisionType.Abandoned | SessionCompletionDecisionType.Indeterminate | SessionCompletionDecisionType.Failed;
|
|
186
392
|
/**
|
|
187
393
|
* @public
|
|
188
394
|
*/
|
package/lib/api/app/types.js
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @public
|
|
3
|
+
*/
|
|
4
|
+
export var CountersigningSessionStateType;
|
|
5
|
+
(function (CountersigningSessionStateType) {
|
|
6
|
+
CountersigningSessionStateType["Accepted"] = "Accepted";
|
|
7
|
+
CountersigningSessionStateType["SignaturesCollected"] = "SignaturesCollected";
|
|
8
|
+
CountersigningSessionStateType["Unknown"] = "Unknown";
|
|
9
|
+
})(CountersigningSessionStateType || (CountersigningSessionStateType = {}));
|
|
10
|
+
/**
|
|
11
|
+
* The reason why a countersigning session can not be resolved automatically and requires manual resolution.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export var ResolutionRequiredReason;
|
|
16
|
+
(function (ResolutionRequiredReason) {
|
|
17
|
+
/** The session has timed out, so we should try to resolve its state before abandoning. */
|
|
18
|
+
ResolutionRequiredReason["Timeout"] = "Timeout";
|
|
19
|
+
/** Something happened, like a conductor restart, and we lost track of the session. */
|
|
20
|
+
ResolutionRequiredReason["Unknown"] = "Unknown";
|
|
21
|
+
})(ResolutionRequiredReason || (ResolutionRequiredReason = {}));
|
|
22
|
+
/**
|
|
23
|
+
* Decision about an incomplete countersigning session.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export var SessionCompletionDecisionType;
|
|
28
|
+
(function (SessionCompletionDecisionType) {
|
|
29
|
+
/** Evidence found on the network that this session completed successfully. */
|
|
30
|
+
SessionCompletionDecisionType["Complete"] = "Complete";
|
|
31
|
+
/**
|
|
32
|
+
* Evidence found on the network that this session was abandoned and other agents have
|
|
33
|
+
* added to their chain without completing the session.
|
|
34
|
+
*/
|
|
35
|
+
SessionCompletionDecisionType["Abandoned"] = "Abandoned";
|
|
36
|
+
/**
|
|
37
|
+
* No evidence, or inconclusive evidence, was found on the network. Holochain will not make an
|
|
38
|
+
* automatic decision until the evidence is conclusive.
|
|
39
|
+
*/
|
|
40
|
+
SessionCompletionDecisionType["Indeterminate"] = "Indeterminate";
|
|
41
|
+
/**There were errors encountered while trying to resolve the session. Errors such as network
|
|
42
|
+
* errors are treated differently to inconclusive evidence. We don't want to force a decision
|
|
43
|
+
* when we're offline, for example. In this case, the resolution must be retried later and this
|
|
44
|
+
* attempt should not be counted.
|
|
45
|
+
*/
|
|
46
|
+
SessionCompletionDecisionType["Failed"] = "Failed";
|
|
47
|
+
})(SessionCompletionDecisionType || (SessionCompletionDecisionType = {}));
|
|
1
48
|
/**
|
|
2
49
|
* @public
|
|
3
50
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UnsubscribeFunction } from "emittery";
|
|
2
2
|
import { AgentPubKey, CellId, InstalledAppId, RoleName } from "../../types.js";
|
|
3
3
|
import { AppInfo, MemproofMap } from "../admin/index.js";
|
|
4
|
-
import { AppCallZomeRequest, AppClient, AppEvents, AppNetworkInfoRequest, AppCreateCloneCellRequest, AppDisableCloneCellRequest, AppEnableCloneCellRequest, SignalCb, CallZomeRequest, CallZomeRequestSigned,
|
|
4
|
+
import { AppCallZomeRequest, AppClient, AppEvents, AppNetworkInfoRequest, AppCreateCloneCellRequest, AppDisableCloneCellRequest, AppEnableCloneCellRequest, SignalCb, CallZomeRequest, CallZomeRequestSigned, NetworkInfoResponse, AppWebsocketConnectionOptions, GetCountersigningSessionStateRequest, GetCountersigningSessionStateResponse, AbandonCountersigningSessionStateRequest, PublishCountersigningSessionStateRequest } from "./types.js";
|
|
5
5
|
import { WsClient } from "../client.js";
|
|
6
6
|
/**
|
|
7
7
|
* A class to establish a websocket connection to an App interface, for a
|
|
@@ -16,7 +16,6 @@ export declare class AppWebsocket implements AppClient {
|
|
|
16
16
|
private readonly defaultTimeout;
|
|
17
17
|
private readonly emitter;
|
|
18
18
|
private readonly callZomeTransform;
|
|
19
|
-
private readonly appAuthenticationToken;
|
|
20
19
|
cachedAppInfo?: AppInfo | null;
|
|
21
20
|
private readonly appInfoRequester;
|
|
22
21
|
private readonly callZomeRequester;
|
|
@@ -26,6 +25,9 @@ export declare class AppWebsocket implements AppClient {
|
|
|
26
25
|
private readonly enableCloneCellRequester;
|
|
27
26
|
private readonly disableCloneCellRequester;
|
|
28
27
|
private readonly networkInfoRequester;
|
|
28
|
+
private readonly getCountersigningSessionStateRequester;
|
|
29
|
+
private readonly abandonCountersigningSessionRequester;
|
|
30
|
+
private readonly publishCountersigningSessionRequester;
|
|
29
31
|
private constructor();
|
|
30
32
|
/**
|
|
31
33
|
* Instance factory for creating an {@link AppWebsocket}.
|
|
@@ -68,33 +70,111 @@ export declare class AppWebsocket implements AppClient {
|
|
|
68
70
|
* @param timeout - A timeout to override the default.
|
|
69
71
|
* @returns The zome call's response.
|
|
70
72
|
*/
|
|
71
|
-
callZome(request: AppCallZomeRequest, timeout?: number): Promise<
|
|
73
|
+
callZome<ReturnType>(request: AppCallZomeRequest, timeout?: number): Promise<ReturnType>;
|
|
72
74
|
/**
|
|
73
75
|
* Clone an existing provisioned cell.
|
|
74
76
|
*
|
|
75
77
|
* @param args - Specify the cell to clone.
|
|
76
78
|
* @returns The created clone cell.
|
|
77
79
|
*/
|
|
78
|
-
createCloneCell(args: AppCreateCloneCellRequest): Promise<
|
|
80
|
+
createCloneCell(args: AppCreateCloneCellRequest): Promise<import("../admin/types.js").ClonedCell>;
|
|
79
81
|
/**
|
|
80
82
|
* Enable a disabled clone cell.
|
|
81
83
|
*
|
|
82
84
|
* @param args - Specify the clone cell to enable.
|
|
83
85
|
* @returns The enabled clone cell.
|
|
84
86
|
*/
|
|
85
|
-
enableCloneCell(args: AppEnableCloneCellRequest): Promise<
|
|
87
|
+
enableCloneCell(args: AppEnableCloneCellRequest): Promise<import("../admin/types.js").ClonedCell>;
|
|
86
88
|
/**
|
|
87
89
|
* Disable an enabled clone cell.
|
|
88
90
|
*
|
|
89
91
|
* @param args - Specify the clone cell to disable.
|
|
90
92
|
*/
|
|
91
|
-
disableCloneCell(args: AppDisableCloneCellRequest): Promise<
|
|
93
|
+
disableCloneCell(args: AppDisableCloneCellRequest): Promise<void>;
|
|
92
94
|
/**
|
|
93
95
|
* Request network info about gossip status.
|
|
94
96
|
* @param args - Specify the DNAs for which you want network info
|
|
95
97
|
* @returns Network info for the specified DNAs
|
|
96
98
|
*/
|
|
97
99
|
networkInfo(args: AppNetworkInfoRequest): Promise<NetworkInfoResponse>;
|
|
100
|
+
/**
|
|
101
|
+
* Get the state of a countersigning session.
|
|
102
|
+
*/
|
|
103
|
+
getCountersigningSessionState(args: GetCountersigningSessionStateRequest): Promise<GetCountersigningSessionStateResponse>;
|
|
104
|
+
/**
|
|
105
|
+
* Abandon an unresolved countersigning session.
|
|
106
|
+
*
|
|
107
|
+
* If the current session has not been resolved automatically, it can be forcefully abandoned.
|
|
108
|
+
* A condition for this call to succeed is that at least one attempt has been made to resolve
|
|
109
|
+
* it automatically.
|
|
110
|
+
*
|
|
111
|
+
* # Returns
|
|
112
|
+
*
|
|
113
|
+
* [`AppResponse::CountersigningSessionAbandoned`]
|
|
114
|
+
*
|
|
115
|
+
* The session is marked for abandoning and the countersigning workflow was triggered. The session
|
|
116
|
+
* has not been abandoned yet.
|
|
117
|
+
*
|
|
118
|
+
* Upon successful abandoning the system signal [`SystemSignal::AbandonedCountersigning`] will
|
|
119
|
+
* be emitted and the session removed from state, so that [`AppRequest::GetCountersigningSessionState`]
|
|
120
|
+
* would return `None`.
|
|
121
|
+
*
|
|
122
|
+
* In the countersigning workflow it will first be attempted to resolve the session with incoming
|
|
123
|
+
* signatures of the countersigned entries, before force-abandoning the session. In a very rare event
|
|
124
|
+
* it could happen that in just the moment where the [`AppRequest::AbandonCountersigningSession`]
|
|
125
|
+
* is made, signatures for this session come in. If they are valid, the session will be resolved and
|
|
126
|
+
* published as usual. Should they be invalid, however, the flag to abandon the session is erased.
|
|
127
|
+
* In such cases this request can be retried until the session has been abandoned successfully.
|
|
128
|
+
*
|
|
129
|
+
* # Errors
|
|
130
|
+
*
|
|
131
|
+
* [`CountersigningError::WorkspaceDoesNotExist`] likely indicates that an invalid cell id was
|
|
132
|
+
* passed in to the call.
|
|
133
|
+
*
|
|
134
|
+
* [`CountersigningError::SessionNotFound`] when no ongoing session could be found for the provided
|
|
135
|
+
* cell id.
|
|
136
|
+
*
|
|
137
|
+
* [`CountersigningError::SessionNotUnresolved`] when an attempt to resolve the session
|
|
138
|
+
* automatically has not been made.
|
|
139
|
+
*/
|
|
140
|
+
abandonCountersigningSession(args: AbandonCountersigningSessionStateRequest): Promise<null>;
|
|
141
|
+
/**
|
|
142
|
+
* Publish an unresolved countersigning session.
|
|
143
|
+
*
|
|
144
|
+
* If the current session has not been resolved automatically, it can be forcefully published.
|
|
145
|
+
* A condition for this call to succeed is that at least one attempt has been made to resolve
|
|
146
|
+
* it automatically.
|
|
147
|
+
*
|
|
148
|
+
* # Returns
|
|
149
|
+
*
|
|
150
|
+
* [`AppResponse::PublishCountersigningSessionTriggered`]
|
|
151
|
+
*
|
|
152
|
+
* The session is marked for publishing and the countersigning workflow was triggered. The session
|
|
153
|
+
* has not been published yet.
|
|
154
|
+
*
|
|
155
|
+
* Upon successful publishing the system signal [`SystemSignal::SuccessfulCountersigning`] will
|
|
156
|
+
* be emitted and the session removed from state, so that [`AppRequest::GetCountersigningSessionState`]
|
|
157
|
+
* would return `None`.
|
|
158
|
+
*
|
|
159
|
+
* In the countersigning workflow it will first be attempted to resolve the session with incoming
|
|
160
|
+
* signatures of the countersigned entries, before force-publishing the session. In a very rare event
|
|
161
|
+
* it could happen that in just the moment where the [`AppRequest::PublishCountersigningSession`]
|
|
162
|
+
* is made, signatures for this session come in. If they are valid, the session will be resolved and
|
|
163
|
+
* published as usual. Should they be invalid, however, the flag to publish the session is erased.
|
|
164
|
+
* In such cases this request can be retried until the session has been published successfully.
|
|
165
|
+
*
|
|
166
|
+
* # Errors
|
|
167
|
+
*
|
|
168
|
+
* [`CountersigningError::WorkspaceDoesNotExist`] likely indicates that an invalid cell id was
|
|
169
|
+
* passed in to the call.
|
|
170
|
+
*
|
|
171
|
+
* [`CountersigningError::SessionNotFound`] when no ongoing session could be found for the provided
|
|
172
|
+
* cell id.
|
|
173
|
+
*
|
|
174
|
+
* [`CountersigningError::SessionNotUnresolved`] when an attempt to resolve the session
|
|
175
|
+
* automatically has not been made.
|
|
176
|
+
*/
|
|
177
|
+
publishCountersigningSession(args: PublishCountersigningSessionStateRequest): Promise<null>;
|
|
98
178
|
/**
|
|
99
179
|
* Register an event listener for signals.
|
|
100
180
|
*
|
package/lib/api/app/websocket.js
CHANGED
|
@@ -6,9 +6,9 @@ import { getHostZomeCallSigner, getLauncherEnvironment, } from "../../environmen
|
|
|
6
6
|
import { decode, encode } from "@msgpack/msgpack";
|
|
7
7
|
import { getNonceExpiration, getSigningCredentials, randomNonce, } from "../zome-call-signing.js";
|
|
8
8
|
import { encodeHashToBase64 } from "../../utils/index.js";
|
|
9
|
-
import { hashZomeCall } from "@holochain/serialization";
|
|
10
9
|
import _sodium from "libsodium-wrappers";
|
|
11
10
|
import { WsClient } from "../client.js";
|
|
11
|
+
import { sha512 } from "js-sha512";
|
|
12
12
|
/**
|
|
13
13
|
* A class to establish a websocket connection to an App interface, for a
|
|
14
14
|
* specific agent and app.
|
|
@@ -22,7 +22,6 @@ export class AppWebsocket {
|
|
|
22
22
|
defaultTimeout;
|
|
23
23
|
emitter;
|
|
24
24
|
callZomeTransform;
|
|
25
|
-
appAuthenticationToken;
|
|
26
25
|
cachedAppInfo;
|
|
27
26
|
appInfoRequester;
|
|
28
27
|
callZomeRequester;
|
|
@@ -32,13 +31,15 @@ export class AppWebsocket {
|
|
|
32
31
|
enableCloneCellRequester;
|
|
33
32
|
disableCloneCellRequester;
|
|
34
33
|
networkInfoRequester;
|
|
35
|
-
|
|
34
|
+
getCountersigningSessionStateRequester;
|
|
35
|
+
abandonCountersigningSessionRequester;
|
|
36
|
+
publishCountersigningSessionRequester;
|
|
37
|
+
constructor(client, appInfo, callZomeTransform, defaultTimeout) {
|
|
36
38
|
this.client = client;
|
|
37
39
|
this.myPubKey = appInfo.agent_pub_key;
|
|
38
40
|
this.installedAppId = appInfo.installed_app_id;
|
|
39
41
|
this.defaultTimeout = defaultTimeout ?? DEFAULT_TIMEOUT;
|
|
40
42
|
this.callZomeTransform = callZomeTransform ?? defaultCallZomeTransform;
|
|
41
|
-
this.appAuthenticationToken = token;
|
|
42
43
|
this.emitter = new Emittery();
|
|
43
44
|
this.cachedAppInfo = appInfo;
|
|
44
45
|
this.appInfoRequester = AppWebsocket.requester(this.client, "app_info", this.defaultTimeout);
|
|
@@ -49,6 +50,9 @@ export class AppWebsocket {
|
|
|
49
50
|
this.enableCloneCellRequester = AppWebsocket.requester(this.client, "enable_clone_cell", this.defaultTimeout);
|
|
50
51
|
this.disableCloneCellRequester = AppWebsocket.requester(this.client, "disable_clone_cell", this.defaultTimeout);
|
|
51
52
|
this.networkInfoRequester = AppWebsocket.requester(this.client, "network_info", this.defaultTimeout);
|
|
53
|
+
this.getCountersigningSessionStateRequester = AppWebsocket.requester(this.client, "get_countersigning_session_state", this.defaultTimeout);
|
|
54
|
+
this.abandonCountersigningSessionRequester = AppWebsocket.requester(this.client, "abandon_countersigning_session", this.defaultTimeout);
|
|
55
|
+
this.publishCountersigningSessionRequester = AppWebsocket.requester(this.client, "publish_countersigning_session", this.defaultTimeout);
|
|
52
56
|
// Ensure all super methods are bound to this instance because Emittery relies on `this` being the instance.
|
|
53
57
|
// Please retain until the upstream is fixed https://github.com/sindresorhus/emittery/issues/86.
|
|
54
58
|
Object.getOwnPropertyNames(Emittery.prototype).forEach((name) => {
|
|
@@ -87,7 +91,7 @@ export class AppWebsocket {
|
|
|
87
91
|
if (!appInfo) {
|
|
88
92
|
throw new HolochainError("AppNotFound", `The app your connection token was issued for was not found. The app needs to be installed and enabled.`);
|
|
89
93
|
}
|
|
90
|
-
return new AppWebsocket(client, appInfo,
|
|
94
|
+
return new AppWebsocket(client, appInfo, options.callZomeTransform, options.defaultTimeout);
|
|
91
95
|
}
|
|
92
96
|
/**
|
|
93
97
|
* Request the app's info, including all cell infos.
|
|
@@ -220,6 +224,90 @@ export class AppWebsocket {
|
|
|
220
224
|
agent_pub_key: this.myPubKey,
|
|
221
225
|
});
|
|
222
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the state of a countersigning session.
|
|
229
|
+
*/
|
|
230
|
+
async getCountersigningSessionState(args) {
|
|
231
|
+
return this.getCountersigningSessionStateRequester(args);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Abandon an unresolved countersigning session.
|
|
235
|
+
*
|
|
236
|
+
* If the current session has not been resolved automatically, it can be forcefully abandoned.
|
|
237
|
+
* A condition for this call to succeed is that at least one attempt has been made to resolve
|
|
238
|
+
* it automatically.
|
|
239
|
+
*
|
|
240
|
+
* # Returns
|
|
241
|
+
*
|
|
242
|
+
* [`AppResponse::CountersigningSessionAbandoned`]
|
|
243
|
+
*
|
|
244
|
+
* The session is marked for abandoning and the countersigning workflow was triggered. The session
|
|
245
|
+
* has not been abandoned yet.
|
|
246
|
+
*
|
|
247
|
+
* Upon successful abandoning the system signal [`SystemSignal::AbandonedCountersigning`] will
|
|
248
|
+
* be emitted and the session removed from state, so that [`AppRequest::GetCountersigningSessionState`]
|
|
249
|
+
* would return `None`.
|
|
250
|
+
*
|
|
251
|
+
* In the countersigning workflow it will first be attempted to resolve the session with incoming
|
|
252
|
+
* signatures of the countersigned entries, before force-abandoning the session. In a very rare event
|
|
253
|
+
* it could happen that in just the moment where the [`AppRequest::AbandonCountersigningSession`]
|
|
254
|
+
* is made, signatures for this session come in. If they are valid, the session will be resolved and
|
|
255
|
+
* published as usual. Should they be invalid, however, the flag to abandon the session is erased.
|
|
256
|
+
* In such cases this request can be retried until the session has been abandoned successfully.
|
|
257
|
+
*
|
|
258
|
+
* # Errors
|
|
259
|
+
*
|
|
260
|
+
* [`CountersigningError::WorkspaceDoesNotExist`] likely indicates that an invalid cell id was
|
|
261
|
+
* passed in to the call.
|
|
262
|
+
*
|
|
263
|
+
* [`CountersigningError::SessionNotFound`] when no ongoing session could be found for the provided
|
|
264
|
+
* cell id.
|
|
265
|
+
*
|
|
266
|
+
* [`CountersigningError::SessionNotUnresolved`] when an attempt to resolve the session
|
|
267
|
+
* automatically has not been made.
|
|
268
|
+
*/
|
|
269
|
+
async abandonCountersigningSession(args) {
|
|
270
|
+
return this.abandonCountersigningSessionRequester(args);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Publish an unresolved countersigning session.
|
|
274
|
+
*
|
|
275
|
+
* If the current session has not been resolved automatically, it can be forcefully published.
|
|
276
|
+
* A condition for this call to succeed is that at least one attempt has been made to resolve
|
|
277
|
+
* it automatically.
|
|
278
|
+
*
|
|
279
|
+
* # Returns
|
|
280
|
+
*
|
|
281
|
+
* [`AppResponse::PublishCountersigningSessionTriggered`]
|
|
282
|
+
*
|
|
283
|
+
* The session is marked for publishing and the countersigning workflow was triggered. The session
|
|
284
|
+
* has not been published yet.
|
|
285
|
+
*
|
|
286
|
+
* Upon successful publishing the system signal [`SystemSignal::SuccessfulCountersigning`] will
|
|
287
|
+
* be emitted and the session removed from state, so that [`AppRequest::GetCountersigningSessionState`]
|
|
288
|
+
* would return `None`.
|
|
289
|
+
*
|
|
290
|
+
* In the countersigning workflow it will first be attempted to resolve the session with incoming
|
|
291
|
+
* signatures of the countersigned entries, before force-publishing the session. In a very rare event
|
|
292
|
+
* it could happen that in just the moment where the [`AppRequest::PublishCountersigningSession`]
|
|
293
|
+
* is made, signatures for this session come in. If they are valid, the session will be resolved and
|
|
294
|
+
* published as usual. Should they be invalid, however, the flag to publish the session is erased.
|
|
295
|
+
* In such cases this request can be retried until the session has been published successfully.
|
|
296
|
+
*
|
|
297
|
+
* # Errors
|
|
298
|
+
*
|
|
299
|
+
* [`CountersigningError::WorkspaceDoesNotExist`] likely indicates that an invalid cell id was
|
|
300
|
+
* passed in to the call.
|
|
301
|
+
*
|
|
302
|
+
* [`CountersigningError::SessionNotFound`] when no ongoing session could be found for the provided
|
|
303
|
+
* cell id.
|
|
304
|
+
*
|
|
305
|
+
* [`CountersigningError::SessionNotUnresolved`] when an attempt to resolve the session
|
|
306
|
+
* automatically has not been made.
|
|
307
|
+
*/
|
|
308
|
+
async publishCountersigningSession(args) {
|
|
309
|
+
return this.publishCountersigningSessionRequester(args);
|
|
310
|
+
}
|
|
223
311
|
/**
|
|
224
312
|
* Register an event listener for signals.
|
|
225
313
|
*
|
|
@@ -249,8 +337,6 @@ const defaultCallZomeTransform = {
|
|
|
249
337
|
},
|
|
250
338
|
output: (response) => decode(response),
|
|
251
339
|
};
|
|
252
|
-
const isSameCell = (cellId1, cellId2) => cellId1[0].every((byte, index) => byte === cellId2[0][index]) &&
|
|
253
|
-
cellId1[1].every((byte, index) => byte === cellId2[1][index]);
|
|
254
340
|
/**
|
|
255
341
|
* @public
|
|
256
342
|
*/
|
|
@@ -269,14 +355,15 @@ export const signZomeCall = async (request) => {
|
|
|
269
355
|
nonce: await randomNonce(),
|
|
270
356
|
expires_at: getNonceExpiration(),
|
|
271
357
|
};
|
|
272
|
-
const
|
|
358
|
+
const bytes = encode(unsignedZomeCallPayload);
|
|
359
|
+
const bytesHash = new Uint8Array(sha512.array(bytes));
|
|
273
360
|
await _sodium.ready;
|
|
274
361
|
const sodium = _sodium;
|
|
275
362
|
const signature = sodium
|
|
276
|
-
.crypto_sign(
|
|
363
|
+
.crypto_sign(bytesHash, signingCredentialsForCell.keyPair.privateKey)
|
|
277
364
|
.subarray(0, sodium.crypto_sign_BYTES);
|
|
278
365
|
const signedZomeCall = {
|
|
279
|
-
|
|
366
|
+
bytes,
|
|
280
367
|
signature,
|
|
281
368
|
};
|
|
282
369
|
return signedZomeCall;
|
package/lib/api/index.d.ts
CHANGED
package/lib/api/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppAuthenticationToken, CallZomeRequest } from "../api/index.js";
|
|
2
|
-
import { CallZomeRequestSigned,
|
|
2
|
+
import { CallZomeRequestSigned, CallZomeRequestParams } from "../api/index.js";
|
|
3
3
|
import { InstalledAppId } from "../types.js";
|
|
4
4
|
export interface LauncherEnvironment {
|
|
5
5
|
APP_INTERFACE_PORT?: number;
|
|
@@ -32,7 +32,7 @@ interface CallZomeRequestSignedElectron extends Omit<CallZomeRequestSigned, "cap
|
|
|
32
32
|
nonce: Array<number>;
|
|
33
33
|
expiresAt: number;
|
|
34
34
|
}
|
|
35
|
-
interface CallZomeRequestUnsignedElectron extends Omit<
|
|
35
|
+
interface CallZomeRequestUnsignedElectron extends Omit<CallZomeRequestParams, "cap_secret" | "cell_id" | "provenance" | "nonce" | "zome_name" | "fn_name" | "expires_at"> {
|
|
36
36
|
cellId: [Array<number>, Array<number>];
|
|
37
37
|
provenance: Array<number>;
|
|
38
38
|
zomeName: string;
|
package/lib/hdk/action.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { AgentPubKey, DnaHash, EntryHash, ActionHash, HoloHashed, Signature, Timestamp } from "../types.js";
|
|
2
2
|
import { Entry, EntryType } from "./entry.js";
|
|
3
3
|
import { LinkTag, LinkType, RateWeight } from "./link.js";
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface SignedAction {
|
|
8
|
+
data: Action;
|
|
9
|
+
signature: Signature;
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* @public
|
|
6
13
|
*/
|
package/lib/tsdoc-metadata.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holochain/client",
|
|
3
|
-
"version": "0.19.0-dev.
|
|
3
|
+
"version": "0.19.0-dev.3",
|
|
4
4
|
"description": "A JavaScript client for the Holochain Conductor API",
|
|
5
5
|
"author": "Holochain Foundation <info@holochain.org> (https://holochain.org)",
|
|
6
6
|
"license": "CAL-1.0",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@bitgo/blake2b": "^3.2.4",
|
|
46
|
-
"@holochain/serialization": "^0.1.0-beta-rc.3",
|
|
47
46
|
"@msgpack/msgpack": "^2.8.0",
|
|
48
47
|
"emittery": "^1.0.1",
|
|
49
48
|
"isomorphic-ws": "^5.0.0",
|
|
50
49
|
"js-base64": "^3.7.5",
|
|
50
|
+
"js-sha512": "^0.9.0",
|
|
51
51
|
"libsodium-wrappers": "^0.7.13",
|
|
52
52
|
"lodash-es": "^4.17.21",
|
|
53
53
|
"ws": "^8.14.2"
|
|
@@ -72,4 +72,4 @@
|
|
|
72
72
|
"tsx": "^4.7.2",
|
|
73
73
|
"typescript": "^4.9.5"
|
|
74
74
|
}
|
|
75
|
-
}
|
|
75
|
+
}
|