@invisible-labs/sdk 0.6.0-devnet.3 → 0.6.0-devnet.4
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 +67 -10
- package/dist/.invisible-sdk-build-target.json +7 -0
- package/dist/{chunk-BWCGNTN5.js → chunk-5NNEO7IK.js} +31 -34
- package/dist/chunk-5NNEO7IK.js.map +1 -0
- package/dist/chunk-BRDLLGCZ.js +59 -0
- package/dist/chunk-BRDLLGCZ.js.map +1 -0
- package/dist/{chunk-NKRVQXRP.js → chunk-E4DCEDAG.js} +121 -11
- package/dist/chunk-E4DCEDAG.js.map +1 -0
- package/dist/{chunk-QQSI3ZD7.js → chunk-UADJCUPK.js} +106 -15
- package/dist/chunk-UADJCUPK.js.map +1 -0
- package/dist/{coordinator-VVJ33WF2.js → coordinator-ZNLGAYXD.js} +3 -3
- package/dist/{coordinator-VVJ33WF2.js.map → coordinator-ZNLGAYXD.js.map} +1 -1
- package/dist/events.js +1 -1
- package/dist/index.d.ts +59 -353
- package/dist/index.js +94 -39
- package/dist/index.js.map +1 -1
- package/dist/lp.d.ts +44 -10
- package/dist/lp.js +211 -71
- package/dist/lp.js.map +1 -1
- package/dist/presets.d.ts +5 -42
- package/dist/presets.js +10 -68
- package/dist/presets.js.map +1 -1
- package/dist/{errors-N2touVm4.d.ts → types.generated-DJBTjLpP.d.ts} +37 -1
- package/dist/user.d.ts +107 -8
- package/dist/user.js +613 -224
- package/dist/user.js.map +1 -1
- package/package.json +2 -31
- package/dist/chunk-BWCGNTN5.js.map +0 -1
- package/dist/chunk-NKRVQXRP.js.map +0 -1
- package/dist/chunk-QQSI3ZD7.js.map +0 -1
- package/dist/types.generated-BSEBz4jR.d.ts +0 -68
package/dist/lp.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isValidLpPositionId, LP_DEFAULT_REFILL_BATCH_SIZE, LP_DEFAULT_TARGET_SHARDS, LP_MAX_TARGET_SHARDS, LP_MAX_REFILL_BATCH_SIZE } from './chunk-4X5OCCQW.js';
|
|
2
2
|
import { publicKey, assertAttested, lamports } from './chunk-NHEHCUS5.js';
|
|
3
|
-
import { requestEnvelope } from './chunk-
|
|
3
|
+
import { requestEnvelope } from './chunk-UADJCUPK.js';
|
|
4
4
|
import { getSessionState } from './chunk-V5HXJRBW.js';
|
|
5
|
-
import { CommandError, PolicyValidationError, RoutingError, LpLifecycleError } from './chunk-GHBQF3A7.js';
|
|
5
|
+
import { CommandError, PolicyValidationError, TransportError, RoutingError, LpLifecycleError } from './chunk-GHBQF3A7.js';
|
|
6
6
|
import './chunk-VR6T6OJS.js';
|
|
7
7
|
|
|
8
8
|
// src/lp/positionCode.ts
|
|
@@ -172,14 +172,8 @@ function getCrypto() {
|
|
|
172
172
|
var SINGLE_DESTINATION_WITHDRAWAL_MESSAGE = "single-destination withdrawal is privacy-degrading; pass allowManyToOne: true to acknowledge";
|
|
173
173
|
var DESTINATION_SOURCE_COUNT_MESSAGE = "LP withdrawal requires one destination per withdrawable source unless allowManyToOne is true";
|
|
174
174
|
var SOURCE_COUNT_MESSAGE = "LP withdrawal source count must be a positive integer";
|
|
175
|
-
function
|
|
176
|
-
const {
|
|
177
|
-
depositPrincipalLamports,
|
|
178
|
-
earnedFeeLamports,
|
|
179
|
-
destinationAddresses,
|
|
180
|
-
allowManyToOne,
|
|
181
|
-
sourceCount
|
|
182
|
-
} = input;
|
|
175
|
+
function validateLpWithdrawalClaim(input) {
|
|
176
|
+
const { depositPrincipalLamports, earnedFeeLamports } = input;
|
|
183
177
|
lamports(depositPrincipalLamports);
|
|
184
178
|
lamports(earnedFeeLamports);
|
|
185
179
|
if (depositPrincipalLamports === 0 && earnedFeeLamports === 0) {
|
|
@@ -188,6 +182,16 @@ function validateLpWithdrawalPlan(input) {
|
|
|
188
182
|
"LP withdrawal requires a non-zero principal or earned-fee claim"
|
|
189
183
|
);
|
|
190
184
|
}
|
|
185
|
+
}
|
|
186
|
+
function validateLpWithdrawalPlan(input) {
|
|
187
|
+
const {
|
|
188
|
+
depositPrincipalLamports,
|
|
189
|
+
earnedFeeLamports,
|
|
190
|
+
destinationAddresses,
|
|
191
|
+
allowManyToOne,
|
|
192
|
+
sourceCount
|
|
193
|
+
} = input;
|
|
194
|
+
validateLpWithdrawalClaim({ depositPrincipalLamports, earnedFeeLamports });
|
|
191
195
|
validateDestinationAddresses(destinationAddresses);
|
|
192
196
|
if (sourceCount !== void 0 && (!Number.isInteger(sourceCount) || sourceCount < 1)) {
|
|
193
197
|
throw new PolicyValidationError("INVALID_WITHDRAWAL_PLAN", SOURCE_COUNT_MESSAGE);
|
|
@@ -245,8 +249,8 @@ function createLpCoordinatorClient(session) {
|
|
|
245
249
|
openPosition(input, auth) {
|
|
246
250
|
return openPosition(session, input, auth);
|
|
247
251
|
},
|
|
248
|
-
getPosition(lpPositionId, auth) {
|
|
249
|
-
return getPosition(session, lpPositionId, auth);
|
|
252
|
+
getPosition(lpPositionId, auth, options) {
|
|
253
|
+
return getPosition(session, lpPositionId, auth, options);
|
|
250
254
|
},
|
|
251
255
|
finalizeDkgBatch(input, auth) {
|
|
252
256
|
return finalizeDkgBatch(session, input, auth);
|
|
@@ -295,7 +299,7 @@ async function abortDkgSessions(session, lpPositionId, auth) {
|
|
|
295
299
|
case: "dkgAbort",
|
|
296
300
|
value: {}
|
|
297
301
|
},
|
|
298
|
-
LP_DKG_ABORT_REQUEST_TIMEOUT_MS
|
|
302
|
+
{ timeoutMs: LP_DKG_ABORT_REQUEST_TIMEOUT_MS }
|
|
299
303
|
);
|
|
300
304
|
if (response.case !== "dkgAbort") throw new Error("Unexpected LP DKG abort response");
|
|
301
305
|
return { abortedSessionCount: response.value.aborted_session_count };
|
|
@@ -348,15 +352,23 @@ async function openPosition(session, input, auth) {
|
|
|
348
352
|
});
|
|
349
353
|
return expectPosition(response);
|
|
350
354
|
}
|
|
351
|
-
async function getPosition(session, lpPositionId, auth) {
|
|
355
|
+
async function getPosition(session, lpPositionId, auth, options = {}) {
|
|
352
356
|
let cursor;
|
|
353
357
|
let position;
|
|
354
358
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
355
359
|
for (; ; ) {
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
+
const pageOptions = lpPositionPageRequestOptions(options);
|
|
361
|
+
const response = await requestForPosition(
|
|
362
|
+
session,
|
|
363
|
+
lpPositionId,
|
|
364
|
+
auth,
|
|
365
|
+
"position_get",
|
|
366
|
+
{
|
|
367
|
+
case: "positionGet",
|
|
368
|
+
value: cursor === void 0 ? {} : { redemption_history_cursor: cursor }
|
|
369
|
+
},
|
|
370
|
+
pageOptions
|
|
371
|
+
);
|
|
360
372
|
const page = expectPosition(response);
|
|
361
373
|
const mergedPosition = position === void 0 ? page : mergePositionHistoryPages(position, page);
|
|
362
374
|
position = mergedPosition;
|
|
@@ -373,6 +385,18 @@ async function getPosition(session, lpPositionId, auth) {
|
|
|
373
385
|
cursor = nextCursor;
|
|
374
386
|
}
|
|
375
387
|
}
|
|
388
|
+
function lpPositionPageRequestOptions(options) {
|
|
389
|
+
if (options.deadlineMs === void 0) return options;
|
|
390
|
+
const remainingMs = options.deadlineMs - Date.now();
|
|
391
|
+
if (remainingMs <= 0) {
|
|
392
|
+
throw new CommandError("REJECTED_STALE_JOB", "LP position observation deadline elapsed");
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
deadlineMs: options.deadlineMs,
|
|
396
|
+
signal: options.signal,
|
|
397
|
+
timeoutMs: Math.min(options.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS, remainingMs)
|
|
398
|
+
};
|
|
399
|
+
}
|
|
376
400
|
async function finalizeDkgBatch(session, input, auth) {
|
|
377
401
|
const response = await requestForPosition(session, input.lpPositionId, auth, "dkg_finalize", {
|
|
378
402
|
case: "dkgFinalize",
|
|
@@ -461,36 +485,59 @@ async function makeAvailable(session, input, auth) {
|
|
|
461
485
|
async function executeWithdrawal(session, input, auth) {
|
|
462
486
|
validateLpWithdrawalPlan({
|
|
463
487
|
destinationAddresses: input.destinationAddresses,
|
|
464
|
-
depositPrincipalLamports: input.depositPrincipalLamports,
|
|
465
|
-
earnedFeeLamports: input.earnedFeeLamports,
|
|
466
|
-
|
|
488
|
+
depositPrincipalLamports: input.withdrawalMode === "max_available" ? 1 : input.depositPrincipalLamports,
|
|
489
|
+
earnedFeeLamports: input.withdrawalMode === "max_available" ? 0 : input.earnedFeeLamports,
|
|
490
|
+
// Max mode deliberately does not preview source count. The coordinator
|
|
491
|
+
// owns the accepted split, so local destination validation must not reject
|
|
492
|
+
// a one-destination request based on an unknown current source count.
|
|
493
|
+
allowManyToOne: input.withdrawalMode === "max_available" || input.allowManyToOne
|
|
467
494
|
});
|
|
468
495
|
const response = await requestForPosition(session, input.lpPositionId, auth, "withdraw_request", {
|
|
469
496
|
case: "withdrawRequest",
|
|
470
497
|
value: {
|
|
471
498
|
destination_addresses: input.destinationAddresses,
|
|
472
|
-
deposit_principal_lamports: input.depositPrincipalLamports,
|
|
473
|
-
earned_fee_lamports: input.earnedFeeLamports,
|
|
499
|
+
deposit_principal_lamports: input.withdrawalMode === "max_available" ? 0 : input.depositPrincipalLamports,
|
|
500
|
+
earned_fee_lamports: input.withdrawalMode === "max_available" ? 0 : input.earnedFeeLamports,
|
|
501
|
+
withdrawal_mode: input.withdrawalMode,
|
|
474
502
|
requested_at_ms: input.requestedAtMs
|
|
475
503
|
}
|
|
476
504
|
});
|
|
477
505
|
if (response.case !== "withdrawalExecution") {
|
|
478
506
|
throw new Error("Unexpected LP withdrawal execution response");
|
|
479
507
|
}
|
|
508
|
+
const execution = response.value;
|
|
509
|
+
if (BigInt(execution.accepted_lamports) !== BigInt(execution.accepted_deposit_principal_lamports) + BigInt(execution.accepted_earned_fee_lamports)) {
|
|
510
|
+
throw new PolicyValidationError(
|
|
511
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
512
|
+
"Coordinator accepted withdrawal total does not match its principal and fee split"
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
if (input.withdrawalMode === "exact" && (execution.accepted_deposit_principal_lamports !== input.depositPrincipalLamports || execution.accepted_earned_fee_lamports !== input.earnedFeeLamports)) {
|
|
516
|
+
throw new PolicyValidationError(
|
|
517
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
518
|
+
"Coordinator accepted withdrawal split does not match the signed exact claim"
|
|
519
|
+
);
|
|
520
|
+
}
|
|
480
521
|
return {
|
|
481
|
-
withdrawalId:
|
|
482
|
-
txSignatures: [...
|
|
522
|
+
withdrawalId: execution.withdrawal_id,
|
|
523
|
+
txSignatures: [...execution.tx_signatures],
|
|
524
|
+
acceptedLamports: execution.accepted_lamports,
|
|
525
|
+
acceptedDepositPrincipalLamports: execution.accepted_deposit_principal_lamports,
|
|
526
|
+
acceptedEarnedFeeLamports: execution.accepted_earned_fee_lamports
|
|
483
527
|
};
|
|
484
528
|
}
|
|
485
529
|
function request(session, auth, action, payload) {
|
|
486
530
|
return requestForPosition(session, auth.lpPositionId, auth, action, payload);
|
|
487
531
|
}
|
|
488
|
-
async function requestForPosition(session, lpPositionId, auth, action, payload,
|
|
532
|
+
async function requestForPosition(session, lpPositionId, auth, action, payload, options = {}) {
|
|
533
|
+
const timeoutMs = options.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS;
|
|
489
534
|
assertAuthMatchesPosition(lpPositionId, auth);
|
|
490
535
|
const protocol = await loadProtocol();
|
|
491
536
|
const state = getSessionState(session);
|
|
492
537
|
const attestation = state.channel?.attestation;
|
|
493
|
-
if (!attestation)
|
|
538
|
+
if (!attestation) {
|
|
539
|
+
throw new TransportError("CONNECTION_LOST", "LP coordinator attestation is not available");
|
|
540
|
+
}
|
|
494
541
|
const command = {
|
|
495
542
|
lp_position_id: lpPositionId,
|
|
496
543
|
action,
|
|
@@ -504,8 +551,10 @@ async function requestForPosition(session, lpPositionId, auth, action, payload,
|
|
|
504
551
|
};
|
|
505
552
|
const signature = await signLpCommandBytes(auth, protocol.encodeLpCommandForSigning(command));
|
|
506
553
|
const { type, payload: envelopePayload } = protocol.lpSignedCommandEnvelope(command, signature);
|
|
554
|
+
const requestOptions = lpPositionPageRequestOptions(options);
|
|
507
555
|
const envelope = await requestEnvelope(session, type, envelopePayload, {
|
|
508
|
-
timeoutMs
|
|
556
|
+
timeoutMs: requestOptions.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS,
|
|
557
|
+
signal: requestOptions.signal
|
|
509
558
|
});
|
|
510
559
|
return protocol.asLpCommandResponsePayload(envelope);
|
|
511
560
|
}
|
|
@@ -564,6 +613,7 @@ function mapLpActorSync(actorSync) {
|
|
|
564
613
|
lifetimeEarnedLamports: actorSync.lifetime_earned_lamports ?? 0,
|
|
565
614
|
redeemablePrincipalSourceCount: actorSync.redeemable_principal_source_count ?? 0,
|
|
566
615
|
redeemableFeeSourceCount: actorSync.redeemable_fee_source_count ?? 0,
|
|
616
|
+
redeemableSourceCount: actorSync.redeemable_source_count,
|
|
567
617
|
pendingReservationCount: actorSync.pending_reservation_count,
|
|
568
618
|
reservedPayoutLamports: actorSync.reserved_payout_lamports,
|
|
569
619
|
estimatedNetworkFeeLamports: actorSync.estimated_network_fee_lamports,
|
|
@@ -607,6 +657,7 @@ function mapLpRedemptionHistory(history) {
|
|
|
607
657
|
return {
|
|
608
658
|
redemptionId: history.redemption_id,
|
|
609
659
|
state: history.state,
|
|
660
|
+
...history.withdrawal_mode === void 0 ? {} : { withdrawalMode: history.withdrawal_mode },
|
|
610
661
|
acceptedLamports: history.accepted_lamports,
|
|
611
662
|
acceptedDepositPrincipalLamports: history.accepted_deposit_principal_lamports,
|
|
612
663
|
acceptedEarnedFeeLamports: history.accepted_earned_fee_lamports,
|
|
@@ -685,7 +736,7 @@ function randomBytes(length) {
|
|
|
685
736
|
return bytes;
|
|
686
737
|
}
|
|
687
738
|
function loadProtocol() {
|
|
688
|
-
protocolPromise ??= import('./coordinator-
|
|
739
|
+
protocolPromise ??= import('./coordinator-ZNLGAYXD.js');
|
|
689
740
|
return protocolPromise;
|
|
690
741
|
}
|
|
691
742
|
|
|
@@ -962,7 +1013,7 @@ var WITHDRAWAL_NO_LAMPORTS_MESSAGE = "LP redemption did not land any lamports on
|
|
|
962
1013
|
var WITHDRAWAL_HISTORY_MISMATCH_MESSAGE = "LP redemption history does not match this request";
|
|
963
1014
|
var LP_WITHDRAWAL_UNRESOLVED_FUNDING_MESSAGE = "LP position has unresolved funding shards before redemption";
|
|
964
1015
|
var UNSUPPORTED_FEE_POLICY_MESSAGE = "LP fee policy overrides are not advertised by the coordinator";
|
|
965
|
-
var
|
|
1016
|
+
var LP_FEE_SOURCE_COUNT_UNAVAILABLE_MESSAGE = "LP earned-fee source count is not available; pass allowManyToOne: true to acknowledge many-to-one withdrawal risk";
|
|
966
1017
|
var LpRedemptionReconcilingError = class extends LpLifecycleError {
|
|
967
1018
|
constructor() {
|
|
968
1019
|
super("LP_REDEMPTION_RECONCILING", LP_REDEMPTION_RECONCILING_MESSAGE);
|
|
@@ -981,6 +1032,16 @@ function isLpRedemptionReconcilingError(error) {
|
|
|
981
1032
|
function isLpPositionAuthMissingError(error) {
|
|
982
1033
|
return error instanceof LpPositionAuthMissingError || error instanceof Error && error.message === LP_MISSING_POSITION_CODE_MESSAGE;
|
|
983
1034
|
}
|
|
1035
|
+
function previewLpWithdrawalPlan(position, args = {}) {
|
|
1036
|
+
const claim = resolveWithdrawalClaim(position, args);
|
|
1037
|
+
return {
|
|
1038
|
+
...claim,
|
|
1039
|
+
sourceCount: lpWithdrawalSourceCountForClaim(position, {
|
|
1040
|
+
...claim,
|
|
1041
|
+
allowManyToOne: args.allowManyToOne
|
|
1042
|
+
})
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
984
1045
|
var lifecycleClients = /* @__PURE__ */ new WeakMap();
|
|
985
1046
|
function createLpLifecycleClient(session, runtime = {}) {
|
|
986
1047
|
const state = {
|
|
@@ -1121,7 +1182,12 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1121
1182
|
async recoverPosition(args) {
|
|
1122
1183
|
const auth = await deriveLpPositionCodeAuth(args.code);
|
|
1123
1184
|
rememberAuth(auth);
|
|
1124
|
-
const position = rememberPosition(
|
|
1185
|
+
const position = rememberPosition(
|
|
1186
|
+
await client.getPosition(auth.lpPositionId, auth, {
|
|
1187
|
+
deadlineMs: args.deadlineMs,
|
|
1188
|
+
signal: args.signal
|
|
1189
|
+
})
|
|
1190
|
+
);
|
|
1125
1191
|
assertPositionMatchesAuth(position, auth);
|
|
1126
1192
|
return position;
|
|
1127
1193
|
},
|
|
@@ -1256,7 +1322,10 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1256
1322
|
if (existingRedemption !== void 0) {
|
|
1257
1323
|
const execution2 = {
|
|
1258
1324
|
withdrawalId: existingRedemption.redemptionId,
|
|
1259
|
-
txSignatures: [...existingRedemption.txSignatures]
|
|
1325
|
+
txSignatures: [...existingRedemption.txSignatures],
|
|
1326
|
+
acceptedLamports: existingRedemption.acceptedLamports,
|
|
1327
|
+
acceptedDepositPrincipalLamports: existingRedemption.acceptedDepositPrincipalLamports,
|
|
1328
|
+
acceptedEarnedFeeLamports: existingRedemption.acceptedEarnedFeeLamports
|
|
1260
1329
|
};
|
|
1261
1330
|
const redemption2 = {
|
|
1262
1331
|
...buildLpRedemptionRecord({
|
|
@@ -1276,39 +1345,44 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1276
1345
|
state.redemptions.set(execution2.withdrawalId, redemption2);
|
|
1277
1346
|
return { execution: execution2, position: before, redemption: redemption2 };
|
|
1278
1347
|
}
|
|
1279
|
-
const
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
allowManyToOne: args.allowManyToOne ?? false,
|
|
1291
|
-
sourceCount
|
|
1292
|
-
};
|
|
1293
|
-
validateLpWithdrawalPlan(validationInput);
|
|
1348
|
+
const preview = args.withdrawalMode === "exact" ? previewLpWithdrawalPlan(before, args) : void 0;
|
|
1349
|
+
const requestedAtMs = nowMs();
|
|
1350
|
+
if (args.withdrawalMode === "exact") {
|
|
1351
|
+
validateLpWithdrawalPlan({
|
|
1352
|
+
destinationAddresses: args.destinationAddresses,
|
|
1353
|
+
depositPrincipalLamports: preview.depositPrincipalLamports,
|
|
1354
|
+
earnedFeeLamports: preview.earnedFeeLamports,
|
|
1355
|
+
allowManyToOne: args.allowManyToOne ?? false,
|
|
1356
|
+
sourceCount: preview.sourceCount
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1294
1359
|
const execution = await executeWithdrawalAfterFundingReadiness(
|
|
1295
1360
|
positionId,
|
|
1296
1361
|
{
|
|
1297
|
-
lpPositionId:
|
|
1298
|
-
destinationAddresses:
|
|
1299
|
-
depositPrincipalLamports:
|
|
1300
|
-
earnedFeeLamports:
|
|
1301
|
-
|
|
1302
|
-
|
|
1362
|
+
lpPositionId: positionId,
|
|
1363
|
+
destinationAddresses: args.destinationAddresses,
|
|
1364
|
+
depositPrincipalLamports: args.withdrawalMode === "max_available" ? 0 : preview.depositPrincipalLamports,
|
|
1365
|
+
earnedFeeLamports: args.withdrawalMode === "max_available" ? 0 : preview.earnedFeeLamports,
|
|
1366
|
+
withdrawalMode: args.withdrawalMode,
|
|
1367
|
+
requestedAtMs,
|
|
1368
|
+
allowManyToOne: args.allowManyToOne === true || preview?.sourceCount === 1
|
|
1303
1369
|
},
|
|
1304
1370
|
auth
|
|
1305
1371
|
);
|
|
1372
|
+
const acceptedLamports = execution.acceptedLamports;
|
|
1373
|
+
if (args.withdrawalMode === "max_available" && acceptedLamports === void 0) {
|
|
1374
|
+
throw new PolicyValidationError(
|
|
1375
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
1376
|
+
"LP redemption response did not include the sealed accepted amount"
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
const acceptedAmount = acceptedLamports ?? preview.depositPrincipalLamports + preview.earnedFeeLamports;
|
|
1306
1380
|
const pendingRedemption = buildLpRedemptionRecord({
|
|
1307
1381
|
execution,
|
|
1308
1382
|
position: before,
|
|
1309
1383
|
destinationAddresses: args.destinationAddresses,
|
|
1310
|
-
acceptedLamports:
|
|
1311
|
-
requestedTargetLamports: (before.actorSync?.withdrawalRequestedLamports ?? 0) +
|
|
1384
|
+
acceptedLamports: acceptedAmount,
|
|
1385
|
+
requestedTargetLamports: (before.actorSync?.withdrawalRequestedLamports ?? 0) + acceptedAmount,
|
|
1312
1386
|
landedBaselineLamports: before.actorSync?.withdrawalLandedLamports ?? 0,
|
|
1313
1387
|
landedFeeBaselineLamports: before.actorSync?.withdrawalLandedFeeLamports ?? 0,
|
|
1314
1388
|
txSignatureBaseline: before.actorSync?.withdrawalTxHashes ?? [],
|
|
@@ -1329,10 +1403,32 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1329
1403
|
options
|
|
1330
1404
|
});
|
|
1331
1405
|
state.redemptions.set(record.redemptionId, record);
|
|
1332
|
-
const deadlineMs = nowMs() + (runtime.withdrawalConfirmationTimeoutMs ?? LP_WITHDRAWAL_CONFIRMATION_TIMEOUT_MS);
|
|
1406
|
+
const deadlineMs = options.deadlineMs ?? nowMs() + (runtime.withdrawalConfirmationTimeoutMs ?? LP_WITHDRAWAL_CONFIRMATION_TIMEOUT_MS);
|
|
1333
1407
|
const pollIntervalMs = runtime.withdrawalConfirmationPollIntervalMs ?? LP_WITHDRAWAL_CONFIRMATION_POLL_INTERVAL_MS;
|
|
1334
1408
|
for (; ; ) {
|
|
1335
|
-
|
|
1409
|
+
throwIfWithdrawalConfirmationAborted(options.signal);
|
|
1410
|
+
if (nowMs() >= deadlineMs) {
|
|
1411
|
+
markLpRedemptionReconciling(state, record, options);
|
|
1412
|
+
}
|
|
1413
|
+
const remainingMs = deadlineMs - nowMs();
|
|
1414
|
+
if (remainingMs <= 0) {
|
|
1415
|
+
markLpRedemptionReconciling(state, record, options);
|
|
1416
|
+
}
|
|
1417
|
+
let position;
|
|
1418
|
+
try {
|
|
1419
|
+
position = rememberPosition(
|
|
1420
|
+
await client.getPosition(positionId, auth, {
|
|
1421
|
+
deadlineMs,
|
|
1422
|
+
signal: options.signal
|
|
1423
|
+
})
|
|
1424
|
+
);
|
|
1425
|
+
} catch (error) {
|
|
1426
|
+
if (isLpPositionObservationDeadlineError(error, deadlineMs, nowMs)) {
|
|
1427
|
+
markLpRedemptionReconciling(state, record, options);
|
|
1428
|
+
}
|
|
1429
|
+
throw error;
|
|
1430
|
+
}
|
|
1431
|
+
throwIfWithdrawalConfirmationAborted(options.signal);
|
|
1336
1432
|
options.onPosition?.(position);
|
|
1337
1433
|
const reconciled = reconcileLpRedemptionFromActorSync(record, position);
|
|
1338
1434
|
record = reconciled;
|
|
@@ -1348,12 +1444,10 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1348
1444
|
if (reconciled.status === "failed") {
|
|
1349
1445
|
throw new Error(reconciled.error ?? WITHDRAWAL_NO_LAMPORTS_MESSAGE);
|
|
1350
1446
|
}
|
|
1351
|
-
if (nowMs()
|
|
1352
|
-
state
|
|
1353
|
-
options.onRedemptionUpdate?.({ ...reconciled, status: "reconciling" });
|
|
1354
|
-
throw new LpRedemptionReconcilingError();
|
|
1447
|
+
if (nowMs() >= deadlineMs) {
|
|
1448
|
+
markLpRedemptionReconciling(state, reconciled, options);
|
|
1355
1449
|
}
|
|
1356
|
-
await sleep2
|
|
1450
|
+
await sleepWithAbort(sleep2, pollIntervalMs, options.signal);
|
|
1357
1451
|
}
|
|
1358
1452
|
},
|
|
1359
1453
|
async withdrawFees(_positionId, args) {
|
|
@@ -1462,10 +1556,12 @@ function isLpPositionReadyForInitialFunding(position) {
|
|
|
1462
1556
|
}
|
|
1463
1557
|
function resolveWithdrawalClaim(position, args) {
|
|
1464
1558
|
if (args.depositPrincipalLamports !== void 0 || args.earnedFeeLamports !== void 0) {
|
|
1465
|
-
|
|
1559
|
+
const claim = {
|
|
1466
1560
|
depositPrincipalLamports: args.depositPrincipalLamports ?? 0,
|
|
1467
1561
|
earnedFeeLamports: args.earnedFeeLamports ?? 0
|
|
1468
1562
|
};
|
|
1563
|
+
validateLpWithdrawalClaim(claim);
|
|
1564
|
+
return claim;
|
|
1469
1565
|
}
|
|
1470
1566
|
const legacyDepositPrincipalLamports = position.shards.filter((shard) => shard.status === "AVAILABLE" && shard.amountLamports > 0).reduce((sum, shard) => sum + shard.amountLamports, 0);
|
|
1471
1567
|
const actorRedeemablePrincipalLamports = Math.max(
|
|
@@ -1491,11 +1587,11 @@ function resolveWithdrawalClaim(position, args) {
|
|
|
1491
1587
|
return { depositPrincipalLamports, earnedFeeLamports };
|
|
1492
1588
|
}
|
|
1493
1589
|
function findOpenRedemptionHistory(position, args) {
|
|
1494
|
-
const hasExplicitClaim = args.
|
|
1590
|
+
const hasExplicitClaim = args.withdrawalMode === "exact";
|
|
1495
1591
|
const requestedPrincipalLamports = args.depositPrincipalLamports ?? 0;
|
|
1496
1592
|
const requestedFeeLamports = args.earnedFeeLamports ?? 0;
|
|
1497
1593
|
return position.actorSync?.redemptionHistory?.find(
|
|
1498
|
-
(history) => LP_REDEMPTION_HISTORY_OPEN_STATES.has(history.state) && history.detailsTruncated !== true && sameStringList(history.destinationAddresses, args.destinationAddresses) && (!hasExplicitClaim || history.acceptedDepositPrincipalLamports === requestedPrincipalLamports && history.acceptedEarnedFeeLamports === requestedFeeLamports)
|
|
1594
|
+
(history) => LP_REDEMPTION_HISTORY_OPEN_STATES.has(history.state) && history.detailsTruncated !== true && (history.withdrawalMode ?? "exact") === args.withdrawalMode && sameStringList(history.destinationAddresses, args.destinationAddresses) && (!hasExplicitClaim || history.acceptedDepositPrincipalLamports === requestedPrincipalLamports && history.acceptedEarnedFeeLamports === requestedFeeLamports)
|
|
1499
1595
|
);
|
|
1500
1596
|
}
|
|
1501
1597
|
function hasActorSyncLpActivity(sync) {
|
|
@@ -1517,11 +1613,25 @@ function hasActorRedeemableProjection(sync) {
|
|
|
1517
1613
|
return sync?.redeemableProjectionAvailable === true;
|
|
1518
1614
|
}
|
|
1519
1615
|
function validateExplicitWithdrawalInput(args) {
|
|
1520
|
-
if (args.
|
|
1616
|
+
if (args.withdrawalMode === "max_available") {
|
|
1617
|
+
if (args.depositPrincipalLamports !== void 0 || args.earnedFeeLamports !== void 0) {
|
|
1618
|
+
throw new PolicyValidationError(
|
|
1619
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
1620
|
+
"max_available withdrawal must not carry exact bucket claims"
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
if (args.depositPrincipalLamports === void 0 || args.earnedFeeLamports === void 0) {
|
|
1626
|
+
throw new PolicyValidationError(
|
|
1627
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
1628
|
+
"exact withdrawal requires both bucket claims"
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1521
1631
|
validateLpWithdrawalPlan({
|
|
1522
1632
|
destinationAddresses: args.destinationAddresses,
|
|
1523
|
-
depositPrincipalLamports: args.depositPrincipalLamports
|
|
1524
|
-
earnedFeeLamports: args.earnedFeeLamports
|
|
1633
|
+
depositPrincipalLamports: args.depositPrincipalLamports,
|
|
1634
|
+
earnedFeeLamports: args.earnedFeeLamports,
|
|
1525
1635
|
allowManyToOne: args.allowManyToOne,
|
|
1526
1636
|
sourceCount: args.destinationAddresses.length
|
|
1527
1637
|
});
|
|
@@ -1554,6 +1664,13 @@ function resolveWithdrawalRecord({
|
|
|
1554
1664
|
};
|
|
1555
1665
|
}
|
|
1556
1666
|
function lpWithdrawalSourceCountForClaim(position, claim) {
|
|
1667
|
+
const actorSync = position.actorSync;
|
|
1668
|
+
const actorRedeemablePrincipalLamports = actorSync?.redeemablePrincipalLamports ?? 0;
|
|
1669
|
+
const actorRedeemableFeeLamports = actorSync?.redeemableFeeLamports ?? 0;
|
|
1670
|
+
const actorRedeemableSourceCount = actorSync?.redeemableSourceCount;
|
|
1671
|
+
if (actorSync?.redeemableProjectionAvailable === true && claim.depositPrincipalLamports === actorRedeemablePrincipalLamports && claim.earnedFeeLamports === actorRedeemableFeeLamports && actorRedeemableSourceCount !== void 0) {
|
|
1672
|
+
return actorRedeemableSourceCount;
|
|
1673
|
+
}
|
|
1557
1674
|
let remainingPrincipalLamports = claim.depositPrincipalLamports;
|
|
1558
1675
|
let principalSourceCount = 0;
|
|
1559
1676
|
const principalCandidates = [...position.shards].filter((shard) => shard.status === "AVAILABLE" && shard.amountLamports > 0).sort((left, right) => left.shardId.localeCompare(right.shardId));
|
|
@@ -1562,7 +1679,6 @@ function lpWithdrawalSourceCountForClaim(position, claim) {
|
|
|
1562
1679
|
principalSourceCount += 1;
|
|
1563
1680
|
remainingPrincipalLamports -= shard.amountLamports;
|
|
1564
1681
|
}
|
|
1565
|
-
const actorRedeemablePrincipalLamports = position.actorSync?.redeemablePrincipalLamports ?? 0;
|
|
1566
1682
|
const actorRedeemablePrincipalSourceCount = position.actorSync?.redeemablePrincipalSourceCount ?? 0;
|
|
1567
1683
|
if (claim.depositPrincipalLamports > 0 && position.actorSync?.redeemableProjectionAvailable === true && actorRedeemablePrincipalLamports >= claim.depositPrincipalLamports && actorRedeemablePrincipalSourceCount > 0) {
|
|
1568
1684
|
principalSourceCount = actorRedeemablePrincipalSourceCount;
|
|
@@ -1571,7 +1687,7 @@ function lpWithdrawalSourceCountForClaim(position, claim) {
|
|
|
1571
1687
|
if (claim.earnedFeeLamports > 0 && observedEarnedFeeSourceCount < 1 && claim.allowManyToOne !== true) {
|
|
1572
1688
|
throw new PolicyValidationError(
|
|
1573
1689
|
"INVALID_WITHDRAWAL_PLAN",
|
|
1574
|
-
|
|
1690
|
+
LP_FEE_SOURCE_COUNT_UNAVAILABLE_MESSAGE
|
|
1575
1691
|
);
|
|
1576
1692
|
}
|
|
1577
1693
|
const earnedFeeSourceCount = claim.earnedFeeLamports > 0 ? Math.max(1, observedEarnedFeeSourceCount) : 0;
|
|
@@ -1737,6 +1853,30 @@ function throwIfTopUpWaitAborted(signal) {
|
|
|
1737
1853
|
if (signal?.aborted !== true) return;
|
|
1738
1854
|
throw new DOMException("LP top-up wait aborted", "AbortError");
|
|
1739
1855
|
}
|
|
1856
|
+
function throwIfWithdrawalConfirmationAborted(signal) {
|
|
1857
|
+
if (signal?.aborted !== true) return;
|
|
1858
|
+
throw new DOMException("LP withdrawal confirmation wait aborted", "AbortError");
|
|
1859
|
+
}
|
|
1860
|
+
function markLpRedemptionReconciling(state, record, options) {
|
|
1861
|
+
const reconciling = { ...record, status: "reconciling" };
|
|
1862
|
+
state.redemptions.set(record.redemptionId, reconciling);
|
|
1863
|
+
options.onRedemptionUpdate?.(reconciling);
|
|
1864
|
+
throw new LpRedemptionReconcilingError();
|
|
1865
|
+
}
|
|
1866
|
+
function isLpPositionObservationDeadlineError(error, deadlineMs, nowMs) {
|
|
1867
|
+
return error instanceof CommandError && error.code === "REJECTED_STALE_JOB" && nowMs() >= deadlineMs;
|
|
1868
|
+
}
|
|
1869
|
+
function sleepWithAbort(sleep2, delayMs, signal) {
|
|
1870
|
+
if (signal === void 0) return sleep2(delayMs);
|
|
1871
|
+
throwIfWithdrawalConfirmationAborted(signal);
|
|
1872
|
+
return new Promise((resolve, reject) => {
|
|
1873
|
+
const onAbort = () => reject(new DOMException("LP withdrawal confirmation wait aborted", "AbortError"));
|
|
1874
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1875
|
+
void sleep2(delayMs).then(resolve, reject).finally(() => {
|
|
1876
|
+
signal.removeEventListener("abort", onAbort);
|
|
1877
|
+
});
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1740
1880
|
function defaultSleep(delayMs) {
|
|
1741
1881
|
return new Promise((resolve) => {
|
|
1742
1882
|
globalThis.setTimeout(resolve, delayMs);
|
|
@@ -1793,6 +1933,6 @@ function listPositions(session) {
|
|
|
1793
1933
|
return defaultLpLifecycleClient(session).listPositions();
|
|
1794
1934
|
}
|
|
1795
1935
|
|
|
1796
|
-
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_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, reconcileFunding2 as reconcileFunding, recoverPosition, refill, refreshPosition, signLpCommandBytes, waitForTopUp, waitForWithdrawalConfirmation, withdrawFees, withdrawPosition };
|
|
1936
|
+
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 };
|
|
1797
1937
|
//# sourceMappingURL=lp.js.map
|
|
1798
1938
|
//# sourceMappingURL=lp.js.map
|