@invisible-labs/sdk 0.9.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 +25 -5
- package/dist/.invisible-sdk-build-target.json +2 -2
- 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-EOPZVOVP.js → chunk-LVCDODTN.js} +582 -19
- package/dist/chunk-LVCDODTN.js.map +1 -0
- package/dist/{chunk-QF5TSUQE.js → chunk-M45APS7S.js} +405 -51
- package/dist/chunk-M45APS7S.js.map +1 -0
- package/dist/{chunk-ISIWWGSR.js → chunk-NOKBFHDP.js} +5 -5
- package/dist/{chunk-ISIWWGSR.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-EQEL23A3.js +4 -0
- package/dist/{coordinator-DHL3AP7V.js.map → coordinator-EQEL23A3.js.map} +1 -1
- package/dist/events.js +3 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/lp.d.ts +46 -5
- package/dist/lp.js +675 -212
- package/dist/lp.js.map +1 -1
- package/dist/stats.js +1 -1
- package/dist/storage.js +2 -2
- package/dist/{types.generated-DrM2M4DZ.d.ts → types.generated-BpbFQlYB.d.ts} +75 -1
- package/dist/user.d.ts +9 -4
- package/dist/user.js +53 -22
- package/dist/user.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-EOPZVOVP.js.map +0 -1
- package/dist/chunk-QF5TSUQE.js.map +0 -1
- package/dist/chunk-RWKG7N7I.js.map +0 -1
- package/dist/coordinator-DHL3AP7V.js +0 -4
package/dist/lp.js
CHANGED
|
@@ -1,10 +1,104 @@
|
|
|
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
|
+
// src/lp/actorSync.ts
|
|
9
|
+
function normalizeLpActorSync(sync) {
|
|
10
|
+
const total = sync.totalNetFundsLamports;
|
|
11
|
+
if (total === void 0) return sync;
|
|
12
|
+
const available = sync.redeemablePrincipalLamports + sync.redeemableFeeLamports;
|
|
13
|
+
if (sync.redeemableProjectionAvailable === true && Number.isSafeInteger(total) && total >= 0 && Number.isSafeInteger(sync.redeemablePrincipalLamports) && sync.redeemablePrincipalLamports >= 0 && Number.isSafeInteger(sync.redeemableFeeLamports) && sync.redeemableFeeLamports >= 0 && Number.isSafeInteger(available) && available >= 0 && total >= available) {
|
|
14
|
+
return sync;
|
|
15
|
+
}
|
|
16
|
+
return { ...sync, totalNetFundsLamports: void 0 };
|
|
17
|
+
}
|
|
18
|
+
function mergeLpActorSync(previous, next) {
|
|
19
|
+
if (next === void 0) return void 0;
|
|
20
|
+
if (previous?.lpPositionId === next.lpPositionId && (next.stateVersion < previous.stateVersion || next.stateVersion === previous.stateVersion && next.updatedAtMs < previous.updatedAtMs)) {
|
|
21
|
+
return normalizeLpActorSync(previous);
|
|
22
|
+
}
|
|
23
|
+
return normalizeLpActorSync(next);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/lp/feePolicy.ts
|
|
27
|
+
var LP_FEE_POLICY_VERSION = 1;
|
|
28
|
+
var LP_PARTNER_COMMISSION_BPS = 6e3;
|
|
29
|
+
var LP_BASIS_POINT_DENOMINATOR = 10000n;
|
|
30
|
+
var LP_FEE_POLICY_HASHES = {
|
|
31
|
+
internal: "53479c39d822899c0abe21990aeff40ea74681277b2744ef86234152cc94ca5a",
|
|
32
|
+
partner: "3e1a307504043bc0b25f03ccffdff1b42cd2b38699f000f7eb70ce9433a5b2a7"
|
|
33
|
+
};
|
|
34
|
+
var LP_ECONOMIC_UNSIGNED_PATTERN = /^(0|[1-9][0-9]*)$/;
|
|
35
|
+
var LP_ECONOMIC_SIGNED_PATTERN = /^(0|-?[1-9][0-9]*)$/;
|
|
36
|
+
var LP_ECONOMIC_UNSIGNED_MAX = (1n << 128n) - 1n;
|
|
37
|
+
var LP_ECONOMIC_SIGNED_MIN = -(1n << 127n);
|
|
38
|
+
var LP_ECONOMIC_SIGNED_MAX = (1n << 127n) - 1n;
|
|
39
|
+
var LP_FEE_POLICY_INVALID_MESSAGE = "Coordinator LP fee policy evidence is missing or invalid";
|
|
40
|
+
function validateLpFeePolicy(value) {
|
|
41
|
+
if (typeof value !== "object" || value === null) {
|
|
42
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
43
|
+
}
|
|
44
|
+
const policy = value;
|
|
45
|
+
if (policy.version !== LP_FEE_POLICY_VERSION || policy.profile !== "internal" && policy.profile !== "partner" || policy.commission_bps !== (policy.profile === "partner" ? LP_PARTNER_COMMISSION_BPS : 0) || typeof policy.policy_hash !== "string" || policy.policy_hash !== LP_FEE_POLICY_HASHES[policy.profile]) {
|
|
46
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
version: LP_FEE_POLICY_VERSION,
|
|
50
|
+
profile: policy.profile,
|
|
51
|
+
commission_bps: policy.profile === "partner" ? LP_PARTNER_COMMISSION_BPS : 0,
|
|
52
|
+
policy_hash: policy.policy_hash
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function requireLpFeePolicyCapability(version) {
|
|
56
|
+
if (version !== LP_FEE_POLICY_VERSION) {
|
|
57
|
+
throw new RoutingError(
|
|
58
|
+
"VERSION_NOT_SUPPORTED",
|
|
59
|
+
"Coordinator does not support the LP fee policy contract"
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function validateLpPositionFeePolicy(position, previous) {
|
|
64
|
+
if (position.feePolicy === void 0) {
|
|
65
|
+
if (previous?.feePolicy !== void 0 || position.actorSync?.feePolicy !== void 0 || position.actorSync?.feeBasisRevision !== void 0 || position.actorSync?.grossFeeLamports !== void 0 || position.actorSync?.protocolCommissionLamports !== void 0 || position.actorSync?.waivedProtocolCommissionLamports !== void 0) {
|
|
66
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
requireLpFeePolicyCapability(position.lpFeePolicyVersion);
|
|
71
|
+
const policy = validateLpFeePolicy(position.feePolicy);
|
|
72
|
+
const sync = position.actorSync;
|
|
73
|
+
const actorPolicy = validateLpFeePolicy(sync?.feePolicy);
|
|
74
|
+
if (JSON.stringify(policy) !== JSON.stringify(actorPolicy) || previous !== void 0 && (previous.feePolicy === void 0 || JSON.stringify(policy) !== JSON.stringify(validateLpFeePolicy(previous.feePolicy))) || sync?.lpPositionId !== position.id || sync?.redeemableProjectionAvailable !== true || !Number.isSafeInteger(sync.feeBasisRevision) || sync.feeBasisRevision < 0 || !Number.isSafeInteger(sync.grossFeeLamports) || sync.grossFeeLamports < 0 || !Number.isSafeInteger(sync.protocolCommissionLamports) || sync.protocolCommissionLamports < 0 || !Number.isSafeInteger(sync.waivedProtocolCommissionLamports) || sync.waivedProtocolCommissionLamports < 0 || sync.economicReturn === void 0) {
|
|
75
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
76
|
+
}
|
|
77
|
+
if (BigInt(sync.protocolCommissionLamports) + BigInt(sync.waivedProtocolCommissionLamports) !== BigInt(sync.grossFeeLamports) * BigInt(policy.commission_bps) / LP_BASIS_POINT_DENOMINATOR) {
|
|
78
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
79
|
+
}
|
|
80
|
+
for (const history of sync.redemptionHistory ?? []) {
|
|
81
|
+
if (history.feePolicyHash !== policy.policy_hash || !Number.isSafeInteger(history.feeBasisRevision) || history.feeBasisRevision < 0) {
|
|
82
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const summary = sync.economicReturn;
|
|
86
|
+
const totals = [
|
|
87
|
+
summary.providerRewardLamports,
|
|
88
|
+
summary.sourceExpenseCompensationLamports,
|
|
89
|
+
summary.chargedReimbursementLossLamports
|
|
90
|
+
];
|
|
91
|
+
if (!totals.every(
|
|
92
|
+
(value) => typeof value === "string" && LP_ECONOMIC_UNSIGNED_PATTERN.test(value) && BigInt(value) <= LP_ECONOMIC_UNSIGNED_MAX
|
|
93
|
+
) || typeof summary.netEconomicReturnLamports !== "string" || !LP_ECONOMIC_SIGNED_PATTERN.test(summary.netEconomicReturnLamports)) {
|
|
94
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
95
|
+
}
|
|
96
|
+
const net = BigInt(summary.netEconomicReturnLamports);
|
|
97
|
+
if (net < LP_ECONOMIC_SIGNED_MIN || net > LP_ECONOMIC_SIGNED_MAX || net !== BigInt(summary.providerRewardLamports) - BigInt(summary.chargedReimbursementLossLamports) - BigInt(sync.protocolCommissionLamports)) {
|
|
98
|
+
throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
8
102
|
// src/lp/positionCode.ts
|
|
9
103
|
var LEGACY_CODE_PREFIX = "ilp1";
|
|
10
104
|
var CODE_PREFIX = "ilp2";
|
|
@@ -235,6 +329,7 @@ var LP_POSITION_HYDRATION_TIMEOUT_MS = LP_COMMAND_REQUEST_TIMEOUT_MS;
|
|
|
235
329
|
var LP_POSITION_SNAPSHOT_MAX_ATTEMPTS = 3;
|
|
236
330
|
var LP_SHARD_SNAPSHOT_CHANGED_MESSAGE = "LP shard snapshot changed";
|
|
237
331
|
var LP_SHARD_PAGE_INVALID_MESSAGE = "coordinator LP shard page is invalid";
|
|
332
|
+
var LP_POSITION_OPEN_IDENTITY_MISMATCH_MESSAGE = "Coordinator returned a different LP position identity or creation intent";
|
|
238
333
|
var LP_SHARD_SNAPSHOT_HASH_PATTERN = /^[0-9a-f]{64}$/;
|
|
239
334
|
var LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS = 3e4;
|
|
240
335
|
var LP_CREATION_WALLET_SIGNATURE_TIMEOUT_MS = 45e3;
|
|
@@ -248,62 +343,108 @@ var protocolPromise = null;
|
|
|
248
343
|
function createLpCoordinatorClient(session, options = {}) {
|
|
249
344
|
const sessionRef = { current: session };
|
|
250
345
|
const reconnectSession = options.reconnectSession === void 0 ? void 0 : async () => {
|
|
346
|
+
options.signal?.throwIfAborted();
|
|
251
347
|
const nextSession = await options.reconnectSession();
|
|
348
|
+
options.signal?.throwIfAborted();
|
|
252
349
|
sessionRef.current = nextSession;
|
|
253
350
|
return nextSession;
|
|
254
351
|
};
|
|
352
|
+
const run = (operation, signal) => withLpClientSignal(options.signal, signal, operation);
|
|
255
353
|
return {
|
|
256
354
|
authorizePositionCreation(intent, signer) {
|
|
257
|
-
return authorizePositionCreation(sessionRef.current, intent, signer);
|
|
355
|
+
return run((signal) => authorizePositionCreation(sessionRef.current, intent, signer, signal));
|
|
258
356
|
},
|
|
259
|
-
initDkg(input, auth) {
|
|
260
|
-
return initDkg(sessionRef.current, input, auth);
|
|
357
|
+
initDkg(input, auth, options2) {
|
|
358
|
+
return run((signal) => initDkg(sessionRef.current, input, auth, { signal }), options2?.signal);
|
|
261
359
|
},
|
|
262
360
|
abortDkgSessions(lpPositionId, auth) {
|
|
263
361
|
return abortDkgSessions(sessionRef.current, lpPositionId, auth);
|
|
264
362
|
},
|
|
265
|
-
dkgRound1(input, auth) {
|
|
266
|
-
return
|
|
363
|
+
dkgRound1(input, auth, options2) {
|
|
364
|
+
return run(
|
|
365
|
+
(signal) => dkgRound1(sessionRef.current, input, auth, { signal }),
|
|
366
|
+
options2?.signal
|
|
367
|
+
);
|
|
267
368
|
},
|
|
268
|
-
dkgRound2(input, auth) {
|
|
269
|
-
return
|
|
369
|
+
dkgRound2(input, auth, options2) {
|
|
370
|
+
return run(
|
|
371
|
+
(signal) => dkgRound2(sessionRef.current, input, auth, { signal }),
|
|
372
|
+
options2?.signal
|
|
373
|
+
);
|
|
270
374
|
},
|
|
271
375
|
openPosition(input, auth) {
|
|
272
|
-
return
|
|
376
|
+
return run(
|
|
377
|
+
(signal) => openPosition(sessionRef.current, input, auth, reconnectSession, signal)
|
|
378
|
+
);
|
|
273
379
|
},
|
|
274
380
|
getPosition(lpPositionId, auth, options2) {
|
|
275
|
-
return
|
|
381
|
+
return run(
|
|
382
|
+
(signal) => getPosition(sessionRef.current, lpPositionId, auth, { ...options2, signal }),
|
|
383
|
+
options2?.signal
|
|
384
|
+
);
|
|
276
385
|
},
|
|
277
386
|
finalizeDkgBatch(input, auth) {
|
|
278
|
-
return finalizeDkgBatch(sessionRef.current, input, auth);
|
|
387
|
+
return run((signal) => finalizeDkgBatch(sessionRef.current, input, auth, { signal }));
|
|
279
388
|
},
|
|
280
389
|
refillPosition(input, auth) {
|
|
281
|
-
return refillPosition(sessionRef.current, input, auth);
|
|
390
|
+
return run((signal) => refillPosition(sessionRef.current, input, auth, { signal }));
|
|
282
391
|
},
|
|
283
392
|
reconcileFunding(lpPositionId, auth) {
|
|
284
|
-
return reconcileFunding(sessionRef.current, lpPositionId, auth);
|
|
393
|
+
return run((signal) => reconcileFunding(sessionRef.current, lpPositionId, auth, { signal }));
|
|
285
394
|
},
|
|
286
395
|
planFunding(input, auth) {
|
|
287
|
-
return planFunding(sessionRef.current, input, auth);
|
|
396
|
+
return run((signal) => planFunding(sessionRef.current, input, auth, { signal }));
|
|
288
397
|
},
|
|
289
398
|
confirmFunding(input, auth) {
|
|
290
|
-
return confirmFunding(sessionRef.current, input, auth);
|
|
399
|
+
return run((signal) => confirmFunding(sessionRef.current, input, auth, { signal }));
|
|
291
400
|
},
|
|
292
401
|
prepareTopUp(lpPositionId, auth) {
|
|
293
|
-
return prepareTopUp(sessionRef.current, lpPositionId, auth);
|
|
402
|
+
return run((signal) => prepareTopUp(sessionRef.current, lpPositionId, auth, { signal }));
|
|
294
403
|
},
|
|
295
404
|
getTopUpStatus(input, auth) {
|
|
296
|
-
return getTopUpStatus(sessionRef.current, input, auth);
|
|
405
|
+
return run((signal) => getTopUpStatus(sessionRef.current, input, auth, { signal }));
|
|
297
406
|
},
|
|
298
407
|
makeAvailable(input, auth) {
|
|
299
|
-
return makeAvailable(sessionRef.current, input, auth);
|
|
408
|
+
return run((signal) => makeAvailable(sessionRef.current, input, auth, { signal }));
|
|
300
409
|
},
|
|
301
410
|
executeWithdrawal(input, auth) {
|
|
302
|
-
return executeWithdrawal(sessionRef.current, input, auth);
|
|
411
|
+
return run((signal) => executeWithdrawal(sessionRef.current, input, auth, { signal }));
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
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;
|
|
303
425
|
}
|
|
304
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
|
+
}
|
|
305
446
|
}
|
|
306
|
-
async function authorizePositionCreation(session, intent, signer) {
|
|
447
|
+
async function authorizePositionCreation(session, intent, signer, signal) {
|
|
307
448
|
const signerPublicKey = publicKey(signer.publicKey);
|
|
308
449
|
const challengeRequestStartedAtMs = Date.now();
|
|
309
450
|
const challengeEnvelope = await requestEnvelope(
|
|
@@ -321,7 +462,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
321
462
|
}
|
|
322
463
|
}
|
|
323
464
|
},
|
|
324
|
-
{ timeoutMs: LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS }
|
|
465
|
+
{ timeoutMs: LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS, signal }
|
|
325
466
|
);
|
|
326
467
|
const challenge = challengeEnvelope.payload;
|
|
327
468
|
if (challenge.case !== "challenge") {
|
|
@@ -330,6 +471,16 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
330
471
|
"Coordinator returned an unexpected LP creation authorization response"
|
|
331
472
|
);
|
|
332
473
|
}
|
|
474
|
+
requireLpFeePolicyCapability(challenge.value.lp_fee_policy_version);
|
|
475
|
+
const feePolicy = validateLpFeePolicy(challenge.value.fee_policy);
|
|
476
|
+
const consentLine = `LP Fee Policy: ${feePolicy.policy_hash}`;
|
|
477
|
+
const policyResource = `&fee_policy_hash=${feePolicy.policy_hash}&fee_policy_version=${feePolicy.version}`;
|
|
478
|
+
if (!challenge.value.message.split("\n").includes(consentLine) || !challenge.value.message.includes(policyResource)) {
|
|
479
|
+
throw new CommandError(
|
|
480
|
+
"REJECTED_STATE",
|
|
481
|
+
"Coordinator LP creation challenge does not bind the authorized fee policy"
|
|
482
|
+
);
|
|
483
|
+
}
|
|
333
484
|
const localAuthorizationDeadlineMs = challengeRequestStartedAtMs + challenge.value.valid_for_ms;
|
|
334
485
|
const walletTimeoutMs = lpCreationAuthorizationStepTimeout(
|
|
335
486
|
localAuthorizationDeadlineMs,
|
|
@@ -367,7 +518,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
367
518
|
session,
|
|
368
519
|
CoordinatorMessageType.LpCreateAuthorization,
|
|
369
520
|
proofPayload,
|
|
370
|
-
{ timeoutMs: proofTimeoutMs }
|
|
521
|
+
{ timeoutMs: proofTimeoutMs, signal }
|
|
371
522
|
);
|
|
372
523
|
} catch (error) {
|
|
373
524
|
if (!isAmbiguousCoordinatorRequestFailure(error)) throw error;
|
|
@@ -380,7 +531,7 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
380
531
|
session,
|
|
381
532
|
CoordinatorMessageType.LpCreateAuthorization,
|
|
382
533
|
proofPayload,
|
|
383
|
-
{ timeoutMs: proofRetryTimeoutMs }
|
|
534
|
+
{ timeoutMs: proofRetryTimeoutMs, signal }
|
|
384
535
|
);
|
|
385
536
|
}
|
|
386
537
|
const authorization = proofEnvelope.payload;
|
|
@@ -401,7 +552,11 @@ async function authorizePositionCreation(session, intent, signer) {
|
|
|
401
552
|
LP_CREATION_AUTHORIZATION_MARGIN_MS,
|
|
402
553
|
LP_CREATION_MIN_STEP_TIMEOUT_MS
|
|
403
554
|
);
|
|
404
|
-
|
|
555
|
+
requireLpFeePolicyCapability(authorization.value.lp_fee_policy_version);
|
|
556
|
+
if (JSON.stringify(validateLpFeePolicy(authorization.value.fee_policy)) !== JSON.stringify(feePolicy)) {
|
|
557
|
+
throw new CommandError("REJECTED_STATE", "Coordinator changed the authorized LP fee policy");
|
|
558
|
+
}
|
|
559
|
+
return { authorizationId: authorization.value.authorization_id, feePolicy };
|
|
405
560
|
}
|
|
406
561
|
function lpCreationAuthorizationStepTimeout(localDeadlineMs, reservedMs, maximumTimeoutMs) {
|
|
407
562
|
const availableMs = localDeadlineMs - Date.now() - reservedMs;
|
|
@@ -433,15 +588,22 @@ async function signLpCreationMessageWithTimeout(signer, message, timeoutMs) {
|
|
|
433
588
|
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
434
589
|
}
|
|
435
590
|
}
|
|
436
|
-
async function initDkg(session, input, auth) {
|
|
437
|
-
const response = await requestForPosition(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
+
);
|
|
441
603
|
if (response.case !== "dkgInit") throw new Error("Unexpected LP DKG init response");
|
|
442
604
|
return { sessionId: response.value.session_id };
|
|
443
605
|
}
|
|
444
|
-
async function abortDkgSessions(session, lpPositionId, auth) {
|
|
606
|
+
async function abortDkgSessions(session, lpPositionId, auth, signal) {
|
|
445
607
|
const response = await requestForPosition(
|
|
446
608
|
session,
|
|
447
609
|
lpPositionId,
|
|
@@ -451,34 +613,46 @@ async function abortDkgSessions(session, lpPositionId, auth) {
|
|
|
451
613
|
case: "dkgAbort",
|
|
452
614
|
value: {}
|
|
453
615
|
},
|
|
454
|
-
{ timeoutMs: LP_DKG_ABORT_REQUEST_TIMEOUT_MS }
|
|
616
|
+
{ timeoutMs: LP_DKG_ABORT_REQUEST_TIMEOUT_MS, signal }
|
|
455
617
|
);
|
|
456
618
|
if (response.case !== "dkgAbort") throw new Error("Unexpected LP DKG abort response");
|
|
457
619
|
return { abortedSessionCount: response.value.aborted_session_count };
|
|
458
620
|
}
|
|
459
|
-
async function dkgRound1(session, input, auth) {
|
|
460
|
-
const response = await request(
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
+
);
|
|
467
635
|
if (response.case !== "dkgRound1") throw new Error("Unexpected LP DKG round1 response");
|
|
468
636
|
return {
|
|
469
637
|
package: response.value.package,
|
|
470
638
|
round2ForLp: response.value.round2_for_lp
|
|
471
639
|
};
|
|
472
640
|
}
|
|
473
|
-
async function dkgRound2(session, input, auth) {
|
|
474
|
-
const response = await request(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
+
);
|
|
482
656
|
if (response.case !== "dkgRound2") throw new Error("Unexpected LP DKG round2 response");
|
|
483
657
|
return {
|
|
484
658
|
address: response.value.address,
|
|
@@ -487,11 +661,12 @@ async function dkgRound2(session, input, auth) {
|
|
|
487
661
|
index: response.value.index
|
|
488
662
|
};
|
|
489
663
|
}
|
|
490
|
-
async function openPosition(session, input, auth, reconnectSession) {
|
|
664
|
+
async function openPosition(session, input, auth, reconnectSession, signal) {
|
|
491
665
|
const payload = {
|
|
492
666
|
case: "positionOpen",
|
|
493
667
|
value: {
|
|
494
668
|
creation_authorization_id: input.creationAuthorizationId,
|
|
669
|
+
fee_policy: input.feePolicy,
|
|
495
670
|
auth_public_key: Uint8Array.from(input.authPublicKey),
|
|
496
671
|
refill_public_key: Uint8Array.from(input.refillPublicKey),
|
|
497
672
|
redemption_commitment: Uint8Array.from(input.withdrawalCommitment),
|
|
@@ -505,12 +680,14 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
505
680
|
};
|
|
506
681
|
const commandDeadlineMs = Date.now() + LP_POSITION_OPEN_COMMAND_TTL_MS;
|
|
507
682
|
const commandOptions = {
|
|
683
|
+
signal,
|
|
508
684
|
commandNonce: randomBytes(32),
|
|
509
685
|
commandExpiresAtMs: commandDeadlineMs,
|
|
510
686
|
deadlineMs: commandDeadlineMs,
|
|
511
687
|
timeoutMs: LP_POSITION_OPEN_REQUEST_TIMEOUT_MS
|
|
512
688
|
};
|
|
513
689
|
let response;
|
|
690
|
+
let responseSession = session;
|
|
514
691
|
try {
|
|
515
692
|
response = await requestForPosition(
|
|
516
693
|
session,
|
|
@@ -522,19 +699,31 @@ async function openPosition(session, input, auth, reconnectSession) {
|
|
|
522
699
|
);
|
|
523
700
|
} catch (error) {
|
|
524
701
|
if (!isAmbiguousLpPositionOpenFailure(error)) throw error;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
702
|
+
responseSession = reconnectSession === void 0 ? session : await reconnectSessionWithinDeadline(reconnectSession, commandDeadlineMs, signal);
|
|
703
|
+
}
|
|
704
|
+
const position = await hydratePositionResponse(
|
|
705
|
+
responseSession,
|
|
706
|
+
auth.lpPositionId,
|
|
707
|
+
auth,
|
|
708
|
+
response,
|
|
709
|
+
{
|
|
710
|
+
deadlineMs: commandDeadlineMs,
|
|
711
|
+
signal
|
|
712
|
+
}
|
|
713
|
+
);
|
|
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) {
|
|
715
|
+
throw new CommandError("REJECTED_STATE", LP_POSITION_OPEN_IDENTITY_MISMATCH_MESSAGE);
|
|
716
|
+
}
|
|
717
|
+
if (input.feePolicy !== void 0 && position.feePolicy?.policy_hash !== input.feePolicy.policy_hash) {
|
|
718
|
+
throw new CommandError(
|
|
719
|
+
"REJECTED_STATE",
|
|
720
|
+
"Coordinator opened the LP position with a different fee policy"
|
|
533
721
|
);
|
|
534
722
|
}
|
|
535
|
-
return
|
|
723
|
+
return position;
|
|
536
724
|
}
|
|
537
|
-
async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
725
|
+
async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs, signal) {
|
|
726
|
+
signal?.throwIfAborted();
|
|
538
727
|
const remainingMs = deadlineMs - Date.now();
|
|
539
728
|
if (remainingMs <= 0) {
|
|
540
729
|
throw new CommandError(
|
|
@@ -543,8 +732,12 @@ async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
|
543
732
|
);
|
|
544
733
|
}
|
|
545
734
|
let timer;
|
|
735
|
+
let removeAbort;
|
|
546
736
|
try {
|
|
547
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);
|
|
548
741
|
timer = setTimeout(() => {
|
|
549
742
|
reject(
|
|
550
743
|
new CommandError(
|
|
@@ -553,10 +746,14 @@ async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
|
|
|
553
746
|
)
|
|
554
747
|
);
|
|
555
748
|
}, remainingMs);
|
|
556
|
-
Promise.resolve().then(
|
|
749
|
+
Promise.resolve().then(() => {
|
|
750
|
+
signal?.throwIfAborted();
|
|
751
|
+
return reconnectSession();
|
|
752
|
+
}).then(resolve, reject);
|
|
557
753
|
});
|
|
558
754
|
} finally {
|
|
559
755
|
if (timer !== void 0) clearTimeout(timer);
|
|
756
|
+
removeAbort?.();
|
|
560
757
|
}
|
|
561
758
|
}
|
|
562
759
|
function isAmbiguousLpPositionOpenFailure(error) {
|
|
@@ -650,6 +847,7 @@ async function hydratePositionResponse(session, lpPositionId, auth, initialRespo
|
|
|
650
847
|
if (first.shards_snapshot_hash !== void 0)
|
|
651
848
|
assertShardPage(first, historyPage, lpPositionId, auth, 0);
|
|
652
849
|
const historyView = mapPosition(historyPage);
|
|
850
|
+
validateLpPositionFeePolicy(historyView, position);
|
|
653
851
|
const merged = mergePositionHistoryPages(position, historyView);
|
|
654
852
|
position = first.shards_snapshot_hash === void 0 ? merged : {
|
|
655
853
|
...position,
|
|
@@ -677,7 +875,7 @@ function assertShardPage(first, page, lpPositionId, auth, startIndex) {
|
|
|
677
875
|
const invalid = () => {
|
|
678
876
|
throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
|
|
679
877
|
};
|
|
680
|
-
if (total === void 0 || !Number.isInteger(total) || total < 1 || total > LP_MAX_TOTAL_SHARDS || total > first.target_shard_count || first.status !== "dkg_pending" && total !== first.target_shard_count || first.shards_snapshot_hash === void 0 || !LP_SHARD_SNAPSHOT_HASH_PATTERN.test(first.shards_snapshot_hash) || page.lp_position_id !== lpPositionId || page.shards_snapshot_hash !== first.shards_snapshot_hash || page.shards_total_count !== total || page.target_shard_count !== first.target_shard_count || page.status !== "dkg_pending" && total !== page.target_shard_count || page.created_at_ms !== first.created_at_ms || page.committed_lamports !== first.committed_lamports || page.earned_lamports !== first.earned_lamports || page.refill_threshold !== first.refill_threshold || bytesToHex(page.auth_public_key) !== bytesToHex(auth.authPublicKey) || bytesToHex(page.refill_public_key) !== bytesToHex(first.refill_public_key) || bytesToHex(page.redemption_commitment) !== bytesToHex(first.redemption_commitment) || page.shards.length !== Math.min(LP_SHARD_PAGE_SIZE, total - startIndex) || page.shards.length === 0)
|
|
878
|
+
if (total === void 0 || !Number.isInteger(total) || total < 1 || total > LP_MAX_TOTAL_SHARDS || total > first.target_shard_count || first.status !== "dkg_pending" && total !== first.target_shard_count || first.shards_snapshot_hash === void 0 || !LP_SHARD_SNAPSHOT_HASH_PATTERN.test(first.shards_snapshot_hash) || page.lp_position_id !== lpPositionId || page.shards_snapshot_hash !== first.shards_snapshot_hash || page.shards_total_count !== total || page.target_shard_count !== first.target_shard_count || page.status !== "dkg_pending" && total !== page.target_shard_count || page.created_at_ms !== first.created_at_ms || page.committed_lamports !== first.committed_lamports || page.earned_lamports !== first.earned_lamports || page.refill_threshold !== first.refill_threshold || page.fee_policy?.policy_hash !== first.fee_policy?.policy_hash || page.lp_fee_policy_version !== first.lp_fee_policy_version || bytesToHex(page.auth_public_key) !== bytesToHex(auth.authPublicKey) || bytesToHex(page.refill_public_key) !== bytesToHex(first.refill_public_key) || bytesToHex(page.redemption_commitment) !== bytesToHex(first.redemption_commitment) || page.shards.length !== Math.min(LP_SHARD_PAGE_SIZE, total - startIndex) || page.shards.length === 0)
|
|
681
879
|
invalid();
|
|
682
880
|
for (const [offset, shard] of page.shards.entries()) {
|
|
683
881
|
const index = startIndex + offset;
|
|
@@ -703,48 +901,76 @@ function lpPositionPageRequestOptions(options) {
|
|
|
703
901
|
timeoutMs: Math.min(options.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS, remainingMs)
|
|
704
902
|
};
|
|
705
903
|
}
|
|
706
|
-
async function finalizeDkgBatch(session, input, auth) {
|
|
707
|
-
const response = await requestForPosition(
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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);
|
|
716
921
|
}
|
|
717
|
-
async function refillPosition(session, input, auth) {
|
|
718
|
-
const response = await requestForPosition(
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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);
|
|
728
940
|
}
|
|
729
|
-
async function reconcileFunding(session, lpPositionId, auth) {
|
|
730
|
-
const response = await requestForPosition(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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);
|
|
735
954
|
}
|
|
736
|
-
async function planFunding(session, input, auth) {
|
|
737
|
-
const response = await requestForPosition(
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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
|
+
);
|
|
744
970
|
if (response.case !== "shards") throw new Error("Unexpected LP funding plan response");
|
|
745
971
|
return response.value.map(mapShard);
|
|
746
972
|
}
|
|
747
|
-
async function confirmFunding(session, input, auth) {
|
|
973
|
+
async function confirmFunding(session, input, auth, options = {}) {
|
|
748
974
|
const response = await requestForPosition(
|
|
749
975
|
session,
|
|
750
976
|
input.lpPositionId,
|
|
@@ -757,38 +983,60 @@ async function confirmFunding(session, input, auth) {
|
|
|
757
983
|
amount_lamports: input.amountLamports,
|
|
758
984
|
funding_tx_signature: input.fundingTxSignature
|
|
759
985
|
}
|
|
760
|
-
}
|
|
986
|
+
},
|
|
987
|
+
options
|
|
761
988
|
);
|
|
762
989
|
if (response.case !== "shard") throw new Error("Unexpected LP funding confirmation response");
|
|
763
990
|
return mapShard(response.value);
|
|
764
991
|
}
|
|
765
|
-
async function prepareTopUp(session, lpPositionId, auth) {
|
|
766
|
-
const response = await requestForPosition(
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
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
|
+
);
|
|
770
1004
|
if (response.case !== "topUpRequest") throw new Error("Unexpected LP top-up response");
|
|
771
1005
|
return mapTopUpRequest(response.value);
|
|
772
1006
|
}
|
|
773
|
-
async function getTopUpStatus(session, input, auth) {
|
|
774
|
-
const response = await requestForPosition(
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
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
|
+
);
|
|
778
1019
|
if (response.case !== "topUpRequest") throw new Error("Unexpected LP top-up response");
|
|
779
1020
|
return mapTopUpRequest(response.value);
|
|
780
1021
|
}
|
|
781
|
-
async function makeAvailable(session, input, auth) {
|
|
782
|
-
const response = await requestForPosition(
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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
|
+
);
|
|
788
1036
|
if (response.case !== "shard") throw new Error("Unexpected LP availability response");
|
|
789
1037
|
return mapShard(response.value);
|
|
790
1038
|
}
|
|
791
|
-
async function executeWithdrawal(session, input, auth) {
|
|
1039
|
+
async function executeWithdrawal(session, input, auth, options = {}) {
|
|
792
1040
|
validateLpWithdrawalPlan({
|
|
793
1041
|
destinationAddresses: input.destinationAddresses,
|
|
794
1042
|
depositPrincipalLamports: input.withdrawalMode === "max_available" ? 1 : input.depositPrincipalLamports,
|
|
@@ -798,20 +1046,35 @@ async function executeWithdrawal(session, input, auth) {
|
|
|
798
1046
|
// a one-destination request based on an unknown current source count.
|
|
799
1047
|
allowManyToOne: input.withdrawalMode === "max_available" || input.allowManyToOne
|
|
800
1048
|
});
|
|
801
|
-
const response = await requestForPosition(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
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
|
+
);
|
|
811
1068
|
if (response.case !== "withdrawalExecution") {
|
|
812
1069
|
throw new Error("Unexpected LP withdrawal execution response");
|
|
813
1070
|
}
|
|
814
1071
|
const execution = response.value;
|
|
1072
|
+
if (execution.fee_policy_hash !== input.feePolicyHash || execution.fee_basis_revision !== input.feeBasisRevision) {
|
|
1073
|
+
throw new PolicyValidationError(
|
|
1074
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
1075
|
+
"Coordinator accepted a different LP fee policy or fee basis"
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
815
1078
|
if (BigInt(execution.accepted_lamports) !== BigInt(execution.accepted_deposit_principal_lamports) + BigInt(execution.accepted_earned_fee_lamports)) {
|
|
816
1079
|
throw new PolicyValidationError(
|
|
817
1080
|
"INVALID_WITHDRAWAL_PLAN",
|
|
@@ -825,6 +1088,8 @@ async function executeWithdrawal(session, input, auth) {
|
|
|
825
1088
|
);
|
|
826
1089
|
}
|
|
827
1090
|
return {
|
|
1091
|
+
feePolicyHash: execution.fee_policy_hash,
|
|
1092
|
+
feeBasisRevision: execution.fee_basis_revision,
|
|
828
1093
|
withdrawalId: execution.withdrawal_id,
|
|
829
1094
|
txSignatures: [...execution.tx_signatures],
|
|
830
1095
|
acceptedLamports: execution.accepted_lamports,
|
|
@@ -832,13 +1097,15 @@ async function executeWithdrawal(session, input, auth) {
|
|
|
832
1097
|
acceptedEarnedFeeLamports: execution.accepted_earned_fee_lamports
|
|
833
1098
|
};
|
|
834
1099
|
}
|
|
835
|
-
function request(session, auth, action, payload) {
|
|
836
|
-
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);
|
|
837
1102
|
}
|
|
838
1103
|
async function requestForPosition(session, lpPositionId, auth, action, payload, options = {}) {
|
|
1104
|
+
options.signal?.throwIfAborted();
|
|
839
1105
|
const timeoutMs = lpPositionPageRequestOptions(options).timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS;
|
|
840
1106
|
assertAuthMatchesPosition(lpPositionId, auth);
|
|
841
1107
|
const protocol = await loadProtocol();
|
|
1108
|
+
options.signal?.throwIfAborted();
|
|
842
1109
|
const state = getSessionState(session);
|
|
843
1110
|
const attestation = state.channel?.attestation;
|
|
844
1111
|
if (!attestation) {
|
|
@@ -855,7 +1122,9 @@ async function requestForPosition(session, lpPositionId, auth, action, payload,
|
|
|
855
1122
|
),
|
|
856
1123
|
payload
|
|
857
1124
|
};
|
|
1125
|
+
options.signal?.throwIfAborted();
|
|
858
1126
|
const signature = await signLpCommandBytes(auth, protocol.encodeLpCommandForSigning(command));
|
|
1127
|
+
options.signal?.throwIfAborted();
|
|
859
1128
|
const { type, payload: envelopePayload } = protocol.lpSignedCommandEnvelope(command, signature);
|
|
860
1129
|
const requestOptions = lpPositionPageRequestOptions(options);
|
|
861
1130
|
const envelope = await requestEnvelope(session, type, envelopePayload, {
|
|
@@ -872,7 +1141,9 @@ function assertAuthMatchesPosition(lpPositionId, auth) {
|
|
|
872
1141
|
);
|
|
873
1142
|
}
|
|
874
1143
|
function mapPosition(position) {
|
|
875
|
-
|
|
1144
|
+
const mapped = {
|
|
1145
|
+
feePolicy: position.fee_policy === void 0 ? void 0 : validateLpFeePolicy(position.fee_policy),
|
|
1146
|
+
lpFeePolicyVersion: position.lp_fee_policy_version,
|
|
876
1147
|
id: position.lp_position_id,
|
|
877
1148
|
status: position.status,
|
|
878
1149
|
targetShardCount: position.target_shard_count,
|
|
@@ -887,6 +1158,8 @@ function mapPosition(position) {
|
|
|
887
1158
|
redemptionPermission: mapLpRedemptionPermission(position.redemption_permission),
|
|
888
1159
|
...position.actor_sync === void 0 ? {} : { actorSync: mapLpActorSync(position.actor_sync) }
|
|
889
1160
|
};
|
|
1161
|
+
validateLpPositionFeePolicy(mapped);
|
|
1162
|
+
return mapped;
|
|
890
1163
|
}
|
|
891
1164
|
function mapLpRedemptionPermission(permission) {
|
|
892
1165
|
if (permission === void 0) {
|
|
@@ -916,11 +1189,22 @@ function mapLpActorSync(actorSync) {
|
|
|
916
1189
|
);
|
|
917
1190
|
}
|
|
918
1191
|
const redeemableProjectionAvailable = redeemableBucketCount === redeemableBucketValues.length;
|
|
919
|
-
return {
|
|
920
|
-
...actorSync.economic_return === void 0 ? {} : {
|
|
1192
|
+
return normalizeLpActorSync({
|
|
1193
|
+
...actorSync.economic_return === void 0 ? {} : {
|
|
1194
|
+
economicReturn: mapLpEconomicReturn(
|
|
1195
|
+
actorSync.economic_return,
|
|
1196
|
+
actorSync.protocol_commission_lamports ?? 0
|
|
1197
|
+
)
|
|
1198
|
+
},
|
|
1199
|
+
feePolicy: actorSync.fee_policy === void 0 ? void 0 : validateLpFeePolicy(actorSync.fee_policy),
|
|
1200
|
+
feeBasisRevision: actorSync.fee_basis_revision,
|
|
1201
|
+
grossFeeLamports: actorSync.gross_fee_lamports,
|
|
1202
|
+
protocolCommissionLamports: actorSync.protocol_commission_lamports,
|
|
1203
|
+
waivedProtocolCommissionLamports: actorSync.waived_protocol_commission_lamports,
|
|
921
1204
|
lpPositionId: actorSync.lp_position_id,
|
|
922
1205
|
status: actorSync.status,
|
|
923
1206
|
sourceLiquidityUse: actorSync.source_liquidity_use,
|
|
1207
|
+
totalNetFundsLamports: actorSync.total_net_funds_lamports,
|
|
924
1208
|
redeemableProjectionAvailable,
|
|
925
1209
|
redeemablePrincipalLamports: actorSync.redeemable_principal_lamports ?? 0,
|
|
926
1210
|
redeemableFeeLamports: actorSync.redeemable_fee_lamports ?? 0,
|
|
@@ -946,14 +1230,14 @@ function mapLpActorSync(actorSync) {
|
|
|
946
1230
|
...actorSync.redemption_history_next_cursor === void 0 ? {} : { redemptionHistoryNextCursor: actorSync.redemption_history_next_cursor },
|
|
947
1231
|
stateVersion: actorSync.state_version,
|
|
948
1232
|
updatedAtMs: actorSync.updated_at_ms
|
|
949
|
-
};
|
|
1233
|
+
});
|
|
950
1234
|
}
|
|
951
1235
|
var LP_ECONOMIC_UNSIGNED_TOTAL_MAX = (1n << 128n) - 1n;
|
|
952
1236
|
var LP_ECONOMIC_SIGNED_TOTAL_MIN = -(1n << 127n);
|
|
953
1237
|
var LP_ECONOMIC_SIGNED_TOTAL_MAX = (1n << 127n) - 1n;
|
|
954
1238
|
var LP_ECONOMIC_UNSIGNED_DECIMAL = /^(0|[1-9][0-9]*)$/;
|
|
955
1239
|
var LP_ECONOMIC_SIGNED_DECIMAL = /^(0|-?[1-9][0-9]*)$/;
|
|
956
|
-
function mapLpEconomicReturn(summary) {
|
|
1240
|
+
function mapLpEconomicReturn(summary, protocolCommissionLamports) {
|
|
957
1241
|
const unsigned = [
|
|
958
1242
|
summary.provider_reward_lamports,
|
|
959
1243
|
summary.source_expense_compensation_lamports,
|
|
@@ -965,7 +1249,7 @@ function mapLpEconomicReturn(summary) {
|
|
|
965
1249
|
if (!valid)
|
|
966
1250
|
throw new CommandError("REJECTED_STATE", "coordinator LP economic return totals are invalid");
|
|
967
1251
|
const net = BigInt(summary.net_economic_return_lamports);
|
|
968
|
-
if (net < LP_ECONOMIC_SIGNED_TOTAL_MIN || net > LP_ECONOMIC_SIGNED_TOTAL_MAX || net !== BigInt(summary.provider_reward_lamports) - BigInt(summary.charged_reimbursement_loss_lamports)) {
|
|
1252
|
+
if (net < LP_ECONOMIC_SIGNED_TOTAL_MIN || net > LP_ECONOMIC_SIGNED_TOTAL_MAX || net !== BigInt(summary.provider_reward_lamports) - BigInt(summary.charged_reimbursement_loss_lamports) - BigInt(protocolCommissionLamports)) {
|
|
969
1253
|
throw new CommandError("REJECTED_STATE", "coordinator LP economic return invariant is invalid");
|
|
970
1254
|
}
|
|
971
1255
|
return {
|
|
@@ -996,6 +1280,8 @@ function mergePositionHistoryPages(first, next) {
|
|
|
996
1280
|
}
|
|
997
1281
|
function mapLpRedemptionHistory(history) {
|
|
998
1282
|
return {
|
|
1283
|
+
feePolicyHash: history.fee_policy_hash,
|
|
1284
|
+
feeBasisRevision: history.fee_basis_revision,
|
|
999
1285
|
redemptionId: history.redemption_id,
|
|
1000
1286
|
state: history.state,
|
|
1001
1287
|
...history.withdrawal_mode === void 0 ? {} : { withdrawalMode: history.withdrawal_mode },
|
|
@@ -1077,13 +1363,14 @@ function randomBytes(length) {
|
|
|
1077
1363
|
return bytes;
|
|
1078
1364
|
}
|
|
1079
1365
|
function loadProtocol() {
|
|
1080
|
-
protocolPromise ??= import('./coordinator-
|
|
1366
|
+
protocolPromise ??= import('./coordinator-EQEL23A3.js');
|
|
1081
1367
|
return protocolPromise;
|
|
1082
1368
|
}
|
|
1083
1369
|
|
|
1084
1370
|
// src/lp/dkgBatch.ts
|
|
1085
|
-
var MAX_LP_DKG_CONCURRENCY =
|
|
1371
|
+
var MAX_LP_DKG_CONCURRENCY = 16;
|
|
1086
1372
|
var DEFAULT_LP_DKG_CONCURRENCY = MAX_LP_DKG_CONCURRENCY;
|
|
1373
|
+
var LP_DKG_WORKER_FAILURE_MESSAGE = "LP DKG worker failed";
|
|
1087
1374
|
var LP_DKG_WORKER_REQUEST_TIMEOUT_MS = 3e4;
|
|
1088
1375
|
var LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE = "LP DKG worker request timed out";
|
|
1089
1376
|
var LP_DKG_ABORT_CLEANUP_TIMEOUT_MS = 1e4;
|
|
@@ -1093,21 +1380,28 @@ var LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS = 5 * 6e4 + 15e3;
|
|
|
1093
1380
|
var LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS = 2e3;
|
|
1094
1381
|
var LP_DKG_ACTIVE_SESSION_RETRY_TIMEOUT_MS = LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS;
|
|
1095
1382
|
async function createLpDkgBatch(input) {
|
|
1383
|
+
input.signal?.throwIfAborted();
|
|
1096
1384
|
if (input.useDeterministicTestAddresses === true) {
|
|
1097
1385
|
const addresses2 = Array.from(
|
|
1098
1386
|
{ length: input.count },
|
|
1099
1387
|
(_, offset) => testAddress(input.lpPositionId, input.startIndex + offset)
|
|
1100
1388
|
);
|
|
1101
1389
|
for (const [offset, address] of addresses2.entries()) {
|
|
1390
|
+
input.signal?.throwIfAborted();
|
|
1102
1391
|
input.onProgress?.({
|
|
1103
1392
|
completed: offset + 1,
|
|
1104
1393
|
total: input.count,
|
|
1105
1394
|
address
|
|
1106
1395
|
});
|
|
1107
1396
|
}
|
|
1397
|
+
input.signal?.throwIfAborted();
|
|
1108
1398
|
return addresses2;
|
|
1109
1399
|
}
|
|
1110
|
-
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();
|
|
1111
1405
|
const workers = [];
|
|
1112
1406
|
let workersTerminated = false;
|
|
1113
1407
|
const terminateWorkers = () => {
|
|
@@ -1120,16 +1414,19 @@ async function createLpDkgBatch(input) {
|
|
|
1120
1414
|
let nextOffset = 0;
|
|
1121
1415
|
try {
|
|
1122
1416
|
for (let index = 0; index < workerCount; index += 1) {
|
|
1417
|
+
cancellation.signal.throwIfAborted();
|
|
1123
1418
|
workers.push(createWorker(input.workerFactory));
|
|
1124
1419
|
}
|
|
1125
1420
|
await Promise.all(
|
|
1126
1421
|
workers.map(async (worker) => {
|
|
1127
1422
|
for (; ; ) {
|
|
1423
|
+
cancellation.signal.throwIfAborted();
|
|
1128
1424
|
const offset = nextOffset;
|
|
1129
1425
|
nextOffset += 1;
|
|
1130
1426
|
if (offset >= input.count) return;
|
|
1131
1427
|
const index = input.startIndex + offset;
|
|
1132
|
-
const address = await createLpDkgShard(input, worker, index);
|
|
1428
|
+
const address = await createLpDkgShard(input, worker, index, cancellation.signal);
|
|
1429
|
+
cancellation.signal.throwIfAborted();
|
|
1133
1430
|
addresses[offset] = address;
|
|
1134
1431
|
completed += 1;
|
|
1135
1432
|
input.onProgress?.({
|
|
@@ -1142,12 +1439,14 @@ async function createLpDkgBatch(input) {
|
|
|
1142
1439
|
);
|
|
1143
1440
|
return addresses;
|
|
1144
1441
|
} catch (error) {
|
|
1442
|
+
cancellation.abort(error);
|
|
1145
1443
|
terminateWorkers();
|
|
1146
1444
|
if (!isLpDkgSessionCoordinationError(error)) {
|
|
1147
1445
|
await abortDkgSessionsAfterFailure(input);
|
|
1148
1446
|
}
|
|
1149
1447
|
throw error;
|
|
1150
1448
|
} finally {
|
|
1449
|
+
input.signal?.removeEventListener("abort", cancel);
|
|
1151
1450
|
terminateWorkers();
|
|
1152
1451
|
}
|
|
1153
1452
|
}
|
|
@@ -1171,61 +1470,82 @@ async function abortDkgSessionsAfterFailure(input) {
|
|
|
1171
1470
|
if (timeoutId !== void 0) globalThis.clearTimeout(timeoutId);
|
|
1172
1471
|
}
|
|
1173
1472
|
}
|
|
1174
|
-
async function createLpDkgShard(input, worker, index) {
|
|
1473
|
+
async function createLpDkgShard(input, worker, index, signal) {
|
|
1175
1474
|
const deadline = Date.now() + LP_DKG_ACTIVE_SESSION_RETRY_TIMEOUT_MS;
|
|
1176
1475
|
let sawActiveSession = false;
|
|
1177
1476
|
for (; ; ) {
|
|
1178
1477
|
if (sawActiveSession) {
|
|
1179
|
-
const completedAddress = await getCompletedShardAddress(input, index);
|
|
1478
|
+
const completedAddress = await getCompletedShardAddress(input, index, signal);
|
|
1180
1479
|
if (completedAddress !== null) return completedAddress;
|
|
1181
1480
|
}
|
|
1182
1481
|
try {
|
|
1183
|
-
return await runLpDkgShard(input, worker, index);
|
|
1482
|
+
return await runLpDkgShard(input, worker, index, signal);
|
|
1184
1483
|
} catch (error) {
|
|
1185
1484
|
if (isLpDkgCompletedOrVisibleError(error)) {
|
|
1186
|
-
return waitForCompletedShardAddress(input, index);
|
|
1485
|
+
return waitForCompletedShardAddress(input, index, signal);
|
|
1187
1486
|
}
|
|
1188
1487
|
if (!isLpDkgActiveSessionError(error)) throw error;
|
|
1189
1488
|
sawActiveSession = true;
|
|
1190
|
-
const completedAddress = await getCompletedShardAddress(input, index);
|
|
1489
|
+
const completedAddress = await getCompletedShardAddress(input, index, signal);
|
|
1191
1490
|
if (completedAddress !== null) return completedAddress;
|
|
1192
1491
|
if (Date.now() >= deadline) throw error;
|
|
1193
|
-
await sleep(LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS);
|
|
1492
|
+
await abortable(sleep(LP_DKG_ACTIVE_SESSION_RETRY_INTERVAL_MS), signal);
|
|
1194
1493
|
}
|
|
1195
1494
|
}
|
|
1196
1495
|
}
|
|
1197
|
-
async function runLpDkgShard(input, worker, index) {
|
|
1496
|
+
async function runLpDkgShard(input, worker, index, signal) {
|
|
1198
1497
|
const roundId = `lp_dkg_${Date.now()}_${index}_${Math.random().toString(16).slice(2)}`;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
input.auth
|
|
1498
|
+
signal.throwIfAborted();
|
|
1499
|
+
const initResponse = await abortable(
|
|
1500
|
+
input.client.initDkg({ lpPositionId: input.lpPositionId, index }, input.auth, { signal }),
|
|
1501
|
+
signal
|
|
1202
1502
|
);
|
|
1203
|
-
const round1 = await workerRequest(
|
|
1204
|
-
|
|
1205
|
-
type: "round1"
|
|
1206
|
-
});
|
|
1207
|
-
if (round1.type !== "round1") throw new Error("LP DKG worker returned wrong round1 type");
|
|
1208
|
-
const round1Response = await input.client.dkgRound1(
|
|
1503
|
+
const round1 = await workerRequest(
|
|
1504
|
+
worker,
|
|
1209
1505
|
{
|
|
1210
|
-
|
|
1211
|
-
|
|
1506
|
+
id: roundId,
|
|
1507
|
+
type: "round1"
|
|
1212
1508
|
},
|
|
1213
|
-
|
|
1509
|
+
signal
|
|
1214
1510
|
);
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
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,
|
|
1223
1527
|
{
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1528
|
+
id: roundId,
|
|
1529
|
+
type: "round2",
|
|
1530
|
+
teeRound1: Array.from(round1Response.package),
|
|
1531
|
+
teeRound2ForLp: Array.from(round1Response.round2ForLp)
|
|
1227
1532
|
},
|
|
1228
|
-
|
|
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
|
|
1229
1549
|
);
|
|
1230
1550
|
if (!bytesEqual(Uint8Array.from(round2.jointPubkey), round2Response.jointPubkey)) {
|
|
1231
1551
|
throw new Error(`LP DKG joint pubkey mismatch at index ${index}`);
|
|
@@ -1235,22 +1555,27 @@ async function runLpDkgShard(input, worker, index) {
|
|
|
1235
1555
|
}
|
|
1236
1556
|
return round2Response.address;
|
|
1237
1557
|
}
|
|
1238
|
-
async function waitForCompletedShardAddress(input, index) {
|
|
1558
|
+
async function waitForCompletedShardAddress(input, index, signal) {
|
|
1239
1559
|
const deadline = Date.now() + LP_DKG_COMPLETED_SHARD_POLL_TIMEOUT_MS;
|
|
1240
1560
|
for (; ; ) {
|
|
1241
|
-
const address = await getCompletedShardAddress(input, index);
|
|
1561
|
+
const address = await getCompletedShardAddress(input, index, signal);
|
|
1242
1562
|
if (address !== null) return address;
|
|
1243
1563
|
if (Date.now() >= deadline) {
|
|
1244
1564
|
throw new Error(`LP DKG completed shard ${index} did not become visible`);
|
|
1245
1565
|
}
|
|
1246
|
-
await sleep(LP_DKG_COMPLETED_SHARD_POLL_INTERVAL_MS);
|
|
1566
|
+
await abortable(sleep(LP_DKG_COMPLETED_SHARD_POLL_INTERVAL_MS), signal);
|
|
1247
1567
|
}
|
|
1248
1568
|
}
|
|
1249
|
-
async function getCompletedShardAddress(input, index) {
|
|
1250
|
-
|
|
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
|
+
);
|
|
1251
1575
|
return position.shards.find((candidate) => candidate.index === index)?.address ?? null;
|
|
1252
1576
|
}
|
|
1253
|
-
function workerRequest(worker, request2) {
|
|
1577
|
+
function workerRequest(worker, request2, signal) {
|
|
1578
|
+
signal.throwIfAborted();
|
|
1254
1579
|
return new Promise((resolve, reject) => {
|
|
1255
1580
|
let timeoutId;
|
|
1256
1581
|
const onMessage = (event) => {
|
|
@@ -1258,37 +1583,54 @@ function workerRequest(worker, request2) {
|
|
|
1258
1583
|
if (message.id !== request2.id) return;
|
|
1259
1584
|
cleanup();
|
|
1260
1585
|
if (message.type === "error") {
|
|
1261
|
-
reject(
|
|
1586
|
+
reject(lpDkgWorkerFailure(message.error));
|
|
1262
1587
|
} else {
|
|
1263
1588
|
resolve(message);
|
|
1264
1589
|
}
|
|
1265
1590
|
};
|
|
1266
1591
|
const onError = (event) => {
|
|
1267
1592
|
cleanup();
|
|
1268
|
-
reject(new Error(event.message));
|
|
1593
|
+
reject(lpDkgWorkerFailure(new Error(event.message)));
|
|
1594
|
+
};
|
|
1595
|
+
const onAbort = () => {
|
|
1596
|
+
cleanup();
|
|
1597
|
+
reject(signal.reason);
|
|
1269
1598
|
};
|
|
1270
1599
|
const cleanup = () => {
|
|
1600
|
+
signal.removeEventListener("abort", onAbort);
|
|
1271
1601
|
if (timeoutId !== void 0) globalThis.clearTimeout(timeoutId);
|
|
1272
1602
|
worker.removeEventListener("message", onMessage);
|
|
1273
1603
|
worker.removeEventListener("error", onError);
|
|
1274
1604
|
};
|
|
1605
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1275
1606
|
worker.addEventListener("message", onMessage);
|
|
1276
1607
|
worker.addEventListener("error", onError);
|
|
1277
1608
|
timeoutId = globalThis.setTimeout(() => {
|
|
1278
1609
|
cleanup();
|
|
1279
|
-
reject(new Error(LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE));
|
|
1610
|
+
reject(lpDkgWorkerFailure(new Error(LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE)));
|
|
1280
1611
|
}, LP_DKG_WORKER_REQUEST_TIMEOUT_MS);
|
|
1281
1612
|
try {
|
|
1282
1613
|
worker.postMessage(request2);
|
|
1283
1614
|
} catch (error) {
|
|
1284
1615
|
cleanup();
|
|
1285
|
-
reject(
|
|
1616
|
+
reject(lpDkgWorkerFailure(error));
|
|
1286
1617
|
}
|
|
1287
1618
|
});
|
|
1288
1619
|
}
|
|
1289
1620
|
function createWorker(workerFactory) {
|
|
1290
|
-
|
|
1291
|
-
|
|
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
|
+
);
|
|
1292
1634
|
}
|
|
1293
1635
|
function bytesEqual(a, b) {
|
|
1294
1636
|
if (a.byteLength !== b.byteLength) return false;
|
|
@@ -1312,12 +1654,20 @@ function isLpDkgIndexDriftError(error) {
|
|
|
1312
1654
|
function isLpDkgSessionCoordinationError(error) {
|
|
1313
1655
|
return isLpDkgActiveSessionError(error) || isLpDkgIndexDriftError(error);
|
|
1314
1656
|
}
|
|
1315
|
-
function
|
|
1657
|
+
function resolveLpDkgConcurrency(count, requested) {
|
|
1316
1658
|
if (count <= 0) return 0;
|
|
1317
1659
|
const concurrency = requested ?? DEFAULT_LP_DKG_CONCURRENCY;
|
|
1318
1660
|
if (!Number.isFinite(concurrency)) return Math.min(count, DEFAULT_LP_DKG_CONCURRENCY);
|
|
1319
1661
|
return Math.max(1, Math.min(count, MAX_LP_DKG_CONCURRENCY, Math.floor(concurrency)));
|
|
1320
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
|
+
}
|
|
1321
1671
|
function sleep(delayMs) {
|
|
1322
1672
|
return new Promise((resolve) => {
|
|
1323
1673
|
globalThis.setTimeout(resolve, delayMs);
|
|
@@ -1375,6 +1725,7 @@ function isLpPositionAuthMissingError(error) {
|
|
|
1375
1725
|
return error instanceof LpPositionAuthMissingError || error instanceof Error && error.message === LP_MISSING_POSITION_CODE_MESSAGE;
|
|
1376
1726
|
}
|
|
1377
1727
|
function previewLpWithdrawalPlan(position, args = {}) {
|
|
1728
|
+
validateLpPositionFeePolicy(position);
|
|
1378
1729
|
const claim = resolveWithdrawalClaim(position, args);
|
|
1379
1730
|
return {
|
|
1380
1731
|
...claim,
|
|
@@ -1384,6 +1735,46 @@ function previewLpWithdrawalPlan(position, args = {}) {
|
|
|
1384
1735
|
})
|
|
1385
1736
|
};
|
|
1386
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
|
+
}
|
|
1387
1778
|
var lifecycleClients = /* @__PURE__ */ new WeakMap();
|
|
1388
1779
|
function createLpLifecycleClient(session, runtime = {}) {
|
|
1389
1780
|
const state = {
|
|
@@ -1392,26 +1783,47 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1392
1783
|
redemptions: /* @__PURE__ */ new Map(),
|
|
1393
1784
|
topUps: /* @__PURE__ */ new Map()
|
|
1394
1785
|
};
|
|
1786
|
+
const cancellation = new AbortController();
|
|
1787
|
+
const assertUsable = () => cancellation.signal.throwIfAborted();
|
|
1395
1788
|
let currentSession = session;
|
|
1396
1789
|
const reconnectSession = runtime.reconnectSession === void 0 ? void 0 : async () => {
|
|
1397
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
|
+
}
|
|
1398
1806
|
currentSession = nextSession;
|
|
1399
1807
|
return nextSession;
|
|
1400
1808
|
};
|
|
1401
|
-
const client = runtime.coordinatorClient ?? createLpCoordinatorClient(session, { reconnectSession });
|
|
1809
|
+
const client = runtime.coordinatorClient ?? createLpCoordinatorClient(session, { reconnectSession, signal: cancellation.signal });
|
|
1402
1810
|
const nowMs = runtime.nowMs ?? Date.now;
|
|
1403
1811
|
const sleep2 = runtime.sleep ?? defaultSleep;
|
|
1404
1812
|
const requireAuth = (positionId) => {
|
|
1813
|
+
assertUsable();
|
|
1405
1814
|
const auth = state.authByPosition.get(positionId);
|
|
1406
1815
|
if (auth === void 0) throw new LpPositionAuthMissingError();
|
|
1407
1816
|
return auth;
|
|
1408
1817
|
};
|
|
1409
1818
|
const rememberPosition = (position) => {
|
|
1819
|
+
assertUsable();
|
|
1820
|
+
validateLpPositionFeePolicy(position, state.positions.get(position.id));
|
|
1410
1821
|
const snapshot = clonePosition(position);
|
|
1411
1822
|
const previous = state.positions.get(snapshot.id);
|
|
1412
|
-
const merged =
|
|
1823
|
+
const merged = {
|
|
1413
1824
|
...snapshot,
|
|
1414
|
-
|
|
1825
|
+
actorSync: mergeLpActorSync(previous?.actorSync, snapshot.actorSync),
|
|
1826
|
+
redemptionPermission: previous === void 0 ? snapshot.redemptionPermission : mergeLpRedemptionPermission(
|
|
1415
1827
|
previous.redemptionPermission,
|
|
1416
1828
|
snapshot.redemptionPermission
|
|
1417
1829
|
)
|
|
@@ -1421,6 +1833,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1421
1833
|
return merged;
|
|
1422
1834
|
};
|
|
1423
1835
|
const rememberAuth = (auth) => {
|
|
1836
|
+
assertUsable();
|
|
1424
1837
|
state.authByPosition.set(auth.lpPositionId, auth);
|
|
1425
1838
|
};
|
|
1426
1839
|
const refreshPosition2 = async (positionId) => {
|
|
@@ -1441,7 +1854,8 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1441
1854
|
}
|
|
1442
1855
|
}
|
|
1443
1856
|
};
|
|
1444
|
-
const completeDkgBatch2 = async (positionId, options = {}) => {
|
|
1857
|
+
const completeDkgBatch2 = async (positionId, options = {}, hasReservation = false) => {
|
|
1858
|
+
assertUsable();
|
|
1445
1859
|
assertAttested(currentSession);
|
|
1446
1860
|
const auth = requireAuth(positionId);
|
|
1447
1861
|
let activeSessionRetryStartedAtMs = null;
|
|
@@ -1451,10 +1865,16 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1451
1865
|
const startIndex = current.shards.length;
|
|
1452
1866
|
const remaining = Math.min(current.targetShardCount - startIndex, LP_MAX_INITIAL_SHARDS);
|
|
1453
1867
|
if (remaining <= 0) return current;
|
|
1454
|
-
|
|
1868
|
+
const release = hasReservation ? () => void 0 : reserveDkg(
|
|
1869
|
+
currentSession,
|
|
1870
|
+
positionId,
|
|
1871
|
+
runtime.useDeterministicTestAddresses === true ? 0 : resolveLpDkgConcurrency(remaining, options.concurrency ?? runtime.dkgConcurrency)
|
|
1872
|
+
);
|
|
1455
1873
|
let expectedAddresses = null;
|
|
1456
1874
|
try {
|
|
1875
|
+
emitDkgProgress(options, current, startIndex, remaining, 0);
|
|
1457
1876
|
const addresses = await createLpDkgBatch({
|
|
1877
|
+
signal: cancellation.signal,
|
|
1458
1878
|
lpPositionId: positionId,
|
|
1459
1879
|
startIndex,
|
|
1460
1880
|
count: remaining,
|
|
@@ -1467,6 +1887,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1467
1887
|
emitDkgProgress(options, current, startIndex, remaining, progress.completed);
|
|
1468
1888
|
}
|
|
1469
1889
|
});
|
|
1890
|
+
assertUsable();
|
|
1470
1891
|
expectedAddresses = addresses;
|
|
1471
1892
|
const position = await client.finalizeDkgBatch(
|
|
1472
1893
|
{
|
|
@@ -1483,6 +1904,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1483
1904
|
if (position.shards.length < position.targetShardCount) continue;
|
|
1484
1905
|
return position;
|
|
1485
1906
|
} catch (error) {
|
|
1907
|
+
assertUsable();
|
|
1486
1908
|
const reconciled = await tryRefreshCompletedDkgWindow({
|
|
1487
1909
|
client,
|
|
1488
1910
|
positionId,
|
|
@@ -1504,11 +1926,14 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1504
1926
|
throw error;
|
|
1505
1927
|
}
|
|
1506
1928
|
await sleep2(LP_DKG_ACTIVE_SESSION_RETRY_DELAY_MS);
|
|
1929
|
+
} finally {
|
|
1930
|
+
release();
|
|
1507
1931
|
}
|
|
1508
1932
|
}
|
|
1509
1933
|
};
|
|
1510
1934
|
return {
|
|
1511
1935
|
async createPosition(args) {
|
|
1936
|
+
assertUsable();
|
|
1512
1937
|
assertNoUnsupportedFeePolicy(args.feePolicy);
|
|
1513
1938
|
const shardCount = args.shardCount ?? LP_DEFAULT_TARGET_SHARDS;
|
|
1514
1939
|
assertShardCount(shardCount, LP_MAX_INITIAL_SHARDS, "shardCount");
|
|
@@ -1532,6 +1957,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1532
1957
|
{
|
|
1533
1958
|
lpPositionId: positionId,
|
|
1534
1959
|
creationAuthorizationId: creationAuthorization.authorizationId,
|
|
1960
|
+
feePolicy: creationAuthorization.feePolicy,
|
|
1535
1961
|
authPublicKey: Array.from(auth.authPublicKey),
|
|
1536
1962
|
refillPublicKey: Array.from(auth.refillPublicKey),
|
|
1537
1963
|
withdrawalCommitment: Array.from(auth.withdrawalCommitment),
|
|
@@ -1549,6 +1975,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1549
1975
|
return { positionId, lpPositionCode: auth.code, position };
|
|
1550
1976
|
},
|
|
1551
1977
|
async recoverPosition(args) {
|
|
1978
|
+
assertUsable();
|
|
1552
1979
|
const auth = await deriveLpPositionCodeAuth(args.code);
|
|
1553
1980
|
rememberAuth(auth);
|
|
1554
1981
|
const position = rememberPosition(
|
|
@@ -1561,11 +1988,13 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1561
1988
|
return position;
|
|
1562
1989
|
},
|
|
1563
1990
|
confirmPositionCodeSaved(_positionId) {
|
|
1991
|
+
assertUsable();
|
|
1564
1992
|
return;
|
|
1565
1993
|
},
|
|
1566
1994
|
completeDkgBatch: completeDkgBatch2,
|
|
1567
1995
|
refreshPosition: refreshPosition2,
|
|
1568
1996
|
async refill(positionId, args = {}) {
|
|
1997
|
+
assertUsable();
|
|
1569
1998
|
const requestedShardCount = args.shardCount ?? LP_DEFAULT_REFILL_BATCH_SIZE;
|
|
1570
1999
|
assertShardCount(requestedShardCount, LP_MAX_REFILL_BATCH_SIZE, "shardCount");
|
|
1571
2000
|
assertAttested(currentSession);
|
|
@@ -1573,29 +2002,44 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1573
2002
|
const current = await refreshPosition2(positionId);
|
|
1574
2003
|
args.onPosition?.(current);
|
|
1575
2004
|
const refillShardCount = resolveLpRefillShardCount(current, requestedShardCount);
|
|
1576
|
-
const
|
|
1577
|
-
|
|
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,
|
|
1578
2029
|
{
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
authorizedAtMs: nowMs()
|
|
2030
|
+
onProgress: args.onProgress,
|
|
2031
|
+
onPosition: args.onPosition,
|
|
2032
|
+
workerFactory: args.workerFactory,
|
|
2033
|
+
concurrency: resolveLpDkgConcurrency(refillShardCount, runtime.dkgConcurrency)
|
|
1584
2034
|
},
|
|
1585
|
-
|
|
1586
|
-
)
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
if (authorizedPosition.shards.length >= authorizedPosition.targetShardCount) {
|
|
1590
|
-
return authorizedPosition;
|
|
2035
|
+
true
|
|
2036
|
+
);
|
|
2037
|
+
} finally {
|
|
2038
|
+
release();
|
|
1591
2039
|
}
|
|
1592
|
-
return completeDkgBatch2(positionId, {
|
|
1593
|
-
onProgress: args.onProgress,
|
|
1594
|
-
onPosition: args.onPosition,
|
|
1595
|
-
workerFactory: args.workerFactory
|
|
1596
|
-
});
|
|
1597
2040
|
},
|
|
1598
2041
|
async prepareInitialFunding(positionId) {
|
|
2042
|
+
assertUsable();
|
|
1599
2043
|
assertAttested(currentSession);
|
|
1600
2044
|
const auth = requireAuth(positionId);
|
|
1601
2045
|
const currentPosition = rememberPosition(await client.getPosition(positionId, auth));
|
|
@@ -1625,6 +2069,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1625
2069
|
return fundingPlanFromShard(position, plannedShard);
|
|
1626
2070
|
},
|
|
1627
2071
|
async prepareTopUp(positionId) {
|
|
2072
|
+
assertUsable();
|
|
1628
2073
|
assertAttested(currentSession);
|
|
1629
2074
|
const auth = requireAuth(positionId);
|
|
1630
2075
|
const request2 = await client.prepareTopUp(positionId, auth);
|
|
@@ -1632,6 +2077,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1632
2077
|
return request2;
|
|
1633
2078
|
},
|
|
1634
2079
|
async waitForTopUp(topUpId, options = {}) {
|
|
2080
|
+
assertUsable();
|
|
1635
2081
|
const cached = state.topUps.get(topUpId);
|
|
1636
2082
|
if (cached !== void 0 && options.positionId !== void 0 && cached.positionId !== options.positionId) {
|
|
1637
2083
|
throw new PolicyValidationError(
|
|
@@ -1673,11 +2119,13 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1673
2119
|
}
|
|
1674
2120
|
},
|
|
1675
2121
|
async reconcileFunding(positionId) {
|
|
2122
|
+
assertUsable();
|
|
1676
2123
|
assertAttested(currentSession);
|
|
1677
2124
|
const auth = requireAuth(positionId);
|
|
1678
2125
|
return rememberPosition(await client.reconcileFunding(positionId, auth));
|
|
1679
2126
|
},
|
|
1680
2127
|
async withdrawPosition(positionId, args) {
|
|
2128
|
+
assertUsable();
|
|
1681
2129
|
validateExplicitWithdrawalInput(args);
|
|
1682
2130
|
validateWithdrawalDestinations(args);
|
|
1683
2131
|
assertAttested(currentSession);
|
|
@@ -1692,6 +2140,8 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1692
2140
|
const existingRedemption = findOpenRedemptionHistory(before, args);
|
|
1693
2141
|
if (existingRedemption !== void 0) {
|
|
1694
2142
|
const execution2 = {
|
|
2143
|
+
feePolicyHash: existingRedemption.feePolicyHash,
|
|
2144
|
+
feeBasisRevision: existingRedemption.feeBasisRevision,
|
|
1695
2145
|
withdrawalId: existingRedemption.redemptionId,
|
|
1696
2146
|
txSignatures: [...existingRedemption.txSignatures],
|
|
1697
2147
|
acceptedLamports: existingRedemption.acceptedLamports,
|
|
@@ -1736,6 +2186,8 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1736
2186
|
earnedFeeLamports: args.withdrawalMode === "max_available" ? 0 : preview.earnedFeeLamports,
|
|
1737
2187
|
withdrawalMode: args.withdrawalMode,
|
|
1738
2188
|
requestedAtMs,
|
|
2189
|
+
feePolicyHash: before.feePolicy?.policy_hash,
|
|
2190
|
+
feeBasisRevision: before.actorSync?.feeBasisRevision,
|
|
1739
2191
|
allowManyToOne: args.allowManyToOne === true || preview?.sourceCount === 1
|
|
1740
2192
|
},
|
|
1741
2193
|
auth
|
|
@@ -1766,6 +2218,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1766
2218
|
return { execution, position, redemption };
|
|
1767
2219
|
},
|
|
1768
2220
|
async waitForWithdrawalConfirmation(positionId, execution, options = {}) {
|
|
2221
|
+
assertUsable();
|
|
1769
2222
|
const auth = requireAuth(positionId);
|
|
1770
2223
|
let record = resolveWithdrawalRecord({
|
|
1771
2224
|
state,
|
|
@@ -1822,6 +2275,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1822
2275
|
}
|
|
1823
2276
|
},
|
|
1824
2277
|
async withdrawFees(_positionId, args) {
|
|
2278
|
+
assertUsable();
|
|
1825
2279
|
publicKey(args.destination);
|
|
1826
2280
|
assertAttested(currentSession);
|
|
1827
2281
|
throw new RoutingError(
|
|
@@ -1830,6 +2284,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1830
2284
|
);
|
|
1831
2285
|
},
|
|
1832
2286
|
async listPositions() {
|
|
2287
|
+
assertUsable();
|
|
1833
2288
|
return [...state.positions.values()].map(clonePosition);
|
|
1834
2289
|
}
|
|
1835
2290
|
};
|
|
@@ -1864,6 +2319,7 @@ async function tryRefreshCompletedDkgWindow({
|
|
|
1864
2319
|
const position = await client.getPosition(positionId, auth).catch(() => null);
|
|
1865
2320
|
if (position === null) return null;
|
|
1866
2321
|
if (!hasCompletedDkgWindow(position, startIndex, total, expectedAddresses)) return null;
|
|
2322
|
+
validateLpPositionFeePolicy(position, state.positions.get(position.id));
|
|
1867
2323
|
state.positions.set(position.id, clonePosition(position));
|
|
1868
2324
|
return position;
|
|
1869
2325
|
}
|
|
@@ -1962,7 +2418,9 @@ function hasActorSyncLpActivity(sync) {
|
|
|
1962
2418
|
}
|
|
1963
2419
|
function resolveRedeemablePrincipalLamports(sync, legacyAvailableLamports, actorRedeemablePrincipalLamports, actorRedeemableFeeLamports) {
|
|
1964
2420
|
if (sync?.redeemableProjectionAvailable !== true) return legacyAvailableLamports;
|
|
1965
|
-
if (legacyAvailableLamports <= 0)
|
|
2421
|
+
if (sync.feePolicy !== void 0 || legacyAvailableLamports <= 0) {
|
|
2422
|
+
return actorRedeemablePrincipalLamports;
|
|
2423
|
+
}
|
|
1966
2424
|
if (actorRedeemablePrincipalLamports >= legacyAvailableLamports || hasActorSyncLpActivity(sync)) {
|
|
1967
2425
|
return actorRedeemablePrincipalLamports;
|
|
1968
2426
|
}
|
|
@@ -2067,6 +2525,8 @@ function buildLpRedemptionRecord({
|
|
|
2067
2525
|
nowMs
|
|
2068
2526
|
}) {
|
|
2069
2527
|
return {
|
|
2528
|
+
feePolicyHash: execution.feePolicyHash,
|
|
2529
|
+
feeBasisRevision: execution.feeBasisRevision,
|
|
2070
2530
|
redemptionId: execution.withdrawalId,
|
|
2071
2531
|
lpPositionId: position.id,
|
|
2072
2532
|
requestedAt: nowMs,
|
|
@@ -2115,7 +2575,7 @@ function reconcileLpRedemptionFromActorSync(record, position) {
|
|
|
2115
2575
|
function reconcileLpRedemptionFromHistory(record, history) {
|
|
2116
2576
|
const observedStateVersion = record.coordinatorStateVersion ?? 0;
|
|
2117
2577
|
if (history.stateVersion < observedStateVersion) return record;
|
|
2118
|
-
if (record.acceptedLamports !== void 0 && history.acceptedLamports !== record.acceptedLamports || history.detailsTruncated !== true && !sameStringList(history.destinationAddresses, record.destinationAddresses)) {
|
|
2578
|
+
if (history.feePolicyHash !== record.feePolicyHash || history.feeBasisRevision !== record.feeBasisRevision || record.acceptedLamports !== void 0 && history.acceptedLamports !== record.acceptedLamports || history.detailsTruncated !== true && !sameStringList(history.destinationAddresses, record.destinationAddresses)) {
|
|
2119
2579
|
return {
|
|
2120
2580
|
...record,
|
|
2121
2581
|
status: "failed",
|
|
@@ -2165,6 +2625,8 @@ function hydrateLpRedemptionsFromPosition(state, position) {
|
|
|
2165
2625
|
}
|
|
2166
2626
|
function lpWithdrawalRecordFromHistory(position, history) {
|
|
2167
2627
|
const record = {
|
|
2628
|
+
feePolicyHash: history.feePolicyHash,
|
|
2629
|
+
feeBasisRevision: history.feeBasisRevision,
|
|
2168
2630
|
redemptionId: history.redemptionId,
|
|
2169
2631
|
lpPositionId: position.id,
|
|
2170
2632
|
requestedAt: history.createdAtMs,
|
|
@@ -2194,6 +2656,7 @@ function uniqueStrings(values) {
|
|
|
2194
2656
|
function clonePosition(position) {
|
|
2195
2657
|
return {
|
|
2196
2658
|
...position,
|
|
2659
|
+
feePolicy: position.feePolicy === void 0 ? void 0 : { ...position.feePolicy },
|
|
2197
2660
|
shards: position.shards.map((shard) => ({ ...shard })),
|
|
2198
2661
|
actorSync: position.actorSync === void 0 ? void 0 : {
|
|
2199
2662
|
...position.actorSync,
|
|
@@ -2306,6 +2769,6 @@ function listPositions(session) {
|
|
|
2306
2769
|
return defaultLpLifecycleClient(session).listPositions();
|
|
2307
2770
|
}
|
|
2308
2771
|
|
|
2309
|
-
export { LP_COMMAND_REQUEST_TIMEOUT_MS, LP_DKG_ABORT_CLEANUP_TIMEOUT_MS, LP_DKG_ABORT_REQUEST_TIMEOUT_MS, LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE, LP_DKG_WORKER_REQUEST_TIMEOUT_MS, LP_FEE_SOURCE_COUNT_UNAVAILABLE_MESSAGE, LP_MISSING_POSITION_CODE_MESSAGE, LP_REDEMPTION_RECONCILING_MESSAGE, bytesToHex, completeDkgBatch, confirmPositionCodeSaved, createLpCoordinatorClient, createLpDkgBatch, createLpLifecycleClient, createPosition, defaultLpLifecycleClient, deriveLpPositionCodeAuth, generateLpPositionCode, isLpPositionAuthMissingError, isLpRedemptionReconcilingError, listPositions, normalizeLpPositionCode, prepareInitialFunding, prepareTopUp2 as prepareTopUp, previewLpWithdrawalPlan, reconcileFunding2 as reconcileFunding, recoverPosition, refill, refreshPosition, signLpCommandBytes, waitForTopUp, waitForWithdrawalConfirmation, withdrawFees, withdrawPosition };
|
|
2772
|
+
export { LP_COMMAND_REQUEST_TIMEOUT_MS, LP_DKG_ABORT_CLEANUP_TIMEOUT_MS, LP_DKG_ABORT_REQUEST_TIMEOUT_MS, LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE, LP_DKG_WORKER_REQUEST_TIMEOUT_MS, LP_FEE_SOURCE_COUNT_UNAVAILABLE_MESSAGE, LP_MISSING_POSITION_CODE_MESSAGE, LP_REDEMPTION_RECONCILING_MESSAGE, bytesToHex, completeDkgBatch, confirmPositionCodeSaved, createLpCoordinatorClient, createLpDkgBatch, createLpLifecycleClient, createPosition, defaultLpLifecycleClient, deriveLpPositionCodeAuth, generateLpPositionCode, isLpPositionAuthMissingError, isLpRedemptionReconcilingError, listPositions, mergeLpActorSync, normalizeLpActorSync, normalizeLpPositionCode, prepareInitialFunding, prepareTopUp2 as prepareTopUp, previewLpWithdrawalPlan, reconcileFunding2 as reconcileFunding, recoverPosition, refill, refreshPosition, signLpCommandBytes, validateLpPositionFeePolicy, waitForTopUp, waitForWithdrawalConfirmation, withdrawFees, withdrawPosition };
|
|
2310
2773
|
//# sourceMappingURL=lp.js.map
|
|
2311
2774
|
//# sourceMappingURL=lp.js.map
|