@invisible-labs/sdk 0.10.0-devnet → 0.11.0-devnet
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 +15 -2
- package/dist/.invisible-sdk-build-target.json +1 -1
- package/dist/{chunk-RWKG7N7I.js → chunk-A4R3DHKN.js} +2 -2
- package/dist/chunk-A4R3DHKN.js.map +1 -0
- package/dist/{chunk-6AKBRYKO.js → chunk-DOTYDYVB.js} +3 -3
- package/dist/{chunk-6AKBRYKO.js.map → chunk-DOTYDYVB.js.map} +1 -1
- package/dist/{chunk-ANQMIQYS.js → chunk-LVCDODTN.js} +5 -5
- package/dist/{chunk-ANQMIQYS.js.map → chunk-LVCDODTN.js.map} +1 -1
- package/dist/{chunk-DFBH5XLM.js → chunk-M45APS7S.js} +4 -4
- package/dist/{chunk-DFBH5XLM.js.map → chunk-M45APS7S.js.map} +1 -1
- package/dist/{chunk-6AGC3IOB.js → chunk-NOKBFHDP.js} +5 -5
- package/dist/{chunk-6AGC3IOB.js.map → chunk-NOKBFHDP.js.map} +1 -1
- package/dist/{chunk-HWRMSK7E.js → chunk-TNLSUQGJ.js} +4 -4
- package/dist/{chunk-HWRMSK7E.js.map → chunk-TNLSUQGJ.js.map} +1 -1
- package/dist/{chunk-EPWTRF5U.js → chunk-TYTVF3A4.js} +3 -3
- package/dist/{chunk-EPWTRF5U.js.map → chunk-TYTVF3A4.js.map} +1 -1
- package/dist/{chunk-AIKC2XQS.js → chunk-YYTRFM2F.js} +3 -3
- package/dist/{chunk-AIKC2XQS.js.map → chunk-YYTRFM2F.js.map} +1 -1
- package/dist/{coordinator-T2B7253V.js → coordinator-EQEL23A3.js} +3 -3
- package/dist/{coordinator-T2B7253V.js.map → coordinator-EQEL23A3.js.map} +1 -1
- package/dist/events.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -8
- package/dist/lp.d.ts +6 -3
- package/dist/lp.js +492 -194
- package/dist/lp.js.map +1 -1
- package/dist/stats.js +1 -1
- package/dist/storage.js +2 -2
- package/dist/{types.generated-CtMxCo9F.d.ts → types.generated-BpbFQlYB.d.ts} +1 -1
- package/dist/user.d.ts +2 -2
- package/dist/user.js +11 -11
- package/package.json +1 -1
- package/dist/chunk-RWKG7N7I.js.map +0 -1
package/dist/lp.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { isValidLpPositionId, LP_MAX_TOTAL_SHARDS, LP_MAX_INITIAL_SHARDS, LP_MAX_REFILL_BATCH_SIZE, LP_SHARD_PAGE_SIZE, LP_DEFAULT_REFILL_BATCH_SIZE, LP_DEFAULT_TARGET_SHARDS } from './chunk-
|
|
2
|
-
import { publicKey, assertAttested, lamports } from './chunk-
|
|
3
|
-
import { requestEnvelope, CoordinatorMessageType } from './chunk-
|
|
4
|
-
import { getSessionState } from './chunk-
|
|
5
|
-
import { CommandError,
|
|
1
|
+
import { isValidLpPositionId, LP_MAX_TOTAL_SHARDS, LP_MAX_INITIAL_SHARDS, LP_MAX_REFILL_BATCH_SIZE, LP_SHARD_PAGE_SIZE, LP_DEFAULT_REFILL_BATCH_SIZE, LP_DEFAULT_TARGET_SHARDS } from './chunk-TNLSUQGJ.js';
|
|
2
|
+
import { publicKey, assertAttested, lamports } from './chunk-TYTVF3A4.js';
|
|
3
|
+
import { requestEnvelope, CoordinatorMessageType } from './chunk-NOKBFHDP.js';
|
|
4
|
+
import { getSessionState } from './chunk-DOTYDYVB.js';
|
|
5
|
+
import { CommandError, TransportError, PolicyValidationError, LpLifecycleError, RoutingError, WalletError } from './chunk-A4R3DHKN.js';
|
|
6
6
|
import './chunk-VR6T6OJS.js';
|
|
7
7
|
|
|
8
8
|
// src/lp/actorSync.ts
|
|
@@ -343,62 +343,108 @@ var protocolPromise = null;
|
|
|
343
343
|
function createLpCoordinatorClient(session, options = {}) {
|
|
344
344
|
const sessionRef = { current: session };
|
|
345
345
|
const reconnectSession = options.reconnectSession === void 0 ? void 0 : async () => {
|
|
346
|
+
options.signal?.throwIfAborted();
|
|
346
347
|
const nextSession = await options.reconnectSession();
|
|
348
|
+
options.signal?.throwIfAborted();
|
|
347
349
|
sessionRef.current = nextSession;
|
|
348
350
|
return nextSession;
|
|
349
351
|
};
|
|
352
|
+
const run = (operation, signal) => withLpClientSignal(options.signal, signal, operation);
|
|
350
353
|
return {
|
|
351
354
|
authorizePositionCreation(intent, signer) {
|
|
352
|
-
return authorizePositionCreation(sessionRef.current, intent, signer);
|
|
355
|
+
return run((signal) => authorizePositionCreation(sessionRef.current, intent, signer, signal));
|
|
353
356
|
},
|
|
354
|
-
initDkg(input, auth) {
|
|
355
|
-
return initDkg(sessionRef.current, input, auth);
|
|
357
|
+
initDkg(input, auth, options2) {
|
|
358
|
+
return run((signal) => initDkg(sessionRef.current, input, auth, { signal }), options2?.signal);
|
|
356
359
|
},
|
|
357
360
|
abortDkgSessions(lpPositionId, auth) {
|
|
358
361
|
return abortDkgSessions(sessionRef.current, lpPositionId, auth);
|
|
359
362
|
},
|
|
360
|
-
dkgRound1(input, auth) {
|
|
361
|
-
return
|
|
363
|
+
dkgRound1(input, auth, options2) {
|
|
364
|
+
return run(
|
|
365
|
+
(signal) => dkgRound1(sessionRef.current, input, auth, { signal }),
|
|
366
|
+
options2?.signal
|
|
367
|
+
);
|
|
362
368
|
},
|
|
363
|
-
dkgRound2(input, auth) {
|
|
364
|
-
return
|
|
369
|
+
dkgRound2(input, auth, options2) {
|
|
370
|
+
return run(
|
|
371
|
+
(signal) => dkgRound2(sessionRef.current, input, auth, { signal }),
|
|
372
|
+
options2?.signal
|
|
373
|
+
);
|
|
365
374
|
},
|
|
366
375
|
openPosition(input, auth) {
|
|
367
|
-
return
|
|
376
|
+
return run(
|
|
377
|
+
(signal) => openPosition(sessionRef.current, input, auth, reconnectSession, signal)
|
|
378
|
+
);
|
|
368
379
|
},
|
|
369
380
|
getPosition(lpPositionId, auth, options2) {
|
|
370
|
-
return
|
|
381
|
+
return run(
|
|
382
|
+
(signal) => getPosition(sessionRef.current, lpPositionId, auth, { ...options2, signal }),
|
|
383
|
+
options2?.signal
|
|
384
|
+
);
|
|
371
385
|
},
|
|
372
386
|
finalizeDkgBatch(input, auth) {
|
|
373
|
-
return finalizeDkgBatch(sessionRef.current, input, auth);
|
|
387
|
+
return run((signal) => finalizeDkgBatch(sessionRef.current, input, auth, { signal }));
|
|
374
388
|
},
|
|
375
389
|
refillPosition(input, auth) {
|
|
376
|
-
return refillPosition(sessionRef.current, input, auth);
|
|
390
|
+
return run((signal) => refillPosition(sessionRef.current, input, auth, { signal }));
|
|
377
391
|
},
|
|
378
392
|
reconcileFunding(lpPositionId, auth) {
|
|
379
|
-
return reconcileFunding(sessionRef.current, lpPositionId, auth);
|
|
393
|
+
return run((signal) => reconcileFunding(sessionRef.current, lpPositionId, auth, { signal }));
|
|
380
394
|
},
|
|
381
395
|
planFunding(input, auth) {
|
|
382
|
-
return planFunding(sessionRef.current, input, auth);
|
|
396
|
+
return run((signal) => planFunding(sessionRef.current, input, auth, { signal }));
|
|
383
397
|
},
|
|
384
398
|
confirmFunding(input, auth) {
|
|
385
|
-
return confirmFunding(sessionRef.current, input, auth);
|
|
399
|
+
return run((signal) => confirmFunding(sessionRef.current, input, auth, { signal }));
|
|
386
400
|
},
|
|
387
401
|
prepareTopUp(lpPositionId, auth) {
|
|
388
|
-
return prepareTopUp(sessionRef.current, lpPositionId, auth);
|
|
402
|
+
return run((signal) => prepareTopUp(sessionRef.current, lpPositionId, auth, { signal }));
|
|
389
403
|
},
|
|
390
404
|
getTopUpStatus(input, auth) {
|
|
391
|
-
return getTopUpStatus(sessionRef.current, input, auth);
|
|
405
|
+
return run((signal) => getTopUpStatus(sessionRef.current, input, auth, { signal }));
|
|
392
406
|
},
|
|
393
407
|
makeAvailable(input, auth) {
|
|
394
|
-
return makeAvailable(sessionRef.current, input, auth);
|
|
408
|
+
return run((signal) => makeAvailable(sessionRef.current, input, auth, { signal }));
|
|
395
409
|
},
|
|
396
410
|
executeWithdrawal(input, auth) {
|
|
397
|
-
return executeWithdrawal(sessionRef.current, input, auth);
|
|
411
|
+
return run((signal) => executeWithdrawal(sessionRef.current, input, auth, { signal }));
|
|
398
412
|
}
|
|
399
413
|
};
|
|
400
414
|
}
|
|
401
|
-
async function
|
|
415
|
+
async function withLpClientSignal(clientSignal, requestSignal, operation) {
|
|
416
|
+
const perform = async (signal) => {
|
|
417
|
+
try {
|
|
418
|
+
signal?.throwIfAborted();
|
|
419
|
+
return await operation(signal);
|
|
420
|
+
} catch (error) {
|
|
421
|
+
if (clientSignal?.aborted && signal?.reason === clientSignal.reason && error instanceof Error && error.name === "AbortError") {
|
|
422
|
+
throw clientSignal.reason;
|
|
423
|
+
}
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
if (clientSignal === void 0) return perform(requestSignal);
|
|
428
|
+
if (requestSignal === void 0 || requestSignal === clientSignal) {
|
|
429
|
+
clientSignal.throwIfAborted();
|
|
430
|
+
return perform(clientSignal);
|
|
431
|
+
}
|
|
432
|
+
const controller = new AbortController();
|
|
433
|
+
const abortClient = () => controller.abort(clientSignal.reason);
|
|
434
|
+
const abortRequest = () => controller.abort(requestSignal.reason);
|
|
435
|
+
clientSignal.addEventListener("abort", abortClient, { once: true });
|
|
436
|
+
requestSignal.addEventListener("abort", abortRequest, { once: true });
|
|
437
|
+
try {
|
|
438
|
+
if (clientSignal.aborted) abortClient();
|
|
439
|
+
if (requestSignal.aborted) abortRequest();
|
|
440
|
+
controller.signal.throwIfAborted();
|
|
441
|
+
return await perform(controller.signal);
|
|
442
|
+
} finally {
|
|
443
|
+
clientSignal.removeEventListener("abort", abortClient);
|
|
444
|
+
requestSignal.removeEventListener("abort", abortRequest);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async function authorizePositionCreation(session, intent, signer, signal) {
|
|
402
448
|
const signerPublicKey = publicKey(signer.publicKey);
|
|
403
449
|
const challengeRequestStartedAtMs = Date.now();
|
|
404
450
|
const challengeEnvelope = await requestEnvelope(
|
|
@@ -416,7 +462,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
416
462
|
}
|
|
417
463
|
}
|
|
418
464
|
},
|
|
419
|
-
{ timeoutMs: LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS }
|
|
465
|
+
{ timeoutMs: LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS, signal }
|
|
420
466
|
);
|
|
421
467
|
const challenge = challengeEnvelope.payload;
|
|
422
468
|
if (challenge.case !== "challenge") {
|
|
@@ -472,7 +518,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
472
518
|
session,
|
|
473
519
|
CoordinatorMessageType.LpCreateAuthorization,
|
|
474
520
|
proofPayload,
|
|
475
|
-
{ timeoutMs: proofTimeoutMs }
|
|
521
|
+
{ timeoutMs: proofTimeoutMs, signal }
|
|
476
522
|
);
|
|
477
523
|
} catch (error) {
|
|
478
524
|
if (!isAmbiguousCoordinatorRequestFailure(error)) throw error;
|
|
@@ -485,7 +531,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
485
531
|
session,
|
|
486
532
|
CoordinatorMessageType.LpCreateAuthorization,
|
|
487
533
|
proofPayload,
|
|
488
|
-
{ timeoutMs: proofRetryTimeoutMs }
|
|
534
|
+
{ timeoutMs: proofRetryTimeoutMs, signal }
|
|
489
535
|
);
|
|
490
536
|
}
|
|
491
537
|
const authorization = proofEnvelope.payload;
|
|
@@ -542,15 +588,22 @@ async function signLpCreationMessageWithTimeout(signer, message, timeoutMs) {
|
|
|
542
588
|
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
543
589
|
}
|
|
544
590
|
}
|
|
545
|
-
async function initDkg(session, input, auth) {
|
|
546
|
-
const response = await requestForPosition(
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
591
|
+
async function initDkg(session, input, auth, options = {}) {
|
|
592
|
+
const response = await requestForPosition(
|
|
593
|
+
session,
|
|
594
|
+
input.lpPositionId,
|
|
595
|
+
auth,
|
|
596
|
+
"dkg_init",
|
|
597
|
+
{
|
|
598
|
+
case: "dkgInit",
|
|
599
|
+
value: { index: input.index }
|
|
600
|
+
},
|
|
601
|
+
options
|
|
602
|
+
);
|
|
550
603
|
if (response.case !== "dkgInit") throw new Error("Unexpected LP DKG init response");
|
|
551
604
|
return { sessionId: response.value.session_id };
|
|
552
605
|
}
|
|
553
|
-
async function abortDkgSessions(session, lpPositionId, auth) {
|
|
606
|
+
async function abortDkgSessions(session, lpPositionId, auth, signal) {
|
|
554
607
|
const response = await requestForPosition(
|
|
555
608
|
session,
|
|
556
609
|
lpPositionId,
|
|
@@ -560,34 +613,46 @@ async function abortDkgSessions(session, lpPositionId, auth) {
|
|
|
560
613
|
case: "dkgAbort",
|
|
561
614
|
value: {}
|
|
562
615
|
},
|
|
563
|
-
{ timeoutMs: LP_DKG_ABORT_REQUEST_TIMEOUT_MS }
|
|
616
|
+
{ timeoutMs: LP_DKG_ABORT_REQUEST_TIMEOUT_MS, signal }
|
|
564
617
|
);
|
|
565
618
|
if (response.case !== "dkgAbort") throw new Error("Unexpected LP DKG abort response");
|
|
566
619
|
return { abortedSessionCount: response.value.aborted_session_count };
|
|
567
620
|
}
|
|
568
|
-
async function dkgRound1(session, input, auth) {
|
|
569
|
-
const response = await request(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
621
|
+
async function dkgRound1(session, input, auth, options = {}) {
|
|
622
|
+
const response = await request(
|
|
623
|
+
session,
|
|
624
|
+
auth,
|
|
625
|
+
"dkg_round1",
|
|
626
|
+
{
|
|
627
|
+
case: "dkgRound1",
|
|
628
|
+
value: {
|
|
629
|
+
session_id: input.sessionId,
|
|
630
|
+
package: Uint8Array.from(input.package)
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
options
|
|
634
|
+
);
|
|
576
635
|
if (response.case !== "dkgRound1") throw new Error("Unexpected LP DKG round1 response");
|
|
577
636
|
return {
|
|
578
637
|
package: response.value.package,
|
|
579
638
|
round2ForLp: response.value.round2_for_lp
|
|
580
639
|
};
|
|
581
640
|
}
|
|
582
|
-
async function dkgRound2(session, input, auth) {
|
|
583
|
-
const response = await request(
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
641
|
+
async function dkgRound2(session, input, auth, options = {}) {
|
|
642
|
+
const response = await request(
|
|
643
|
+
session,
|
|
644
|
+
auth,
|
|
645
|
+
"dkg_round2",
|
|
646
|
+
{
|
|
647
|
+
case: "dkgRound2",
|
|
648
|
+
value: {
|
|
649
|
+
session_id: input.sessionId,
|
|
650
|
+
package: Uint8Array.from(input.package),
|
|
651
|
+
delegated_share: Uint8Array.from(input.delegatedShare)
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
options
|
|
655
|
+
);
|
|
591
656
|
if (response.case !== "dkgRound2") throw new Error("Unexpected LP DKG round2 response");
|
|
592
657
|
return {
|
|
593
658
|
address: response.value.address,
|
|
@@ -596,7 +661,7 @@ async function dkgRound2(session, input, auth) {
|
|
|
596
661
|
index: response.value.index
|
|
597
662
|
};
|
|
598
663
|
}
|
|
599
|
-
async function openPosition(session, input, auth, reconnectSession) {
|
|
664
|
+
async function openPosition(session, input, auth, reconnectSession, signal) {
|
|
600
665
|
const payload = {
|
|
601
666
|
case: "positionOpen",
|
|
602
667
|
value: {
|
|
@@ -615,6 +680,7 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
615
680
|
};
|
|
616
681
|
const commandDeadlineMs = Date.now() + LP_POSITION_OPEN_COMMAND_TTL_MS;
|
|
617
682
|
const commandOptions = {
|
|
683
|
+
signal,
|
|
618
684
|
commandNonce: randomBytes(32),
|
|
619
685
|
commandExpiresAtMs: commandDeadlineMs,
|
|
620
686
|
deadlineMs: commandDeadlineMs,
|
|
@@ -633,7 +699,7 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
633
699
|
);
|
|
634
700
|
} catch (error) {
|
|
635
701
|
if (!isAmbiguousLpPositionOpenFailure(error)) throw error;
|
|
636
|
-
responseSession = reconnectSession === void 0 ? session : await reconnectSessionWithinDeadline(reconnectSession, commandDeadlineMs);
|
|
702
|
+
responseSession = reconnectSession === void 0 ? session : await reconnectSessionWithinDeadline(reconnectSession, commandDeadlineMs, signal);
|
|
637
703
|
}
|
|
638
704
|
const position = await hydratePositionResponse(
|
|
639
705
|
responseSession,
|
|
@@ -641,7 +707,8 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
641
707
|
auth,
|
|
642
708
|
response,
|
|
643
709
|
{
|
|
644
|
-
deadlineMs: commandDeadlineMs
|
|
710
|
+
deadlineMs: commandDeadlineMs,
|
|
711
|
+
signal
|
|
645
712
|
}
|
|
646
713
|
);
|
|
647
714
|
if (position.authPublicKey !== bytesToHex(Uint8Array.from(input.authPublicKey)) || position.refillPublicKey !== bytesToHex(Uint8Array.from(input.refillPublicKey)) || position.withdrawalCommitment !== bytesToHex(Uint8Array.from(input.withdrawalCommitment)) || position.committedLamports !== input.committedLamports || position.targetShardCount !== input.shardCount || position.refillThreshold !== input.refillThreshold || position.createdAt !== input.createdAtMs) {
|
|
@@ -655,7 +722,8 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
655
722
|
}
|
|
656
723
|
return position;
|
|
657
724
|
}
|
|
658
|
-
async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
725
|
+
async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs, signal) {
|
|
726
|
+
signal?.throwIfAborted();
|
|
659
727
|
const remainingMs = deadlineMs - Date.now();
|
|
660
728
|
if (remainingMs <= 0) {
|
|
661
729
|
throw new CommandError(
|
|
@@ -664,8 +732,12 @@ async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
|
664
732
|
);
|
|
665
733
|
}
|
|
666
734
|
let timer;
|
|
735
|
+
let removeAbort;
|
|
667
736
|
try {
|
|
668
737
|
return await new Promise((resolve, reject) => {
|
|
738
|
+
const onAbort = () => reject(signal?.reason);
|
|
739
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
740
|
+
removeAbort = () => signal?.removeEventListener("abort", onAbort);
|
|
669
741
|
timer = setTimeout(() => {
|
|
670
742
|
reject(
|
|
671
743
|
new CommandError(
|
|
@@ -674,10 +746,14 @@ async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
|
674
746
|
)
|
|
675
747
|
);
|
|
676
748
|
}, remainingMs);
|
|
677
|
-
Promise.resolve().then(
|
|
749
|
+
Promise.resolve().then(() => {
|
|
750
|
+
signal?.throwIfAborted();
|
|
751
|
+
return reconnectSession();
|
|
752
|
+
}).then(resolve, reject);
|
|
678
753
|
});
|
|
679
754
|
} finally {
|
|
680
755
|
if (timer !== void 0) clearTimeout(timer);
|
|
756
|
+
removeAbort?.();
|
|
681
757
|
}
|
|
682
758
|
}
|
|
683
759
|
function isAmbiguousLpPositionOpenFailure(error) {
|
|
@@ -825,48 +901,76 @@ function lpPositionPageRequestOptions(options) {
|
|
|
825
901
|
timeoutMs: Math.min(options.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS, remainingMs)
|
|
826
902
|
};
|
|
827
903
|
}
|
|
828
|
-
async function finalizeDkgBatch(session, input, auth) {
|
|
829
|
-
const response = await requestForPosition(
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
904
|
+
async function finalizeDkgBatch(session, input, auth, options = {}) {
|
|
905
|
+
const response = await requestForPosition(
|
|
906
|
+
session,
|
|
907
|
+
input.lpPositionId,
|
|
908
|
+
auth,
|
|
909
|
+
"dkg_finalize",
|
|
910
|
+
{
|
|
911
|
+
case: "dkgFinalize",
|
|
912
|
+
value: {
|
|
913
|
+
start_index: input.startIndex,
|
|
914
|
+
addresses: input.addresses,
|
|
915
|
+
finalized_at_ms: input.finalizedAtMs
|
|
916
|
+
}
|
|
917
|
+
},
|
|
918
|
+
options
|
|
919
|
+
);
|
|
920
|
+
return hydratePositionResponse(session, auth.lpPositionId, auth, response, options);
|
|
838
921
|
}
|
|
839
|
-
async function refillPosition(session, input, auth) {
|
|
840
|
-
const response = await requestForPosition(
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
922
|
+
async function refillPosition(session, input, auth, options = {}) {
|
|
923
|
+
const response = await requestForPosition(
|
|
924
|
+
session,
|
|
925
|
+
input.lpPositionId,
|
|
926
|
+
auth,
|
|
927
|
+
"refill",
|
|
928
|
+
{
|
|
929
|
+
case: "refill",
|
|
930
|
+
value: {
|
|
931
|
+
shard_count: input.shardCount,
|
|
932
|
+
shard_amount_lamports: input.shardAmountLamports,
|
|
933
|
+
addresses: input.addresses,
|
|
934
|
+
authorized_at_ms: input.authorizedAtMs
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
options
|
|
938
|
+
);
|
|
939
|
+
return hydratePositionResponse(session, auth.lpPositionId, auth, response, options);
|
|
850
940
|
}
|
|
851
|
-
async function reconcileFunding(session, lpPositionId, auth) {
|
|
852
|
-
const response = await requestForPosition(
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
941
|
+
async function reconcileFunding(session, lpPositionId, auth, options = {}) {
|
|
942
|
+
const response = await requestForPosition(
|
|
943
|
+
session,
|
|
944
|
+
lpPositionId,
|
|
945
|
+
auth,
|
|
946
|
+
"reconcile_funding",
|
|
947
|
+
{
|
|
948
|
+
case: "reconcileFunding",
|
|
949
|
+
value: {}
|
|
950
|
+
},
|
|
951
|
+
options
|
|
952
|
+
);
|
|
953
|
+
return hydratePositionResponse(session, auth.lpPositionId, auth, response, options);
|
|
857
954
|
}
|
|
858
|
-
async function planFunding(session, input, auth) {
|
|
859
|
-
const response = await requestForPosition(
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
955
|
+
async function planFunding(session, input, auth, options = {}) {
|
|
956
|
+
const response = await requestForPosition(
|
|
957
|
+
session,
|
|
958
|
+
input.lpPositionId,
|
|
959
|
+
auth,
|
|
960
|
+
"funding_plan",
|
|
961
|
+
{
|
|
962
|
+
case: "fundingPlan",
|
|
963
|
+
value: {
|
|
964
|
+
shard_count: input.shardCount,
|
|
965
|
+
planned_at_ms: input.nowMs
|
|
966
|
+
}
|
|
967
|
+
},
|
|
968
|
+
options
|
|
969
|
+
);
|
|
866
970
|
if (response.case !== "shards") throw new Error("Unexpected LP funding plan response");
|
|
867
971
|
return response.value.map(mapShard);
|
|
868
972
|
}
|
|
869
|
-
async function confirmFunding(session, input, auth) {
|
|
973
|
+
async function confirmFunding(session, input, auth, options = {}) {
|
|
870
974
|
const response = await requestForPosition(
|
|
871
975
|
session,
|
|
872
976
|
input.lpPositionId,
|
|
@@ -879,38 +983,60 @@ async function confirmFunding(session, input, auth) {
|
|
|
879
983
|
amount_lamports: input.amountLamports,
|
|
880
984
|
funding_tx_signature: input.fundingTxSignature
|
|
881
985
|
}
|
|
882
|
-
}
|
|
986
|
+
},
|
|
987
|
+
options
|
|
883
988
|
);
|
|
884
989
|
if (response.case !== "shard") throw new Error("Unexpected LP funding confirmation response");
|
|
885
990
|
return mapShard(response.value);
|
|
886
991
|
}
|
|
887
|
-
async function prepareTopUp(session, lpPositionId, auth) {
|
|
888
|
-
const response = await requestForPosition(
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
992
|
+
async function prepareTopUp(session, lpPositionId, auth, options = {}) {
|
|
993
|
+
const response = await requestForPosition(
|
|
994
|
+
session,
|
|
995
|
+
lpPositionId,
|
|
996
|
+
auth,
|
|
997
|
+
"prepare_top_up",
|
|
998
|
+
{
|
|
999
|
+
case: "prepareTopUp",
|
|
1000
|
+
value: {}
|
|
1001
|
+
},
|
|
1002
|
+
options
|
|
1003
|
+
);
|
|
892
1004
|
if (response.case !== "topUpRequest") throw new Error("Unexpected LP top-up response");
|
|
893
1005
|
return mapTopUpRequest(response.value);
|
|
894
1006
|
}
|
|
895
|
-
async function getTopUpStatus(session, input, auth) {
|
|
896
|
-
const response = await requestForPosition(
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1007
|
+
async function getTopUpStatus(session, input, auth, options = {}) {
|
|
1008
|
+
const response = await requestForPosition(
|
|
1009
|
+
session,
|
|
1010
|
+
input.lpPositionId,
|
|
1011
|
+
auth,
|
|
1012
|
+
"top_up_status",
|
|
1013
|
+
{
|
|
1014
|
+
case: "topUpStatus",
|
|
1015
|
+
value: { top_up_id: input.topUpId }
|
|
1016
|
+
},
|
|
1017
|
+
options
|
|
1018
|
+
);
|
|
900
1019
|
if (response.case !== "topUpRequest") throw new Error("Unexpected LP top-up response");
|
|
901
1020
|
return mapTopUpRequest(response.value);
|
|
902
1021
|
}
|
|
903
|
-
async function makeAvailable(session, input, auth) {
|
|
904
|
-
const response = await requestForPosition(
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1022
|
+
async function makeAvailable(session, input, auth, options = {}) {
|
|
1023
|
+
const response = await requestForPosition(
|
|
1024
|
+
session,
|
|
1025
|
+
input.lpPositionId,
|
|
1026
|
+
auth,
|
|
1027
|
+
"make_available",
|
|
1028
|
+
{
|
|
1029
|
+
case: "makeAvailable",
|
|
1030
|
+
value: {
|
|
1031
|
+
shard_id: input.shardId
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
options
|
|
1035
|
+
);
|
|
910
1036
|
if (response.case !== "shard") throw new Error("Unexpected LP availability response");
|
|
911
1037
|
return mapShard(response.value);
|
|
912
1038
|
}
|
|
913
|
-
async function executeWithdrawal(session, input, auth) {
|
|
1039
|
+
async function executeWithdrawal(session, input, auth, options = {}) {
|
|
914
1040
|
validateLpWithdrawalPlan({
|
|
915
1041
|
destinationAddresses: input.destinationAddresses,
|
|
916
1042
|
depositPrincipalLamports: input.withdrawalMode === "max_available" ? 1 : input.depositPrincipalLamports,
|
|
@@ -920,18 +1046,25 @@ async function executeWithdrawal(session, input, auth) {
|
|
|
920
1046
|
// a one-destination request based on an unknown current source count.
|
|
921
1047
|
allowManyToOne: input.withdrawalMode === "max_available" || input.allowManyToOne
|
|
922
1048
|
});
|
|
923
|
-
const response = await requestForPosition(
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1049
|
+
const response = await requestForPosition(
|
|
1050
|
+
session,
|
|
1051
|
+
input.lpPositionId,
|
|
1052
|
+
auth,
|
|
1053
|
+
"withdraw_request",
|
|
1054
|
+
{
|
|
1055
|
+
case: "withdrawRequest",
|
|
1056
|
+
value: {
|
|
1057
|
+
destination_addresses: input.destinationAddresses,
|
|
1058
|
+
deposit_principal_lamports: input.withdrawalMode === "max_available" ? 0 : input.depositPrincipalLamports,
|
|
1059
|
+
earned_fee_lamports: input.withdrawalMode === "max_available" ? 0 : input.earnedFeeLamports,
|
|
1060
|
+
withdrawal_mode: input.withdrawalMode,
|
|
1061
|
+
requested_at_ms: input.requestedAtMs,
|
|
1062
|
+
fee_policy_hash: input.feePolicyHash,
|
|
1063
|
+
fee_basis_revision: input.feeBasisRevision
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
1066
|
+
options
|
|
1067
|
+
);
|
|
935
1068
|
if (response.case !== "withdrawalExecution") {
|
|
936
1069
|
throw new Error("Unexpected LP withdrawal execution response");
|
|
937
1070
|
}
|
|
@@ -964,13 +1097,15 @@ async function executeWithdrawal(session, input, auth) {
|
|
|
964
1097
|
acceptedEarnedFeeLamports: execution.accepted_earned_fee_lamports
|
|
965
1098
|
};
|
|
966
1099
|
}
|
|
967
|
-
function request(session, auth, action, payload) {
|
|
968
|
-
return requestForPosition(session, auth.lpPositionId, auth, action, payload);
|
|
1100
|
+
function request(session, auth, action, payload, options = {}) {
|
|
1101
|
+
return requestForPosition(session, auth.lpPositionId, auth, action, payload, options);
|
|
969
1102
|
}
|
|
970
1103
|
async function requestForPosition(session, lpPositionId, auth, action, payload, options = {}) {
|
|
1104
|
+
options.signal?.throwIfAborted();
|
|
971
1105
|
const timeoutMs = lpPositionPageRequestOptions(options).timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS;
|
|
972
1106
|
assertAuthMatchesPosition(lpPositionId, auth);
|
|
973
1107
|
const protocol = await loadProtocol();
|
|
1108
|
+
options.signal?.throwIfAborted();
|
|
974
1109
|
const state = getSessionState(session);
|
|
975
1110
|
const attestation = state.channel?.attestation;
|
|
976
1111
|
if (!attestation) {
|
|
@@ -987,7 +1122,9 @@ async function requestForPosition(session, lpPositionId, auth, action, payload,
|
|
|
987
1122
|
),
|
|
988
1123
|
payload
|
|
989
1124
|
};
|
|
1125
|
+
options.signal?.throwIfAborted();
|
|
990
1126
|
const signature = await signLpCommandBytes(auth, protocol.encodeLpCommandForSigning(command));
|
|
1127
|
+
options.signal?.throwIfAborted();
|
|
991
1128
|
const { type, payload: envelopePayload } = protocol.lpSignedCommandEnvelope(command, signature);
|
|
992
1129
|
const requestOptions = lpPositionPageRequestOptions(options);
|
|
993
1130
|
const envelope = await requestEnvelope(session, type, envelopePayload, {
|
|
@@ -1226,13 +1363,14 @@ function randomBytes(length) {
|
|
|
1226
1363
|
return bytes;
|
|
1227
1364
|
}
|
|
1228
1365
|
function loadProtocol() {
|
|
1229
|
-
protocolPromise ??= import('./coordinator-
|
|
1366
|
+
protocolPromise ??= import('./coordinator-EQEL23A3.js');
|
|
1230
1367
|
return protocolPromise;
|
|
1231
1368
|
}
|
|
1232
1369
|
|
|
1233
1370
|
// src/lp/dkgBatch.ts
|
|
1234
|
-
var MAX_LP_DKG_CONCURRENCY =
|
|
1371
|
+
var MAX_LP_DKG_CONCURRENCY = 16;
|
|
1235
1372
|
var DEFAULT_LP_DKG_CONCURRENCY = MAX_LP_DKG_CONCURRENCY;
|
|
1373
|
+
var LP_DKG_WORKER_FAILURE_MESSAGE = "LP DKG worker failed";
|
|
1236
1374
|
var LP_DKG_WORKER_REQUEST_TIMEOUT_MS = 3e4;
|
|
1237
1375
|
var LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE = "LP DKG worker request timed out";
|
|
1238
1376
|
var LP_DKG_ABORT_CLEANUP_TIMEOUT_MS = 1e4;
|
|
@@ -1242,21 +1380,28 @@ var LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS = 5 * 6e4 + 15e3;
|
|
|
1242
1380
|
var LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS = 2e3;
|
|
1243
1381
|
var LP_DKG_ACTIVE_SESSION_RETRY_TIMEOUT_MS = LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS;
|
|
1244
1382
|
async function createLpDkgBatch(input) {
|
|
1383
|
+
input.signal?.throwIfAborted();
|
|
1245
1384
|
if (input.useDeterministicTestAddresses === true) {
|
|
1246
1385
|
const addresses2 = Array.from(
|
|
1247
1386
|
{ length: input.count },
|
|
1248
1387
|
(_, offset) => testAddress(input.lpPositionId, input.startIndex + offset)
|
|
1249
1388
|
);
|
|
1250
1389
|
for (const [offset, address] of addresses2.entries()) {
|
|
1390
|
+
input.signal?.throwIfAborted();
|
|
1251
1391
|
input.onProgress?.({
|
|
1252
1392
|
completed: offset + 1,
|
|
1253
1393
|
total: input.count,
|
|
1254
1394
|
address
|
|
1255
1395
|
});
|
|
1256
1396
|
}
|
|
1397
|
+
input.signal?.throwIfAborted();
|
|
1257
1398
|
return addresses2;
|
|
1258
1399
|
}
|
|
1259
|
-
const workerCount =
|
|
1400
|
+
const workerCount = resolveLpDkgConcurrency(input.count, input.concurrency);
|
|
1401
|
+
const cancellation = new AbortController();
|
|
1402
|
+
const cancel = () => cancellation.abort(input.signal?.reason);
|
|
1403
|
+
input.signal?.addEventListener("abort", cancel, { once: true });
|
|
1404
|
+
if (input.signal?.aborted) cancel();
|
|
1260
1405
|
const workers = [];
|
|
1261
1406
|
let workersTerminated = false;
|
|
1262
1407
|
const terminateWorkers = () => {
|
|
@@ -1269,16 +1414,19 @@ async function createLpDkgBatch(input) {
|
|
|
1269
1414
|
let nextOffset = 0;
|
|
1270
1415
|
try {
|
|
1271
1416
|
for (let index = 0; index < workerCount; index += 1) {
|
|
1417
|
+
cancellation.signal.throwIfAborted();
|
|
1272
1418
|
workers.push(createWorker(input.workerFactory));
|
|
1273
1419
|
}
|
|
1274
1420
|
await Promise.all(
|
|
1275
1421
|
workers.map(async (worker) => {
|
|
1276
1422
|
for (; ; ) {
|
|
1423
|
+
cancellation.signal.throwIfAborted();
|
|
1277
1424
|
const offset = nextOffset;
|
|
1278
1425
|
nextOffset += 1;
|
|
1279
1426
|
if (offset >= input.count) return;
|
|
1280
1427
|
const index = input.startIndex + offset;
|
|
1281
|
-
const address = await createLpDkgShard(input, worker, index);
|
|
1428
|
+
const address = await createLpDkgShard(input, worker, index, cancellation.signal);
|
|
1429
|
+
cancellation.signal.throwIfAborted();
|
|
1282
1430
|
addresses[offset] = address;
|
|
1283
1431
|
completed += 1;
|
|
1284
1432
|
input.onProgress?.({
|
|
@@ -1291,12 +1439,14 @@ async function createLpDkgBatch(input) {
|
|
|
1291
1439
|
);
|
|
1292
1440
|
return addresses;
|
|
1293
1441
|
} catch (error) {
|
|
1442
|
+
cancellation.abort(error);
|
|
1294
1443
|
terminateWorkers();
|
|
1295
1444
|
if (!isLpDkgSessionCoordinationError(error)) {
|
|
1296
1445
|
await abortDkgSessionsAfterFailure(input);
|
|
1297
1446
|
}
|
|
1298
1447
|
throw error;
|
|
1299
1448
|
} finally {
|
|
1449
|
+
input.signal?.removeEventListener("abort", cancel);
|
|
1300
1450
|
terminateWorkers();
|
|
1301
1451
|
}
|
|
1302
1452
|
}
|
|
@@ -1320,61 +1470,82 @@ async function abortDkgSessionsAfterFailure(input) {
|
|
|
1320
1470
|
if (timeoutId !== void 0) globalThis.clearTimeout(timeoutId);
|
|
1321
1471
|
}
|
|
1322
1472
|
}
|
|
1323
|
-
async function createLpDkgShard(input, worker, index) {
|
|
1473
|
+
async function createLpDkgShard(input, worker, index, signal) {
|
|
1324
1474
|
const deadline = Date.now() + LP_DKG_ACTIVE_SESSION_RETRY_TIMEOUT_MS;
|
|
1325
1475
|
let sawActiveSession = false;
|
|
1326
1476
|
for (; ; ) {
|
|
1327
1477
|
if (sawActiveSession) {
|
|
1328
|
-
const completedAddress = await getCompletedShardAddress(input, index);
|
|
1478
|
+
const completedAddress = await getCompletedShardAddress(input, index, signal);
|
|
1329
1479
|
if (completedAddress !== null) return completedAddress;
|
|
1330
1480
|
}
|
|
1331
1481
|
try {
|
|
1332
|
-
return await runLpDkgShard(input, worker, index);
|
|
1482
|
+
return await runLpDkgShard(input, worker, index, signal);
|
|
1333
1483
|
} catch (error) {
|
|
1334
1484
|
if (isLpDkgCompletedOrVisibleError(error)) {
|
|
1335
|
-
return waitForCompletedShardAddress(input, index);
|
|
1485
|
+
return waitForCompletedShardAddress(input, index, signal);
|
|
1336
1486
|
}
|
|
1337
1487
|
if (!isLpDkgActiveSessionError(error)) throw error;
|
|
1338
1488
|
sawActiveSession = true;
|
|
1339
|
-
const completedAddress = await getCompletedShardAddress(input, index);
|
|
1489
|
+
const completedAddress = await getCompletedShardAddress(input, index, signal);
|
|
1340
1490
|
if (completedAddress !== null) return completedAddress;
|
|
1341
1491
|
if (Date.now() >= deadline) throw error;
|
|
1342
|
-
await sleep(LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS);
|
|
1492
|
+
await abortable(sleep(LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS), signal);
|
|
1343
1493
|
}
|
|
1344
1494
|
}
|
|
1345
1495
|
}
|
|
1346
|
-
async function runLpDkgShard(input, worker, index) {
|
|
1496
|
+
async function runLpDkgShard(input, worker, index, signal) {
|
|
1347
1497
|
const roundId = `lp_dkg_${Date.now()}_${index}_${Math.random().toString(16).slice(2)}`;
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
input.auth
|
|
1498
|
+
signal.throwIfAborted();
|
|
1499
|
+
const initResponse = await abortable(
|
|
1500
|
+
input.client.initDkg({ lpPositionId: input.lpPositionId, index }, input.auth, { signal }),
|
|
1501
|
+
signal
|
|
1351
1502
|
);
|
|
1352
|
-
const round1 = await workerRequest(
|
|
1353
|
-
|
|
1354
|
-
type: "round1"
|
|
1355
|
-
});
|
|
1356
|
-
if (round1.type !== "round1") throw new Error("LP DKG worker returned wrong round1 type");
|
|
1357
|
-
const round1Response = await input.client.dkgRound1(
|
|
1503
|
+
const round1 = await workerRequest(
|
|
1504
|
+
worker,
|
|
1358
1505
|
{
|
|
1359
|
-
|
|
1360
|
-
|
|
1506
|
+
id: roundId,
|
|
1507
|
+
type: "round1"
|
|
1361
1508
|
},
|
|
1362
|
-
|
|
1509
|
+
signal
|
|
1363
1510
|
);
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1511
|
+
if (round1.type !== "round1")
|
|
1512
|
+
throw lpDkgWorkerFailure(new Error("LP DKG worker returned wrong round1 type"));
|
|
1513
|
+
signal.throwIfAborted();
|
|
1514
|
+
const round1Response = await abortable(
|
|
1515
|
+
input.client.dkgRound1(
|
|
1516
|
+
{
|
|
1517
|
+
sessionId: initResponse.sessionId,
|
|
1518
|
+
package: round1.package
|
|
1519
|
+
},
|
|
1520
|
+
input.auth,
|
|
1521
|
+
{ signal }
|
|
1522
|
+
),
|
|
1523
|
+
signal
|
|
1524
|
+
);
|
|
1525
|
+
const round2 = await workerRequest(
|
|
1526
|
+
worker,
|
|
1372
1527
|
{
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1528
|
+
id: roundId,
|
|
1529
|
+
type: "round2",
|
|
1530
|
+
teeRound1: Array.from(round1Response.package),
|
|
1531
|
+
teeRound2ForLp: Array.from(round1Response.round2ForLp)
|
|
1376
1532
|
},
|
|
1377
|
-
|
|
1533
|
+
signal
|
|
1534
|
+
);
|
|
1535
|
+
if (round2.type !== "round2")
|
|
1536
|
+
throw lpDkgWorkerFailure(new Error("LP DKG worker returned wrong round2 type"));
|
|
1537
|
+
signal.throwIfAborted();
|
|
1538
|
+
const round2Response = await abortable(
|
|
1539
|
+
input.client.dkgRound2(
|
|
1540
|
+
{
|
|
1541
|
+
sessionId: initResponse.sessionId,
|
|
1542
|
+
package: round2.package,
|
|
1543
|
+
delegatedShare: round2.delegatedShare
|
|
1544
|
+
},
|
|
1545
|
+
input.auth,
|
|
1546
|
+
{ signal }
|
|
1547
|
+
),
|
|
1548
|
+
signal
|
|
1378
1549
|
);
|
|
1379
1550
|
if (!bytesEqual(Uint8Array.from(round2.jointPubkey), round2Response.jointPubkey)) {
|
|
1380
1551
|
throw new Error(`LP DKG joint pubkey mismatch at index ${index}`);
|
|
@@ -1384,22 +1555,27 @@ async function runLpDkgShard(input, worker, index) {
|
|
|
1384
1555
|
}
|
|
1385
1556
|
return round2Response.address;
|
|
1386
1557
|
}
|
|
1387
|
-
async function waitForCompletedShardAddress(input, index) {
|
|
1558
|
+
async function waitForCompletedShardAddress(input, index, signal) {
|
|
1388
1559
|
const deadline = Date.now() + LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS;
|
|
1389
1560
|
for (; ; ) {
|
|
1390
|
-
const address = await getCompletedShardAddress(input, index);
|
|
1561
|
+
const address = await getCompletedShardAddress(input, index, signal);
|
|
1391
1562
|
if (address !== null) return address;
|
|
1392
1563
|
if (Date.now() >= deadline) {
|
|
1393
1564
|
throw new Error(`LP DKG completed shard ${index} did not become visible`);
|
|
1394
1565
|
}
|
|
1395
|
-
await sleep(LP_DKG_COMPLETED_SHARD_POLL_INTERVAL_MS);
|
|
1566
|
+
await abortable(sleep(LP_DKG_COMPLETED_SHARD_POLL_INTERVAL_MS), signal);
|
|
1396
1567
|
}
|
|
1397
1568
|
}
|
|
1398
|
-
async function getCompletedShardAddress(input, index) {
|
|
1399
|
-
|
|
1569
|
+
async function getCompletedShardAddress(input, index, signal) {
|
|
1570
|
+
signal.throwIfAborted();
|
|
1571
|
+
const position = await abortable(
|
|
1572
|
+
input.client.getPosition(input.lpPositionId, input.auth, { signal }),
|
|
1573
|
+
signal
|
|
1574
|
+
);
|
|
1400
1575
|
return position.shards.find((candidate) => candidate.index === index)?.address ?? null;
|
|
1401
1576
|
}
|
|
1402
|
-
function workerRequest(worker, request2) {
|
|
1577
|
+
function workerRequest(worker, request2, signal) {
|
|
1578
|
+
signal.throwIfAborted();
|
|
1403
1579
|
return new Promise((resolve, reject) => {
|
|
1404
1580
|
let timeoutId;
|
|
1405
1581
|
const onMessage = (event) => {
|
|
@@ -1407,37 +1583,54 @@ function workerRequest(worker, request2) {
|
|
|
1407
1583
|
if (message.id !== request2.id) return;
|
|
1408
1584
|
cleanup();
|
|
1409
1585
|
if (message.type === "error") {
|
|
1410
|
-
reject(
|
|
1586
|
+
reject(lpDkgWorkerFailure(message.error));
|
|
1411
1587
|
} else {
|
|
1412
1588
|
resolve(message);
|
|
1413
1589
|
}
|
|
1414
1590
|
};
|
|
1415
1591
|
const onError = (event) => {
|
|
1416
1592
|
cleanup();
|
|
1417
|
-
reject(new Error(event.message));
|
|
1593
|
+
reject(lpDkgWorkerFailure(new Error(event.message)));
|
|
1594
|
+
};
|
|
1595
|
+
const onAbort = () => {
|
|
1596
|
+
cleanup();
|
|
1597
|
+
reject(signal.reason);
|
|
1418
1598
|
};
|
|
1419
1599
|
const cleanup = () => {
|
|
1600
|
+
signal.removeEventListener("abort", onAbort);
|
|
1420
1601
|
if (timeoutId !== void 0) globalThis.clearTimeout(timeoutId);
|
|
1421
1602
|
worker.removeEventListener("message", onMessage);
|
|
1422
1603
|
worker.removeEventListener("error", onError);
|
|
1423
1604
|
};
|
|
1605
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1424
1606
|
worker.addEventListener("message", onMessage);
|
|
1425
1607
|
worker.addEventListener("error", onError);
|
|
1426
1608
|
timeoutId = globalThis.setTimeout(() => {
|
|
1427
1609
|
cleanup();
|
|
1428
|
-
reject(new Error(LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE));
|
|
1610
|
+
reject(lpDkgWorkerFailure(new Error(LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE)));
|
|
1429
1611
|
}, LP_DKG_WORKER_REQUEST_TIMEOUT_MS);
|
|
1430
1612
|
try {
|
|
1431
1613
|
worker.postMessage(request2);
|
|
1432
1614
|
} catch (error) {
|
|
1433
1615
|
cleanup();
|
|
1434
|
-
reject(
|
|
1616
|
+
reject(lpDkgWorkerFailure(error));
|
|
1435
1617
|
}
|
|
1436
1618
|
});
|
|
1437
1619
|
}
|
|
1438
1620
|
function createWorker(workerFactory) {
|
|
1439
|
-
|
|
1440
|
-
|
|
1621
|
+
try {
|
|
1622
|
+
if (workerFactory !== void 0) return workerFactory();
|
|
1623
|
+
return new Worker(new URL("./dkgWorker.js", import.meta.url), { type: "module" });
|
|
1624
|
+
} catch (error) {
|
|
1625
|
+
throw lpDkgWorkerFailure(error);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
function lpDkgWorkerFailure(cause) {
|
|
1629
|
+
return new LpLifecycleError(
|
|
1630
|
+
"LP_DKG_WORKER_FAILED",
|
|
1631
|
+
cause instanceof Error ? cause.message : typeof cause === "string" ? cause : LP_DKG_WORKER_FAILURE_MESSAGE,
|
|
1632
|
+
{ cause }
|
|
1633
|
+
);
|
|
1441
1634
|
}
|
|
1442
1635
|
function bytesEqual(a, b) {
|
|
1443
1636
|
if (a.byteLength !== b.byteLength) return false;
|
|
@@ -1461,12 +1654,20 @@ function isLpDkgIndexDriftError(error) {
|
|
|
1461
1654
|
function isLpDkgSessionCoordinationError(error) {
|
|
1462
1655
|
return isLpDkgActiveSessionError(error) || isLpDkgIndexDriftError(error);
|
|
1463
1656
|
}
|
|
1464
|
-
function
|
|
1657
|
+
function resolveLpDkgConcurrency(count, requested) {
|
|
1465
1658
|
if (count <= 0) return 0;
|
|
1466
1659
|
const concurrency = requested ?? DEFAULT_LP_DKG_CONCURRENCY;
|
|
1467
1660
|
if (!Number.isFinite(concurrency)) return Math.min(count, DEFAULT_LP_DKG_CONCURRENCY);
|
|
1468
1661
|
return Math.max(1, Math.min(count, MAX_LP_DKG_CONCURRENCY, Math.floor(concurrency)));
|
|
1469
1662
|
}
|
|
1663
|
+
function abortable(promise, signal) {
|
|
1664
|
+
signal.throwIfAborted();
|
|
1665
|
+
return new Promise((resolve, reject) => {
|
|
1666
|
+
const onAbort = () => reject(signal.reason);
|
|
1667
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1668
|
+
void promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1470
1671
|
function sleep(delayMs) {
|
|
1471
1672
|
return new Promise((resolve) => {
|
|
1472
1673
|
globalThis.setTimeout(resolve, delayMs);
|
|
@@ -1534,6 +1735,46 @@ function previewLpWithdrawalPlan(position, args = {}) {
|
|
|
1534
1735
|
})
|
|
1535
1736
|
};
|
|
1536
1737
|
}
|
|
1738
|
+
var dkgAdmissions = /* @__PURE__ */ new WeakMap();
|
|
1739
|
+
var LP_DKG_BUSY_MESSAGE = "LP DKG session capacity is busy; wait for the active batch to finish";
|
|
1740
|
+
var LP_CLIENT_INVALIDATED_MESSAGE = "LP client invalidated by a reconnect capacity conflict; create a new LP lifecycle client and recover positions using their saved Position Codes";
|
|
1741
|
+
function getDkgAdmission(session) {
|
|
1742
|
+
let admission = dkgAdmissions.get(session);
|
|
1743
|
+
if (admission === void 0) {
|
|
1744
|
+
admission = { reservations: /* @__PURE__ */ new Set() };
|
|
1745
|
+
dkgAdmissions.set(session, admission);
|
|
1746
|
+
}
|
|
1747
|
+
while (admission.parent !== void 0) admission = admission.parent;
|
|
1748
|
+
dkgAdmissions.set(session, admission);
|
|
1749
|
+
return admission;
|
|
1750
|
+
}
|
|
1751
|
+
function assertDkgCapacity(reservations) {
|
|
1752
|
+
let workerCount = 0;
|
|
1753
|
+
const positions = /* @__PURE__ */ new Set();
|
|
1754
|
+
for (const reservation of reservations) {
|
|
1755
|
+
workerCount += reservation.workerCount;
|
|
1756
|
+
if (positions.has(reservation.positionId) || workerCount > MAX_LP_DKG_CONCURRENCY) {
|
|
1757
|
+
throw new LpLifecycleError("LP_DKG_BUSY", LP_DKG_BUSY_MESSAGE);
|
|
1758
|
+
}
|
|
1759
|
+
positions.add(reservation.positionId);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
function reserveDkg(session, positionId, workerCount) {
|
|
1763
|
+
const admission = getDkgAdmission(session);
|
|
1764
|
+
const reservation = { positionId, workerCount };
|
|
1765
|
+
assertDkgCapacity([...admission.reservations, reservation]);
|
|
1766
|
+
admission.reservations.add(reservation);
|
|
1767
|
+
return () => getDkgAdmission(session).reservations.delete(reservation);
|
|
1768
|
+
}
|
|
1769
|
+
function transferDkgAdmission(previousSession, nextSession) {
|
|
1770
|
+
const previous = getDkgAdmission(previousSession);
|
|
1771
|
+
const next = getDkgAdmission(nextSession);
|
|
1772
|
+
if (previous === next) return;
|
|
1773
|
+
assertDkgCapacity([...previous.reservations, ...next.reservations]);
|
|
1774
|
+
for (const reservation of previous.reservations) next.reservations.add(reservation);
|
|
1775
|
+
previous.reservations.clear();
|
|
1776
|
+
previous.parent = next;
|
|
1777
|
+
}
|
|
1537
1778
|
var lifecycleClients = /* @__PURE__ */ new WeakMap();
|
|
1538
1779
|
function createLpLifecycleClient(session, runtime = {}) {
|
|
1539
1780
|
const state = {
|
|
@@ -1542,21 +1783,40 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1542
1783
|
redemptions: /* @__PURE__ */ new Map(),
|
|
1543
1784
|
topUps: /* @__PURE__ */ new Map()
|
|
1544
1785
|
};
|
|
1786
|
+
const cancellation = new AbortController();
|
|
1787
|
+
const assertUsable = () => cancellation.signal.throwIfAborted();
|
|
1545
1788
|
let currentSession = session;
|
|
1546
1789
|
const reconnectSession = runtime.reconnectSession === void 0 ? void 0 : async () => {
|
|
1547
1790
|
const nextSession = await runtime.reconnectSession();
|
|
1791
|
+
assertUsable();
|
|
1792
|
+
try {
|
|
1793
|
+
transferDkgAdmission(currentSession, nextSession);
|
|
1794
|
+
} catch (error) {
|
|
1795
|
+
if (error instanceof LpLifecycleError && error.code === "LP_DKG_BUSY") {
|
|
1796
|
+
const invalidated = new LpLifecycleError(
|
|
1797
|
+
"LP_CLIENT_INVALIDATED",
|
|
1798
|
+
LP_CLIENT_INVALIDATED_MESSAGE,
|
|
1799
|
+
{ cause: error }
|
|
1800
|
+
);
|
|
1801
|
+
cancellation.abort(invalidated);
|
|
1802
|
+
throw invalidated;
|
|
1803
|
+
}
|
|
1804
|
+
throw error;
|
|
1805
|
+
}
|
|
1548
1806
|
currentSession = nextSession;
|
|
1549
1807
|
return nextSession;
|
|
1550
1808
|
};
|
|
1551
|
-
const client = runtime.coordinatorClient ?? createLpCoordinatorClient(session, { reconnectSession });
|
|
1809
|
+
const client = runtime.coordinatorClient ?? createLpCoordinatorClient(session, { reconnectSession, signal: cancellation.signal });
|
|
1552
1810
|
const nowMs = runtime.nowMs ?? Date.now;
|
|
1553
1811
|
const sleep2 = runtime.sleep ?? defaultSleep;
|
|
1554
1812
|
const requireAuth = (positionId) => {
|
|
1813
|
+
assertUsable();
|
|
1555
1814
|
const auth = state.authByPosition.get(positionId);
|
|
1556
1815
|
if (auth === void 0) throw new LpPositionAuthMissingError();
|
|
1557
1816
|
return auth;
|
|
1558
1817
|
};
|
|
1559
1818
|
const rememberPosition = (position) => {
|
|
1819
|
+
assertUsable();
|
|
1560
1820
|
validateLpPositionFeePolicy(position, state.positions.get(position.id));
|
|
1561
1821
|
const snapshot = clonePosition(position);
|
|
1562
1822
|
const previous = state.positions.get(snapshot.id);
|
|
@@ -1573,6 +1833,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1573
1833
|
return merged;
|
|
1574
1834
|
};
|
|
1575
1835
|
const rememberAuth = (auth) => {
|
|
1836
|
+
assertUsable();
|
|
1576
1837
|
state.authByPosition.set(auth.lpPositionId, auth);
|
|
1577
1838
|
};
|
|
1578
1839
|
const refreshPosition2 = async (positionId) => {
|
|
@@ -1593,7 +1854,8 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1593
1854
|
}
|
|
1594
1855
|
}
|
|
1595
1856
|
};
|
|
1596
|
-
const completeDkgBatch2 = async (positionId, options = {}) => {
|
|
1857
|
+
const completeDkgBatch2 = async (positionId, options = {}, hasReservation = false) => {
|
|
1858
|
+
assertUsable();
|
|
1597
1859
|
assertAttested(currentSession);
|
|
1598
1860
|
const auth = requireAuth(positionId);
|
|
1599
1861
|
let activeSessionRetryStartedAtMs = null;
|
|
@@ -1603,10 +1865,16 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1603
1865
|
const startIndex = current.shards.length;
|
|
1604
1866
|
const remaining = Math.min(current.targetShardCount - startIndex, LP_MAX_INITIAL_SHARDS);
|
|
1605
1867
|
if (remaining <= 0) return current;
|
|
1606
|
-
|
|
1868
|
+
const release = hasReservation ? () => void 0 : reserveDkg(
|
|
1869
|
+
currentSession,
|
|
1870
|
+
positionId,
|
|
1871
|
+
runtime.useDeterministicTestAddresses === true ? 0 : resolveLpDkgConcurrency(remaining, options.concurrency ?? runtime.dkgConcurrency)
|
|
1872
|
+
);
|
|
1607
1873
|
let expectedAddresses = null;
|
|
1608
1874
|
try {
|
|
1875
|
+
emitDkgProgress(options, current, startIndex, remaining, 0);
|
|
1609
1876
|
const addresses = await createLpDkgBatch({
|
|
1877
|
+
signal: cancellation.signal,
|
|
1610
1878
|
lpPositionId: positionId,
|
|
1611
1879
|
startIndex,
|
|
1612
1880
|
count: remaining,
|
|
@@ -1619,6 +1887,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1619
1887
|
emitDkgProgress(options, current, startIndex, remaining, progress.completed);
|
|
1620
1888
|
}
|
|
1621
1889
|
});
|
|
1890
|
+
assertUsable();
|
|
1622
1891
|
expectedAddresses = addresses;
|
|
1623
1892
|
const position = await client.finalizeDkgBatch(
|
|
1624
1893
|
{
|
|
@@ -1635,6 +1904,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1635
1904
|
if (position.shards.length < position.targetShardCount) continue;
|
|
1636
1905
|
return position;
|
|
1637
1906
|
} catch (error) {
|
|
1907
|
+
assertUsable();
|
|
1638
1908
|
const reconciled = await tryRefreshCompletedDkgWindow({
|
|
1639
1909
|
client,
|
|
1640
1910
|
positionId,
|
|
@@ -1656,11 +1926,14 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1656
1926
|
throw error;
|
|
1657
1927
|
}
|
|
1658
1928
|
await sleep2(LP_DKG_ACTIVE_SESSION_RETRY_DELAY_MS);
|
|
1929
|
+
} finally {
|
|
1930
|
+
release();
|
|
1659
1931
|
}
|
|
1660
1932
|
}
|
|
1661
1933
|
};
|
|
1662
1934
|
return {
|
|
1663
1935
|
async createPosition(args) {
|
|
1936
|
+
assertUsable();
|
|
1664
1937
|
assertNoUnsupportedFeePolicy(args.feePolicy);
|
|
1665
1938
|
const shardCount = args.shardCount ?? LP_DEFAULT_TARGET_SHARDS;
|
|
1666
1939
|
assertShardCount(shardCount, LP_MAX_INITIAL_SHARDS, "shardCount");
|
|
@@ -1702,6 +1975,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1702
1975
|
return { positionId, lpPositionCode: auth.code, position };
|
|
1703
1976
|
},
|
|
1704
1977
|
async recoverPosition(args) {
|
|
1978
|
+
assertUsable();
|
|
1705
1979
|
const auth = await deriveLpPositionCodeAuth(args.code);
|
|
1706
1980
|
rememberAuth(auth);
|
|
1707
1981
|
const position = rememberPosition(
|
|
@@ -1714,11 +1988,13 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1714
1988
|
return position;
|
|
1715
1989
|
},
|
|
1716
1990
|
confirmPositionCodeSaved(_positionId) {
|
|
1991
|
+
assertUsable();
|
|
1717
1992
|
return;
|
|
1718
1993
|
},
|
|
1719
1994
|
completeDkgBatch: completeDkgBatch2,
|
|
1720
1995
|
refreshPosition: refreshPosition2,
|
|
1721
1996
|
async refill(positionId, args = {}) {
|
|
1997
|
+
assertUsable();
|
|
1722
1998
|
const requestedShardCount = args.shardCount ?? LP_DEFAULT_REFILL_BATCH_SIZE;
|
|
1723
1999
|
assertShardCount(requestedShardCount, LP_MAX_REFILL_BATCH_SIZE, "shardCount");
|
|
1724
2000
|
assertAttested(currentSession);
|
|
@@ -1726,29 +2002,44 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1726
2002
|
const current = await refreshPosition2(positionId);
|
|
1727
2003
|
args.onPosition?.(current);
|
|
1728
2004
|
const refillShardCount = resolveLpRefillShardCount(current, requestedShardCount);
|
|
1729
|
-
const
|
|
1730
|
-
|
|
2005
|
+
const release = reserveDkg(
|
|
2006
|
+
currentSession,
|
|
2007
|
+
positionId,
|
|
2008
|
+
runtime.useDeterministicTestAddresses === true ? 0 : resolveLpDkgConcurrency(refillShardCount, runtime.dkgConcurrency)
|
|
2009
|
+
);
|
|
2010
|
+
try {
|
|
2011
|
+
const authorizedPosition = rememberPosition(
|
|
2012
|
+
await client.refillPosition(
|
|
2013
|
+
{
|
|
2014
|
+
lpPositionId: positionId,
|
|
2015
|
+
shardCount: refillShardCount,
|
|
2016
|
+
shardAmountLamports: DEFAULT_SHARD_FUNDING_LAMPORTS,
|
|
2017
|
+
addresses: [],
|
|
2018
|
+
authorizedAtMs: nowMs()
|
|
2019
|
+
},
|
|
2020
|
+
auth
|
|
2021
|
+
)
|
|
2022
|
+
);
|
|
2023
|
+
args.onPosition?.(authorizedPosition);
|
|
2024
|
+
if (authorizedPosition.shards.length >= authorizedPosition.targetShardCount) {
|
|
2025
|
+
return authorizedPosition;
|
|
2026
|
+
}
|
|
2027
|
+
return await completeDkgBatch2(
|
|
2028
|
+
positionId,
|
|
1731
2029
|
{
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
authorizedAtMs: nowMs()
|
|
2030
|
+
onProgress: args.onProgress,
|
|
2031
|
+
onPosition: args.onPosition,
|
|
2032
|
+
workerFactory: args.workerFactory,
|
|
2033
|
+
concurrency: resolveLpDkgConcurrency(refillShardCount, runtime.dkgConcurrency)
|
|
1737
2034
|
},
|
|
1738
|
-
|
|
1739
|
-
)
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
if (authorizedPosition.shards.length >= authorizedPosition.targetShardCount) {
|
|
1743
|
-
return authorizedPosition;
|
|
2035
|
+
true
|
|
2036
|
+
);
|
|
2037
|
+
} finally {
|
|
2038
|
+
release();
|
|
1744
2039
|
}
|
|
1745
|
-
return completeDkgBatch2(positionId, {
|
|
1746
|
-
onProgress: args.onProgress,
|
|
1747
|
-
onPosition: args.onPosition,
|
|
1748
|
-
workerFactory: args.workerFactory
|
|
1749
|
-
});
|
|
1750
2040
|
},
|
|
1751
2041
|
async prepareInitialFunding(positionId) {
|
|
2042
|
+
assertUsable();
|
|
1752
2043
|
assertAttested(currentSession);
|
|
1753
2044
|
const auth = requireAuth(positionId);
|
|
1754
2045
|
const currentPosition = rememberPosition(await client.getPosition(positionId, auth));
|
|
@@ -1778,6 +2069,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1778
2069
|
return fundingPlanFromShard(position, plannedShard);
|
|
1779
2070
|
},
|
|
1780
2071
|
async prepareTopUp(positionId) {
|
|
2072
|
+
assertUsable();
|
|
1781
2073
|
assertAttested(currentSession);
|
|
1782
2074
|
const auth = requireAuth(positionId);
|
|
1783
2075
|
const request2 = await client.prepareTopUp(positionId, auth);
|
|
@@ -1785,6 +2077,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1785
2077
|
return request2;
|
|
1786
2078
|
},
|
|
1787
2079
|
async waitForTopUp(topUpId, options = {}) {
|
|
2080
|
+
assertUsable();
|
|
1788
2081
|
const cached = state.topUps.get(topUpId);
|
|
1789
2082
|
if (cached !== void 0 && options.positionId !== void 0 && cached.positionId !== options.positionId) {
|
|
1790
2083
|
throw new PolicyValidationError(
|
|
@@ -1826,11 +2119,13 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1826
2119
|
}
|
|
1827
2120
|
},
|
|
1828
2121
|
async reconcileFunding(positionId) {
|
|
2122
|
+
assertUsable();
|
|
1829
2123
|
assertAttested(currentSession);
|
|
1830
2124
|
const auth = requireAuth(positionId);
|
|
1831
2125
|
return rememberPosition(await client.reconcileFunding(positionId, auth));
|
|
1832
2126
|
},
|
|
1833
2127
|
async withdrawPosition(positionId, args) {
|
|
2128
|
+
assertUsable();
|
|
1834
2129
|
validateExplicitWithdrawalInput(args);
|
|
1835
2130
|
validateWithdrawalDestinations(args);
|
|
1836
2131
|
assertAttested(currentSession);
|
|
@@ -1923,6 +2218,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1923
2218
|
return { execution, position, redemption };
|
|
1924
2219
|
},
|
|
1925
2220
|
async waitForWithdrawalConfirmation(positionId, execution, options = {}) {
|
|
2221
|
+
assertUsable();
|
|
1926
2222
|
const auth = requireAuth(positionId);
|
|
1927
2223
|
let record = resolveWithdrawalRecord({
|
|
1928
2224
|
state,
|
|
@@ -1979,6 +2275,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1979
2275
|
}
|
|
1980
2276
|
},
|
|
1981
2277
|
async withdrawFees(_positionId, args) {
|
|
2278
|
+
assertUsable();
|
|
1982
2279
|
publicKey(args.destination);
|
|
1983
2280
|
assertAttested(currentSession);
|
|
1984
2281
|
throw new RoutingError(
|
|
@@ -1987,6 +2284,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1987
2284
|
);
|
|
1988
2285
|
},
|
|
1989
2286
|
async listPositions() {
|
|
2287
|
+
assertUsable();
|
|
1990
2288
|
return [...state.positions.values()].map(clonePosition);
|
|
1991
2289
|
}
|
|
1992
2290
|
};
|