@did-btcr2/method 0.36.0 → 0.37.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/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +1371 -260
- package/dist/browser.mjs +1371 -260
- package/dist/cjs/index.js +1464 -343
- package/dist/esm/core/aggregation/beacon-strategy.js +19 -6
- package/dist/esm/core/aggregation/beacon-strategy.js.map +1 -1
- package/dist/esm/core/aggregation/cohort.js +142 -33
- package/dist/esm/core/aggregation/cohort.js.map +1 -1
- package/dist/esm/core/aggregation/conditions.js +27 -0
- package/dist/esm/core/aggregation/conditions.js.map +1 -1
- package/dist/esm/core/aggregation/fallback-spend.js +132 -0
- package/dist/esm/core/aggregation/fallback-spend.js.map +1 -0
- package/dist/esm/core/aggregation/messages/base.js.map +1 -1
- package/dist/esm/core/aggregation/messages/bodies.js +46 -1
- package/dist/esm/core/aggregation/messages/bodies.js.map +1 -1
- package/dist/esm/core/aggregation/messages/constants.js +11 -0
- package/dist/esm/core/aggregation/messages/constants.js.map +1 -1
- package/dist/esm/core/aggregation/messages/factories.js +27 -1
- package/dist/esm/core/aggregation/messages/factories.js.map +1 -1
- package/dist/esm/core/aggregation/messages/guards.js +4 -1
- package/dist/esm/core/aggregation/messages/guards.js.map +1 -1
- package/dist/esm/core/aggregation/participant.js +218 -18
- package/dist/esm/core/aggregation/participant.js.map +1 -1
- package/dist/esm/core/aggregation/phases.js +6 -0
- package/dist/esm/core/aggregation/phases.js.map +1 -1
- package/dist/esm/core/aggregation/recovery-policy.js +156 -0
- package/dist/esm/core/aggregation/recovery-policy.js.map +1 -0
- package/dist/esm/core/aggregation/recovery-spend.js +106 -0
- package/dist/esm/core/aggregation/recovery-spend.js.map +1 -0
- package/dist/esm/core/aggregation/runner/aggregation-runner.js +11 -3
- package/dist/esm/core/aggregation/runner/aggregation-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js +106 -19
- package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/service-runner.js +409 -195
- package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
- package/dist/esm/core/aggregation/service.js +221 -11
- package/dist/esm/core/aggregation/service.js.map +1 -1
- package/dist/esm/core/aggregation/signing-session.js +3 -3
- package/dist/esm/core/aggregation/signing-session.js.map +1 -1
- package/dist/esm/core/aggregation/transport/http/envelope.js +3 -3
- package/dist/esm/core/aggregation/transport/http/inbox-buffer.js +1 -1
- package/dist/esm/core/aggregation/transport/http/nonce-cache.js +1 -1
- package/dist/esm/core/aggregation/transport/http/rate-limiter.js +1 -1
- package/dist/esm/core/aggregation/transport/http/request-auth.js +1 -1
- package/dist/esm/core/aggregation/transport/http/server.js +1 -1
- package/dist/esm/core/aggregation/transport/http/sse-stream.js +1 -1
- package/dist/esm/core/aggregation/transport/http/sse-writer.js +1 -1
- package/dist/esm/core/aggregation/transport/in-memory.js +1 -1
- package/dist/esm/core/aggregation/transport/nostr.js +6 -6
- package/dist/esm/core/beacon/beacon.js +15 -10
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +6 -6
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/singleton-beacon.js +2 -2
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +3 -3
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/esm/core/resolver.js +8 -8
- package/dist/esm/core/resolver.js.map +1 -1
- package/dist/esm/core/updater.js +6 -6
- package/dist/esm/core/updater.js.map +1 -1
- package/dist/esm/did-btcr2.js +2 -2
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/aggregation/beacon-strategy.d.ts +8 -4
- package/dist/types/core/aggregation/beacon-strategy.d.ts.map +1 -1
- package/dist/types/core/aggregation/cohort.d.ts +88 -17
- package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
- package/dist/types/core/aggregation/conditions.d.ts +28 -0
- package/dist/types/core/aggregation/conditions.d.ts.map +1 -1
- package/dist/types/core/aggregation/fallback-spend.d.ts +94 -0
- package/dist/types/core/aggregation/fallback-spend.d.ts.map +1 -0
- package/dist/types/core/aggregation/logger.d.ts +1 -1
- package/dist/types/core/aggregation/messages/base.d.ts +6 -0
- package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/bodies.d.ts +50 -2
- package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/constants.d.ts +8 -0
- package/dist/types/core/aggregation/messages/constants.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/factories.d.ts +40 -0
- package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/guards.d.ts.map +1 -1
- package/dist/types/core/aggregation/participant.d.ts +47 -4
- package/dist/types/core/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/aggregation/phases.d.ts +8 -2
- package/dist/types/core/aggregation/phases.d.ts.map +1 -1
- package/dist/types/core/aggregation/recovery-policy.d.ts +132 -0
- package/dist/types/core/aggregation/recovery-policy.d.ts.map +1 -0
- package/dist/types/core/aggregation/recovery-spend.d.ts +94 -0
- package/dist/types/core/aggregation/recovery-spend.d.ts.map +1 -0
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts +13 -3
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/events.d.ts +48 -16
- package/dist/types/core/aggregation/runner/events.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/participant-runner.d.ts +23 -14
- package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/service-runner.d.ts +102 -23
- package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/service.d.ts +26 -2
- package/dist/types/core/aggregation/service.d.ts.map +1 -1
- package/dist/types/core/aggregation/signing-session.d.ts +2 -2
- package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/http/envelope.d.ts +3 -3
- package/dist/types/core/aggregation/transport/http/inbox-buffer.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/nonce-cache.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/rate-limiter.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/request-auth.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/server.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/sse-stream.d.ts +2 -2
- package/dist/types/core/aggregation/transport/http/sse-writer.d.ts +1 -1
- package/dist/types/core/aggregation/transport/in-memory.d.ts +1 -1
- package/dist/types/core/aggregation/transport/nostr.d.ts +4 -4
- package/dist/types/core/aggregation/transport/transport.d.ts +4 -4
- package/dist/types/core/aggregation/transport/transport.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +7 -7
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +2 -2
- package/dist/types/core/beacon/interfaces.d.ts +1 -1
- package/dist/types/core/resolver.d.ts +3 -3
- package/dist/types/core/updater.d.ts +4 -4
- package/dist/types/did-btcr2.d.ts +2 -2
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/aggregation/beacon-strategy.ts +27 -9
- package/src/core/aggregation/cohort.ts +171 -35
- package/src/core/aggregation/conditions.ts +56 -0
- package/src/core/aggregation/fallback-spend.ts +223 -0
- package/src/core/aggregation/logger.ts +1 -1
- package/src/core/aggregation/messages/base.ts +6 -0
- package/src/core/aggregation/messages/bodies.ts +94 -1
- package/src/core/aggregation/messages/constants.ts +12 -0
- package/src/core/aggregation/messages/factories.ts +57 -0
- package/src/core/aggregation/messages/guards.ts +6 -0
- package/src/core/aggregation/participant.ts +264 -20
- package/src/core/aggregation/phases.ts +9 -0
- package/src/core/aggregation/recovery-policy.ts +237 -0
- package/src/core/aggregation/recovery-spend.ts +192 -0
- package/src/core/aggregation/runner/aggregation-runner.ts +27 -5
- package/src/core/aggregation/runner/events.ts +47 -19
- package/src/core/aggregation/runner/participant-runner.ts +113 -31
- package/src/core/aggregation/runner/service-runner.ts +484 -203
- package/src/core/aggregation/service.ts +260 -14
- package/src/core/aggregation/signing-session.ts +3 -3
- package/src/core/aggregation/transport/http/envelope.ts +3 -3
- package/src/core/aggregation/transport/http/inbox-buffer.ts +1 -1
- package/src/core/aggregation/transport/http/nonce-cache.ts +1 -1
- package/src/core/aggregation/transport/http/rate-limiter.ts +1 -1
- package/src/core/aggregation/transport/http/request-auth.ts +1 -1
- package/src/core/aggregation/transport/http/server.ts +1 -1
- package/src/core/aggregation/transport/http/sse-stream.ts +2 -2
- package/src/core/aggregation/transport/http/sse-writer.ts +1 -1
- package/src/core/aggregation/transport/in-memory.ts +1 -1
- package/src/core/aggregation/transport/nostr.ts +6 -6
- package/src/core/aggregation/transport/transport.ts +4 -4
- package/src/core/beacon/beacon.ts +16 -11
- package/src/core/beacon/cas-beacon.ts +7 -7
- package/src/core/beacon/interfaces.ts +1 -1
- package/src/core/beacon/singleton-beacon.ts +2 -2
- package/src/core/beacon/smt-beacon.ts +3 -3
- package/src/core/resolver.ts +8 -8
- package/src/core/updater.ts +6 -6
- package/src/did-btcr2.ts +2 -2
- package/src/index.ts +3 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
2
2
|
import type { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
|
-
import type { SerializedSMTProof } from '@did-btcr2/smt';
|
|
4
3
|
import type { BaseMessage } from '../messages/base.js';
|
|
5
4
|
import {
|
|
6
5
|
AGGREGATED_NONCE,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
COHORT_OPT_IN_ACCEPT,
|
|
10
9
|
COHORT_READY,
|
|
11
10
|
DISTRIBUTE_AGGREGATED_DATA,
|
|
11
|
+
FALLBACK_AUTHORIZATION_REQUEST,
|
|
12
12
|
} from '../messages/constants.js';
|
|
13
13
|
import type {
|
|
14
14
|
CohortAdvert,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { ParticipantCohortPhase } from '../phases.js';
|
|
21
21
|
import { KeyPairAggregationSigner } from '../signer.js';
|
|
22
22
|
import type { Transport } from '../transport/transport.js';
|
|
23
|
-
import type { AggregationParticipantEvents } from './events.js';
|
|
23
|
+
import type { AggregationParticipantEvents, CohortCompleteInfo } from './events.js';
|
|
24
24
|
import { TypedEventEmitter } from './typed-emitter.js';
|
|
25
25
|
|
|
26
26
|
/** Decision callback: filter discovered cohorts. Default rejects all. */
|
|
@@ -30,7 +30,7 @@ export type ShouldJoin = (advert: CohortAdvert) => Promise<boolean>;
|
|
|
30
30
|
export type OnProvideUpdate = (info: {
|
|
31
31
|
cohortId: string;
|
|
32
32
|
beaconAddress: string;
|
|
33
|
-
}) => Promise<SignedBTCR2Update>;
|
|
33
|
+
}) => Promise<SignedBTCR2Update | null>;
|
|
34
34
|
|
|
35
35
|
/** Decision callback: approve or reject aggregated data. */
|
|
36
36
|
export type OnValidateData = (info: PendingValidation) => Promise<{ approved: boolean }>;
|
|
@@ -54,7 +54,7 @@ export interface AggregationParticipantRunnerOptions {
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Provide a signed BTCR2 update for the cohort.
|
|
57
|
-
* REQUIRED
|
|
57
|
+
* REQUIRED - no sensible default.
|
|
58
58
|
*/
|
|
59
59
|
onProvideUpdate: OnProvideUpdate;
|
|
60
60
|
|
|
@@ -162,6 +162,7 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
162
162
|
DISTRIBUTE_AGGREGATED_DATA,
|
|
163
163
|
AUTHORIZATION_REQUEST,
|
|
164
164
|
AGGREGATED_NONCE,
|
|
165
|
+
FALLBACK_AUTHORIZATION_REQUEST,
|
|
165
166
|
];
|
|
166
167
|
|
|
167
168
|
/** Internal: detach from the transport. Safe to call repeatedly. */
|
|
@@ -175,19 +176,12 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
175
176
|
|
|
176
177
|
/**
|
|
177
178
|
* Single-shot helper: start, join the first cohort that passes `shouldJoin`,
|
|
178
|
-
* drive it to completion, and resolve. Convenient for tests and demos.
|
|
179
|
+
* drive it to completion, and resolve. Convenient for tests and demos. The
|
|
180
|
+
* single-cohort special case of {@link joinMatching} (count = 1).
|
|
179
181
|
*/
|
|
180
182
|
static async joinFirst(
|
|
181
183
|
options: AggregationParticipantRunnerOptions
|
|
182
|
-
): Promise<{
|
|
183
|
-
cohortId: string;
|
|
184
|
-
beaconAddress: string;
|
|
185
|
-
beaconType: string;
|
|
186
|
-
/** DID → base64url update hash. Populated only for CAS beacons. */
|
|
187
|
-
casAnnouncement?: Record<string, string>;
|
|
188
|
-
/** Merkle inclusion proof for this participant's slot. Populated only for SMT beacons. */
|
|
189
|
-
smtProof?: SerializedSMTProof;
|
|
190
|
-
}> {
|
|
184
|
+
): Promise<CohortCompleteInfo> {
|
|
191
185
|
return new Promise((resolve, reject) => {
|
|
192
186
|
const runner = new AggregationParticipantRunner(options);
|
|
193
187
|
runner.once('cohort-complete', (info) => {
|
|
@@ -199,6 +193,41 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
199
193
|
});
|
|
200
194
|
}
|
|
201
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Multi-cohort helper: start, join EVERY cohort whose advert passes
|
|
198
|
+
* `shouldJoin`, drive each to completion in parallel, and resolve once
|
|
199
|
+
* `count` cohorts have completed (the runner stops at that point). The
|
|
200
|
+
* N-cohort generalization of {@link joinFirst}, for a participant that joins
|
|
201
|
+
* several cohorts advertised by one service.
|
|
202
|
+
*
|
|
203
|
+
* For an open-ended, long-lived subscriber (no fixed count), construct an
|
|
204
|
+
* {@link AggregationParticipantRunner} directly, set `shouldJoin`, call
|
|
205
|
+
* `start()`, and listen for `cohort-complete` - the runner already drives
|
|
206
|
+
* any number of cohorts concurrently.
|
|
207
|
+
*
|
|
208
|
+
* @param options Participant runner options (set `shouldJoin` to select cohorts).
|
|
209
|
+
* @param count Number of completed cohorts to collect before resolving.
|
|
210
|
+
* @returns The {@link CohortCompleteInfo} for each completed cohort, in completion order.
|
|
211
|
+
*/
|
|
212
|
+
static async joinMatching(
|
|
213
|
+
options: AggregationParticipantRunnerOptions,
|
|
214
|
+
count: number,
|
|
215
|
+
): Promise<CohortCompleteInfo[]> {
|
|
216
|
+
return new Promise((resolve, reject) => {
|
|
217
|
+
const runner = new AggregationParticipantRunner(options);
|
|
218
|
+
const completed: CohortCompleteInfo[] = [];
|
|
219
|
+
runner.on('cohort-complete', (info) => {
|
|
220
|
+
completed.push(info);
|
|
221
|
+
if(completed.length >= count) {
|
|
222
|
+
runner.stop();
|
|
223
|
+
resolve(completed);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
runner.on('error', reject);
|
|
227
|
+
runner.start().catch(reject);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
202
231
|
/**
|
|
203
232
|
* Internal: handler registration with the transport. Idempotent and safe to call multiple times,
|
|
204
233
|
* but only registers handlers once.
|
|
@@ -213,6 +242,7 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
213
242
|
this.#transport.registerMessageHandler(this.#did, DISTRIBUTE_AGGREGATED_DATA, this.#handleDistributeData.bind(this));
|
|
214
243
|
this.#transport.registerMessageHandler(this.#did, AUTHORIZATION_REQUEST, this.#handleAuthorizationRequest.bind(this));
|
|
215
244
|
this.#transport.registerMessageHandler(this.#did, AGGREGATED_NONCE, this.#handleAggregatedNonce.bind(this));
|
|
245
|
+
this.#transport.registerMessageHandler(this.#did, FALLBACK_AUTHORIZATION_REQUEST, this.#handleFallbackAuthorizationRequest.bind(this));
|
|
216
246
|
}
|
|
217
247
|
|
|
218
248
|
/**
|
|
@@ -275,13 +305,20 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
275
305
|
if (!info) return;
|
|
276
306
|
this.emit('cohort-ready', { cohortId, beaconAddress: info.beaconAddress });
|
|
277
307
|
|
|
278
|
-
// Construct the signed update via caller callback and submit
|
|
308
|
+
// Construct the signed update via caller callback and submit. A null return
|
|
309
|
+
// means the member has no update this round: it declines (cooperative
|
|
310
|
+
// non-inclusion) but stays in the cohort and still signs.
|
|
279
311
|
const signedUpdate = await this.#onProvideUpdate({
|
|
280
312
|
cohortId,
|
|
281
313
|
beaconAddress : info.beaconAddress,
|
|
282
314
|
});
|
|
283
|
-
|
|
284
|
-
|
|
315
|
+
if(signedUpdate === null) {
|
|
316
|
+
await this.#sendAll(this.session.declineUpdate(cohortId));
|
|
317
|
+
this.emit('update-declined', { cohortId });
|
|
318
|
+
} else {
|
|
319
|
+
await this.#sendAll(this.session.submitUpdate(cohortId, signedUpdate));
|
|
320
|
+
this.emit('update-submitted', { cohortId });
|
|
321
|
+
}
|
|
285
322
|
} catch (err) {
|
|
286
323
|
this.emit('error', err as Error);
|
|
287
324
|
}
|
|
@@ -371,26 +408,71 @@ export class AggregationParticipantRunner extends TypedEventEmitter<AggregationP
|
|
|
371
408
|
await this.#sendAll(this.session.generatePartialSignature(cohortId));
|
|
372
409
|
|
|
373
410
|
// Check if we've reached completion
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
411
|
+
this.#emitCohortCompleteIfDone(cohortId);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
this.emit('error', err as Error);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Internal: handler for fallback authorization requests. The service abandoned
|
|
419
|
+
* the optimistic key path; the member authorizes the k-of-n script-path spend
|
|
420
|
+
* of the same beacon transaction (ADR 042). Reuses `onApproveSigning` to gate
|
|
421
|
+
* the decision, signs the fallback, and completes once it has contributed (the
|
|
422
|
+
* service needs only k members).
|
|
423
|
+
* @param {BaseMessage} msg - The received fallback authorization request message.
|
|
424
|
+
* @returns {Promise<void>} Resolves when processing is complete.
|
|
425
|
+
*/
|
|
426
|
+
async #handleFallbackAuthorizationRequest(msg: BaseMessage): Promise<void> {
|
|
427
|
+
if (this.#stopped) return;
|
|
428
|
+
try {
|
|
429
|
+
this.session.receive(msg);
|
|
430
|
+
|
|
431
|
+
const cohortId = msg.body?.cohortId;
|
|
432
|
+
if (!cohortId) return;
|
|
433
|
+
|
|
434
|
+
const req = this.session.pendingFallbackRequests.get(cohortId);
|
|
435
|
+
if (!req) return;
|
|
436
|
+
this.emit('fallback-requested', req);
|
|
437
|
+
|
|
438
|
+
const decision = await this.#onApproveSigning(req);
|
|
439
|
+
if (!decision.approved) {
|
|
440
|
+
this.emit('cohort-failed', { cohortId, reason: 'Fallback signing rejected by participant' });
|
|
441
|
+
return;
|
|
388
442
|
}
|
|
443
|
+
|
|
444
|
+
await this.#sendAll(this.session.approveFallback(cohortId));
|
|
445
|
+
// The member has contributed its fallback signature and is done from its
|
|
446
|
+
// own perspective, regardless of whether the service has yet collected k.
|
|
447
|
+
this.#emitCohortCompleteIfDone(cohortId);
|
|
389
448
|
} catch (err) {
|
|
390
449
|
this.emit('error', err as Error);
|
|
391
450
|
}
|
|
392
451
|
}
|
|
393
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Internal: emit `cohort-complete` with the participant's retained sidecar once
|
|
455
|
+
* the cohort has reached the Complete phase. Surfaces the CAS Announcement map
|
|
456
|
+
* (CAS beacons) or the SMT proof (SMT beacons) the participant keeps for future
|
|
457
|
+
* DID resolution. Read via getValidation (not pendingValidations, which lists
|
|
458
|
+
* only the AwaitingValidation phase) so the sidecar is still available at
|
|
459
|
+
* Complete. Shared by the optimistic and fallback completion paths.
|
|
460
|
+
*/
|
|
461
|
+
#emitCohortCompleteIfDone(cohortId: string): void {
|
|
462
|
+
if (this.session.getCohortPhase(cohortId) !== ParticipantCohortPhase.Complete) return;
|
|
463
|
+
const info = this.session.joinedCohorts.get(cohortId);
|
|
464
|
+
if (!info) return;
|
|
465
|
+
const validation = this.session.getValidation(cohortId);
|
|
466
|
+
this.emit('cohort-complete', {
|
|
467
|
+
cohortId,
|
|
468
|
+
beaconAddress : info.beaconAddress,
|
|
469
|
+
beaconType : validation?.beaconType ?? '',
|
|
470
|
+
included : validation?.included ?? true,
|
|
471
|
+
casAnnouncement : validation?.casAnnouncement,
|
|
472
|
+
smtProof : validation?.smtProof,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
394
476
|
/**
|
|
395
477
|
* Internal: send helper to ensure messages are sent sequentially. This is important for protocol
|
|
396
478
|
* correctness, as some transports may not guarantee message order if sent in parallel.
|