@invisible-labs/sdk 0.13.2-devnet → 0.13.3-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/dist/.invisible-sdk-build-target.json +1 -1
- package/dist/{chunk-NOKBFHDP.js → chunk-5YOVJLHU.js} +3 -3
- package/dist/{chunk-NOKBFHDP.js.map → chunk-5YOVJLHU.js.map} +1 -1
- package/dist/{chunk-M45APS7S.js → chunk-7CUZ7NWC.js} +184 -6
- package/dist/chunk-7CUZ7NWC.js.map +1 -0
- package/dist/{coordinator-EQEL23A3.js → coordinator-MLBKEKGO.js} +3 -3
- package/dist/{coordinator-EQEL23A3.js.map → coordinator-MLBKEKGO.js.map} +1 -1
- package/dist/events.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lp.d.ts +75 -2
- package/dist/lp.js +592 -180
- package/dist/lp.js.map +1 -1
- package/dist/user.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-M45APS7S.js.map +0 -1
package/dist/lp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
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
2
|
import { publicKey, assertAttested, lamports } from './chunk-TYTVF3A4.js';
|
|
3
|
-
import { requestEnvelope, CoordinatorMessageType } from './chunk-
|
|
3
|
+
import { requestEnvelope, CoordinatorMessageType } from './chunk-5YOVJLHU.js';
|
|
4
4
|
import { getSessionState } from './chunk-DOTYDYVB.js';
|
|
5
5
|
import { CommandError, TransportError, PolicyValidationError, LpLifecycleError, RoutingError, WalletError } from './chunk-A4R3DHKN.js';
|
|
6
6
|
import './chunk-VR6T6OJS.js';
|
|
@@ -320,6 +320,50 @@ function validateDestinationAddresses(destinationAddresses) {
|
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
// src/lp/positionSummary.ts
|
|
324
|
+
var LP_POSITION_SUMMARY_MAX_SHARDS = 2;
|
|
325
|
+
var LP_POSITION_SUMMARY_ANCHOR_SHARD_INDEX = 0;
|
|
326
|
+
var LP_FUNDING_QUEUED_STATUS = "FUNDING_QUEUED";
|
|
327
|
+
var LP_SHARD_STATUSES = [
|
|
328
|
+
"PREGENERATED",
|
|
329
|
+
"FUNDING_QUEUED",
|
|
330
|
+
"FUNDED",
|
|
331
|
+
"COOLING",
|
|
332
|
+
"AVAILABLE",
|
|
333
|
+
"RESERVED",
|
|
334
|
+
"RETIRED",
|
|
335
|
+
"REDEEMED"
|
|
336
|
+
];
|
|
337
|
+
function emptyLpShardStatusTotals() {
|
|
338
|
+
return Object.fromEntries(
|
|
339
|
+
LP_SHARD_STATUSES.map((status) => [status, { count: 0, lamports: 0 }])
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
function selectLpPositionSummaryShards(shards) {
|
|
343
|
+
const anchor = shards.find((shard) => shard.index === LP_POSITION_SUMMARY_ANCHOR_SHARD_INDEX);
|
|
344
|
+
const fundingQueued = shards.filter((shard) => shard.status === LP_FUNDING_QUEUED_STATUS).reduce((lowest, shard) => lowest === void 0 || shard.index < lowest.index ? shard : lowest, void 0);
|
|
345
|
+
return [anchor, fundingQueued].filter(
|
|
346
|
+
(shard, position, selected) => shard !== void 0 && selected.indexOf(shard) === position
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
function summarizeLpPosition(position) {
|
|
350
|
+
const { shards, ...identity } = position;
|
|
351
|
+
const shardTotals = emptyLpShardStatusTotals();
|
|
352
|
+
for (const shard of shards) {
|
|
353
|
+
const total = shardTotals[shard.status];
|
|
354
|
+
shardTotals[shard.status] = {
|
|
355
|
+
count: total.count + 1,
|
|
356
|
+
lamports: total.lamports + shard.amountLamports
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
...identity,
|
|
361
|
+
shardsTotalCount: shards.length,
|
|
362
|
+
shardTotals,
|
|
363
|
+
shards: selectLpPositionSummaryShards(shards)
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
323
367
|
// src/lp/coordinatorClient.ts
|
|
324
368
|
var COMMAND_TTL_MS = 3e4;
|
|
325
369
|
var LP_POSITION_OPEN_COMMAND_TTL_MS = 55e3;
|
|
@@ -330,6 +374,11 @@ var LP_POSITION_PAGE_STALL_TIMEOUT_MS = 3e4;
|
|
|
330
374
|
var LP_POSITION_SNAPSHOT_MAX_ATTEMPTS = 3;
|
|
331
375
|
var LP_SHARD_SNAPSHOT_CHANGED_MESSAGE = "LP shard snapshot changed";
|
|
332
376
|
var LP_SHARD_PAGE_INVALID_MESSAGE = "coordinator LP shard page is invalid";
|
|
377
|
+
var LP_POSITION_SUMMARY_INVALID_MESSAGE = "coordinator LP position summary is invalid";
|
|
378
|
+
var LP_POSITION_SUMMARY_VIEW = "summary";
|
|
379
|
+
var LP_LEGACY_UNSET_TARGET_SHARD_COUNT = 0;
|
|
380
|
+
var LP_REDEMPTION_HISTORY_FIRST_PAGE = "first_page";
|
|
381
|
+
var LP_REDEMPTION_HISTORY_CURSOR_INVALID_MESSAGE = "coordinator LP actor sync returned an invalid redemption history cursor";
|
|
333
382
|
var LP_POSITION_OPEN_IDENTITY_MISMATCH_MESSAGE = "Coordinator returned a different LP position identity or creation intent";
|
|
334
383
|
var LP_SHARD_SNAPSHOT_HASH_PATTERN = /^[0-9a-f]{64}$/;
|
|
335
384
|
var LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -384,6 +433,12 @@ function createLpCoordinatorClient(session, options = {}) {
|
|
|
384
433
|
options2?.signal
|
|
385
434
|
);
|
|
386
435
|
},
|
|
436
|
+
getPositionSummary(lpPositionId, auth, options2) {
|
|
437
|
+
return run(
|
|
438
|
+
(signal) => getPositionSummary(sessionRef.current, lpPositionId, auth, { ...options2, signal }),
|
|
439
|
+
options2?.signal
|
|
440
|
+
);
|
|
441
|
+
},
|
|
387
442
|
finalizeDkgBatch(input, auth) {
|
|
388
443
|
return run((signal) => finalizeDkgBatch(sessionRef.current, input, auth, { signal }));
|
|
389
444
|
},
|
|
@@ -393,6 +448,12 @@ function createLpCoordinatorClient(session, options = {}) {
|
|
|
393
448
|
reconcileFunding(lpPositionId, auth) {
|
|
394
449
|
return run((signal) => reconcileFunding(sessionRef.current, lpPositionId, auth, { signal }));
|
|
395
450
|
},
|
|
451
|
+
reconcileFundingSummary(lpPositionId, auth, options2) {
|
|
452
|
+
return run(
|
|
453
|
+
(signal) => reconcileFundingSummary(sessionRef.current, lpPositionId, auth, { ...options2, signal }),
|
|
454
|
+
options2?.signal
|
|
455
|
+
);
|
|
456
|
+
},
|
|
396
457
|
planFunding(input, auth) {
|
|
397
458
|
return run((signal) => planFunding(sessionRef.current, input, auth, { signal }));
|
|
398
459
|
},
|
|
@@ -766,8 +827,78 @@ function isAmbiguousCoordinatorRequestFailure(error) {
|
|
|
766
827
|
async function getPosition(session, lpPositionId, auth, options = {}) {
|
|
767
828
|
return hydratePositionResponse(session, lpPositionId, auth, void 0, options);
|
|
768
829
|
}
|
|
769
|
-
async function
|
|
770
|
-
const boundedOptions =
|
|
830
|
+
async function getPositionSummary(session, lpPositionId, auth, options = {}) {
|
|
831
|
+
const boundedOptions = boundedPositionObservationOptions(options);
|
|
832
|
+
const response = await requestForPosition(
|
|
833
|
+
session,
|
|
834
|
+
lpPositionId,
|
|
835
|
+
auth,
|
|
836
|
+
"position_get",
|
|
837
|
+
{ case: "positionGet", value: { view: LP_POSITION_SUMMARY_VIEW } },
|
|
838
|
+
boundedOptions
|
|
839
|
+
);
|
|
840
|
+
return completePositionSummary(session, lpPositionId, auth, response, boundedOptions);
|
|
841
|
+
}
|
|
842
|
+
async function reconcileFundingSummary(session, lpPositionId, auth, options = {}) {
|
|
843
|
+
const boundedOptions = boundedPositionObservationOptions(options);
|
|
844
|
+
const response = await requestForPosition(
|
|
845
|
+
session,
|
|
846
|
+
lpPositionId,
|
|
847
|
+
auth,
|
|
848
|
+
"reconcile_funding",
|
|
849
|
+
{ case: "reconcileFunding", value: { view: LP_POSITION_SUMMARY_VIEW } },
|
|
850
|
+
boundedOptions
|
|
851
|
+
);
|
|
852
|
+
return completePositionSummary(session, lpPositionId, auth, response, boundedOptions);
|
|
853
|
+
}
|
|
854
|
+
async function completePositionSummary(session, lpPositionId, auth, firstResponse, options) {
|
|
855
|
+
if (firstResponse.case !== "positionSummary")
|
|
856
|
+
throw new CommandError("REJECTED_STATE", LP_POSITION_SUMMARY_INVALID_MESSAGE);
|
|
857
|
+
const first = mapPositionSummary(firstResponse.value, lpPositionId, auth);
|
|
858
|
+
if (options.redemptionHistory === LP_REDEMPTION_HISTORY_FIRST_PAGE) return first;
|
|
859
|
+
const historyByRedemptionId = /* @__PURE__ */ new Map();
|
|
860
|
+
for (const history of first.actorSync?.redemptionHistory ?? [])
|
|
861
|
+
historyByRedemptionId.set(history.redemptionId, history);
|
|
862
|
+
let page = first;
|
|
863
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
864
|
+
while (page.actorSync?.redemptionHistoryHasMore === true) {
|
|
865
|
+
const cursor = page.actorSync.redemptionHistoryNextCursor;
|
|
866
|
+
if (cursor === void 0 || seenCursors.has(cursor)) {
|
|
867
|
+
throw new CommandError("REJECTED_STATE", LP_REDEMPTION_HISTORY_CURSOR_INVALID_MESSAGE);
|
|
868
|
+
}
|
|
869
|
+
seenCursors.add(cursor);
|
|
870
|
+
const nextResponse = await requestForPosition(
|
|
871
|
+
session,
|
|
872
|
+
lpPositionId,
|
|
873
|
+
auth,
|
|
874
|
+
"position_get",
|
|
875
|
+
{
|
|
876
|
+
case: "positionGet",
|
|
877
|
+
value: { view: LP_POSITION_SUMMARY_VIEW, redemption_history_cursor: cursor }
|
|
878
|
+
},
|
|
879
|
+
options
|
|
880
|
+
);
|
|
881
|
+
if (nextResponse.case !== "positionSummary")
|
|
882
|
+
throw new CommandError("REJECTED_STATE", LP_POSITION_SUMMARY_INVALID_MESSAGE);
|
|
883
|
+
page = mapPositionSummary(nextResponse.value, lpPositionId, auth);
|
|
884
|
+
validateLpPositionFeePolicy(page, first);
|
|
885
|
+
for (const history of page.actorSync?.redemptionHistory ?? [])
|
|
886
|
+
historyByRedemptionId.set(history.redemptionId, history);
|
|
887
|
+
}
|
|
888
|
+
lpPositionPageRequestOptions(options);
|
|
889
|
+
if (first.actorSync === void 0) return first;
|
|
890
|
+
return {
|
|
891
|
+
...first,
|
|
892
|
+
actorSync: {
|
|
893
|
+
...first.actorSync,
|
|
894
|
+
redemptionHistory: [...historyByRedemptionId.values()],
|
|
895
|
+
redemptionHistoryHasMore: false,
|
|
896
|
+
redemptionHistoryNextCursor: void 0
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
function boundedPositionObservationOptions(options) {
|
|
901
|
+
return {
|
|
771
902
|
...options,
|
|
772
903
|
deadlineMs: options.deadlineMs ?? Date.now() + LP_POSITION_HYDRATION_MAX_MS,
|
|
773
904
|
timeoutMs: Math.min(
|
|
@@ -775,6 +906,52 @@ async function hydratePositionResponse(session, lpPositionId, auth, initialRespo
|
|
|
775
906
|
LP_POSITION_PAGE_STALL_TIMEOUT_MS
|
|
776
907
|
)
|
|
777
908
|
};
|
|
909
|
+
}
|
|
910
|
+
function mapPositionSummary(summary, lpPositionId, auth) {
|
|
911
|
+
const invalid = () => {
|
|
912
|
+
throw new CommandError("REJECTED_STATE", LP_POSITION_SUMMARY_INVALID_MESSAGE);
|
|
913
|
+
};
|
|
914
|
+
const total = summary.shards_total_count;
|
|
915
|
+
const effectiveTargetShardCount = summary.target_shard_count === LP_LEGACY_UNSET_TARGET_SHARD_COUNT ? total : summary.target_shard_count;
|
|
916
|
+
if (summary.lp_position_id !== lpPositionId || bytesToHex(summary.auth_public_key) !== bytesToHex(auth.authPublicKey) || !Number.isInteger(total) || total < 0 || total > LP_MAX_TOTAL_SHARDS || total > effectiveTargetShardCount || summary.shards.length > LP_POSITION_SUMMARY_MAX_SHARDS)
|
|
917
|
+
invalid();
|
|
918
|
+
const seenIndexes = /* @__PURE__ */ new Set();
|
|
919
|
+
for (const shard of summary.shards) {
|
|
920
|
+
if (shard.index >= total || seenIndexes.has(shard.index) || shard.lp_position_id !== lpPositionId || shard.shard_id !== `${lpPositionId}:shard:${shard.index}`)
|
|
921
|
+
invalid();
|
|
922
|
+
seenIndexes.add(shard.index);
|
|
923
|
+
}
|
|
924
|
+
const shardTotals = emptyLpShardStatusTotals();
|
|
925
|
+
let countSum = 0;
|
|
926
|
+
for (const [status, statusTotal] of Object.entries(summary.shard_totals)) {
|
|
927
|
+
shardTotals[mapStatus(status)] = { count: statusTotal.count, lamports: statusTotal.lamports };
|
|
928
|
+
countSum += statusTotal.count;
|
|
929
|
+
}
|
|
930
|
+
if (countSum !== total) invalid();
|
|
931
|
+
const mapped = {
|
|
932
|
+
feePolicy: summary.fee_policy === void 0 ? void 0 : validateLpFeePolicy(summary.fee_policy),
|
|
933
|
+
lpFeePolicyVersion: summary.lp_fee_policy_version,
|
|
934
|
+
id: summary.lp_position_id,
|
|
935
|
+
status: summary.status,
|
|
936
|
+
targetShardCount: summary.target_shard_count,
|
|
937
|
+
authPublicKey: bytesToHex(summary.auth_public_key),
|
|
938
|
+
refillPublicKey: bytesToHex(summary.refill_public_key),
|
|
939
|
+
withdrawalCommitment: bytesToHex(summary.redemption_commitment),
|
|
940
|
+
committedLamports: summary.committed_lamports,
|
|
941
|
+
earnedLamports: summary.earned_lamports,
|
|
942
|
+
refillThreshold: summary.refill_threshold,
|
|
943
|
+
createdAt: summary.created_at_ms,
|
|
944
|
+
redemptionPermission: mapLpRedemptionPermission(summary.redemption_permission),
|
|
945
|
+
...summary.actor_sync === void 0 ? {} : { actorSync: mapLpActorSync(summary.actor_sync) },
|
|
946
|
+
shardsTotalCount: total,
|
|
947
|
+
shardTotals,
|
|
948
|
+
shards: summary.shards.map(mapShard)
|
|
949
|
+
};
|
|
950
|
+
validateLpPositionFeePolicy(mapped);
|
|
951
|
+
return mapped;
|
|
952
|
+
}
|
|
953
|
+
async function hydratePositionResponse(session, lpPositionId, auth, initialResponse, options = {}) {
|
|
954
|
+
const boundedOptions = boundedPositionObservationOptions(options);
|
|
778
955
|
for (let attempt = 0; attempt < LP_POSITION_SNAPSHOT_MAX_ATTEMPTS; attempt += 1) {
|
|
779
956
|
try {
|
|
780
957
|
const response = initialResponse ?? await requestForPosition(
|
|
@@ -826,10 +1003,7 @@ async function hydratePositionResponse(session, lpPositionId, auth, initialRespo
|
|
|
826
1003
|
while (historyPage.actor_sync?.redemption_history_has_more === true) {
|
|
827
1004
|
const cursor = historyPage.actor_sync.redemption_history_next_cursor;
|
|
828
1005
|
if (cursor === void 0 || seenCursors.has(cursor)) {
|
|
829
|
-
throw new CommandError(
|
|
830
|
-
"REJECTED_STATE",
|
|
831
|
-
"coordinator LP actor sync returned an invalid redemption history cursor"
|
|
832
|
-
);
|
|
1006
|
+
throw new CommandError("REJECTED_STATE", LP_REDEMPTION_HISTORY_CURSOR_INVALID_MESSAGE);
|
|
833
1007
|
}
|
|
834
1008
|
seenCursors.add(cursor);
|
|
835
1009
|
const nextResponse = await requestForPosition(
|
|
@@ -1368,7 +1542,7 @@ function randomBytes(length) {
|
|
|
1368
1542
|
return bytes;
|
|
1369
1543
|
}
|
|
1370
1544
|
function loadProtocol() {
|
|
1371
|
-
protocolPromise ??= import('./coordinator-
|
|
1545
|
+
protocolPromise ??= import('./coordinator-MLBKEKGO.js');
|
|
1372
1546
|
return protocolPromise;
|
|
1373
1547
|
}
|
|
1374
1548
|
|
|
@@ -1693,6 +1867,10 @@ var LP_WITHDRAWAL_CONFIRMATION_TIMEOUT_MS = 15 * 6e4;
|
|
|
1693
1867
|
var LP_WITHDRAWAL_READINESS_RETRY_DELAY_MS = 1e3;
|
|
1694
1868
|
var LP_WITHDRAWAL_READINESS_RETRY_ATTEMPTS = 30;
|
|
1695
1869
|
var LP_TOP_UP_WAIT_POLL_INTERVAL_MS = 1e3;
|
|
1870
|
+
var LP_POSITION_SUMMARY_UNSUPPORTED_COORDINATOR_CODE = "ERR_INVALID_PAYLOAD";
|
|
1871
|
+
var LP_POSITION_SUMMARY_SCHEMA_REJECTION_PREFIX = "json schema validation failed: ";
|
|
1872
|
+
var LP_POSITION_SUMMARY_SCHEMA_REJECTION_VIEW_TOKEN = '"view":"summary"';
|
|
1873
|
+
var summaryUnsupportedSessions = /* @__PURE__ */ new WeakSet();
|
|
1696
1874
|
var LP_REDEMPTION_HISTORY_OPEN_STATES = /* @__PURE__ */ new Set([
|
|
1697
1875
|
"requested",
|
|
1698
1876
|
"match_requested",
|
|
@@ -1710,6 +1888,7 @@ var WITHDRAWAL_HISTORY_MISMATCH_MESSAGE = "LP redemption history does not match
|
|
|
1710
1888
|
var LP_REDEMPTION_PERMISSION_UNAVAILABLE_MESSAGE = "LP redemption is unavailable until the coordinator confirms permission";
|
|
1711
1889
|
var LP_WITHDRAWAL_UNRESOLVED_FUNDING_MESSAGE = "LP position has unresolved funding shards before redemption";
|
|
1712
1890
|
var UNSUPPORTED_FEE_POLICY_MESSAGE = "LP fee policy overrides are not advertised by the coordinator";
|
|
1891
|
+
var LP_WITHDRAWAL_FULL_INVENTORY_REQUIRED_MESSAGE = "LP withdrawal plan requires the full shard inventory";
|
|
1713
1892
|
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";
|
|
1714
1893
|
var LpRedemptionReconcilingError = class extends LpLifecycleError {
|
|
1715
1894
|
constructor() {
|
|
@@ -1729,16 +1908,24 @@ function isLpRedemptionReconcilingError(error) {
|
|
|
1729
1908
|
function isLpPositionAuthMissingError(error) {
|
|
1730
1909
|
return error instanceof LpPositionAuthMissingError || error instanceof Error && error.message === LP_MISSING_POSITION_CODE_MESSAGE;
|
|
1731
1910
|
}
|
|
1911
|
+
function isLpPositionSummaryUnsupportedError(error) {
|
|
1912
|
+
if (!(error instanceof CommandError) || error.coordinatorCode !== LP_POSITION_SUMMARY_UNSUPPORTED_COORDINATOR_CODE)
|
|
1913
|
+
return false;
|
|
1914
|
+
const message = error.coordinatorMessage ?? error.message;
|
|
1915
|
+
return message.startsWith(LP_POSITION_SUMMARY_SCHEMA_REJECTION_PREFIX) && message.includes(LP_POSITION_SUMMARY_SCHEMA_REJECTION_VIEW_TOKEN);
|
|
1916
|
+
}
|
|
1917
|
+
function isTransientLpObservationError(error) {
|
|
1918
|
+
return error instanceof CommandError && (error.code === "RETRYABLE_BUSY" || error.code === "REJECTED_STALE_JOB" && error.coordinatorCode === void 0);
|
|
1919
|
+
}
|
|
1920
|
+
var LpPositionSummaryUnsupportedProbe = class extends Error {
|
|
1921
|
+
};
|
|
1732
1922
|
function previewLpWithdrawalPlan(position, args = {}) {
|
|
1733
1923
|
validateLpPositionFeePolicy(position);
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
allowManyToOne: args.allowManyToOne
|
|
1740
|
-
})
|
|
1741
|
-
};
|
|
1924
|
+
return previewWithdrawalFromBasis(fullWithdrawalBasis(position), args);
|
|
1925
|
+
}
|
|
1926
|
+
function previewLpWithdrawalPlanFromSummary(summary, args = {}) {
|
|
1927
|
+
validateLpPositionFeePolicy(summary);
|
|
1928
|
+
return previewWithdrawalFromBasis(summaryWithdrawalBasis(summary), args);
|
|
1742
1929
|
}
|
|
1743
1930
|
var dkgAdmissions = /* @__PURE__ */ new WeakMap();
|
|
1744
1931
|
var LP_DKG_BUSY_MESSAGE = "LP DKG session capacity is busy; wait for the active batch to finish";
|
|
@@ -1845,7 +2032,7 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1845
2032
|
const auth = requireAuth(positionId);
|
|
1846
2033
|
return rememberPosition(await client.getPosition(positionId, auth));
|
|
1847
2034
|
};
|
|
1848
|
-
const executeWithdrawalAfterFundingReadiness = async (
|
|
2035
|
+
const executeWithdrawalAfterFundingReadiness = async (input, auth, reconcile) => {
|
|
1849
2036
|
for (let attempt = 0; ; attempt += 1) {
|
|
1850
2037
|
try {
|
|
1851
2038
|
return await client.executeWithdrawal(input, auth);
|
|
@@ -1855,8 +2042,148 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1855
2042
|
throw error;
|
|
1856
2043
|
}
|
|
1857
2044
|
await sleep2(LP_WITHDRAWAL_READINESS_RETRY_DELAY_MS);
|
|
1858
|
-
await
|
|
2045
|
+
await reconcile().catch(() => void 0);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
const recoverPosition2 = async (args) => {
|
|
2050
|
+
assertUsable();
|
|
2051
|
+
const auth = await deriveLpPositionCodeAuth(args.code);
|
|
2052
|
+
rememberAuth(auth);
|
|
2053
|
+
const position = rememberPosition(
|
|
2054
|
+
await client.getPosition(auth.lpPositionId, auth, {
|
|
2055
|
+
deadlineMs: args.deadlineMs,
|
|
2056
|
+
signal: args.signal
|
|
2057
|
+
})
|
|
2058
|
+
);
|
|
2059
|
+
assertPositionMatchesAuth(position, auth);
|
|
2060
|
+
return position;
|
|
2061
|
+
};
|
|
2062
|
+
const withSummarySupport = async (summaryRead, fullRead) => {
|
|
2063
|
+
const session2 = currentSession;
|
|
2064
|
+
if (summaryUnsupportedSessions.has(session2)) return fullRead();
|
|
2065
|
+
try {
|
|
2066
|
+
return await summaryRead();
|
|
2067
|
+
} catch (error) {
|
|
2068
|
+
if (!isLpPositionSummaryUnsupportedError(error)) throw error;
|
|
2069
|
+
summaryUnsupportedSessions.add(session2);
|
|
2070
|
+
}
|
|
2071
|
+
return fullRead();
|
|
2072
|
+
};
|
|
2073
|
+
const executeWithdrawalPlan = async (positionId, args, auth, before, plan, reconcile) => {
|
|
2074
|
+
if (plan.kind === "existing") {
|
|
2075
|
+
state.redemptions.set(plan.execution.withdrawalId, plan.redemption);
|
|
2076
|
+
return { execution: plan.execution, redemption: plan.redemption, submitted: false };
|
|
2077
|
+
}
|
|
2078
|
+
const preview = plan.preview;
|
|
2079
|
+
const requestedAtMs = nowMs();
|
|
2080
|
+
const execution = await executeWithdrawalAfterFundingReadiness(
|
|
2081
|
+
{
|
|
2082
|
+
lpPositionId: positionId,
|
|
2083
|
+
destinationAddresses: args.destinationAddresses,
|
|
2084
|
+
depositPrincipalLamports: args.withdrawalMode === "max_available" ? 0 : preview.depositPrincipalLamports,
|
|
2085
|
+
earnedFeeLamports: args.withdrawalMode === "max_available" ? 0 : preview.earnedFeeLamports,
|
|
2086
|
+
withdrawalMode: args.withdrawalMode,
|
|
2087
|
+
requestedAtMs,
|
|
2088
|
+
feePolicyHash: before.feePolicy?.policy_hash,
|
|
2089
|
+
feeBasisRevision: before.actorSync?.feeBasisRevision,
|
|
2090
|
+
allowManyToOne: args.allowManyToOne === true || preview?.sourceCount === 1
|
|
2091
|
+
},
|
|
2092
|
+
auth,
|
|
2093
|
+
reconcile
|
|
2094
|
+
);
|
|
2095
|
+
const acceptedLamports = execution.acceptedLamports;
|
|
2096
|
+
if (args.withdrawalMode === "max_available" && acceptedLamports === void 0) {
|
|
2097
|
+
throw new PolicyValidationError(
|
|
2098
|
+
"INVALID_WITHDRAWAL_PLAN",
|
|
2099
|
+
"LP redemption response did not include the sealed accepted amount"
|
|
2100
|
+
);
|
|
2101
|
+
}
|
|
2102
|
+
const acceptedAmount = acceptedLamports ?? preview.depositPrincipalLamports + preview.earnedFeeLamports;
|
|
2103
|
+
const redemption = buildLpRedemptionRecord({
|
|
2104
|
+
execution,
|
|
2105
|
+
position: before,
|
|
2106
|
+
destinationAddresses: args.destinationAddresses,
|
|
2107
|
+
acceptedLamports: acceptedAmount,
|
|
2108
|
+
requestedTargetLamports: (before.actorSync?.withdrawalRequestedLamports ?? 0) + acceptedAmount,
|
|
2109
|
+
landedBaselineLamports: before.actorSync?.withdrawalLandedLamports ?? 0,
|
|
2110
|
+
landedFeeBaselineLamports: before.actorSync?.withdrawalLandedFeeLamports ?? 0,
|
|
2111
|
+
txSignatureBaseline: before.actorSync?.withdrawalTxHashes ?? [],
|
|
2112
|
+
nowMs: nowMs()
|
|
2113
|
+
});
|
|
2114
|
+
state.redemptions.set(execution.withdrawalId, redemption);
|
|
2115
|
+
return { execution, redemption, submitted: true };
|
|
2116
|
+
};
|
|
2117
|
+
const withdrawPosition2 = async (positionId, args) => {
|
|
2118
|
+
assertUsable();
|
|
2119
|
+
validateExplicitWithdrawalInput(args);
|
|
2120
|
+
validateWithdrawalDestinations(args);
|
|
2121
|
+
assertAttested(currentSession);
|
|
2122
|
+
const auth = requireAuth(positionId);
|
|
2123
|
+
const before = rememberPosition(await client.reconcileFunding(positionId, auth));
|
|
2124
|
+
const plan = planWithdrawal(before, fullWithdrawalBasis(before), args);
|
|
2125
|
+
const result = await executeWithdrawalPlan(
|
|
2126
|
+
positionId,
|
|
2127
|
+
args,
|
|
2128
|
+
auth,
|
|
2129
|
+
before,
|
|
2130
|
+
plan,
|
|
2131
|
+
() => client.reconcileFunding(positionId, auth)
|
|
2132
|
+
);
|
|
2133
|
+
if (!result.submitted) return { ...result, position: before };
|
|
2134
|
+
const position = await client.getPosition(positionId, auth).then((refreshed) => rememberPosition(refreshed)).catch(() => before);
|
|
2135
|
+
const redemption = { ...result.redemption, lpPositionId: position.id };
|
|
2136
|
+
state.redemptions.set(result.execution.withdrawalId, redemption);
|
|
2137
|
+
return { execution: result.execution, position, redemption };
|
|
2138
|
+
};
|
|
2139
|
+
const observeWithdrawalConfirmation = async (positionId, execution, options, observe, reconcileRecord, onView) => {
|
|
2140
|
+
let record = resolveWithdrawalRecord({
|
|
2141
|
+
state,
|
|
2142
|
+
positionId,
|
|
2143
|
+
execution,
|
|
2144
|
+
options
|
|
2145
|
+
});
|
|
2146
|
+
state.redemptions.set(record.redemptionId, record);
|
|
2147
|
+
const deadlineMs = options.deadlineMs ?? nowMs() + (runtime.withdrawalConfirmationTimeoutMs ?? LP_WITHDRAWAL_CONFIRMATION_TIMEOUT_MS);
|
|
2148
|
+
const pollIntervalMs = runtime.withdrawalConfirmationPollIntervalMs ?? LP_WITHDRAWAL_CONFIRMATION_POLL_INTERVAL_MS;
|
|
2149
|
+
for (; ; ) {
|
|
2150
|
+
throwIfWithdrawalConfirmationAborted(options.signal);
|
|
2151
|
+
if (nowMs() >= deadlineMs) {
|
|
2152
|
+
markLpRedemptionReconciling(state, record, options);
|
|
2153
|
+
}
|
|
2154
|
+
const remainingMs = deadlineMs - nowMs();
|
|
2155
|
+
if (remainingMs <= 0) {
|
|
2156
|
+
markLpRedemptionReconciling(state, record, options);
|
|
2157
|
+
}
|
|
2158
|
+
let view;
|
|
2159
|
+
try {
|
|
2160
|
+
view = await observe(deadlineMs);
|
|
2161
|
+
} catch (error) {
|
|
2162
|
+
if (isLpPositionObservationDeadlineError(error, deadlineMs, nowMs)) {
|
|
2163
|
+
markLpRedemptionReconciling(state, record, options);
|
|
2164
|
+
}
|
|
2165
|
+
throw error;
|
|
2166
|
+
}
|
|
2167
|
+
throwIfWithdrawalConfirmationAborted(options.signal);
|
|
2168
|
+
onView?.(view);
|
|
2169
|
+
const reconciled = reconcileRecord(record, view);
|
|
2170
|
+
record = reconciled;
|
|
2171
|
+
state.redemptions.set(record.redemptionId, reconciled);
|
|
2172
|
+
options.onRedemptionUpdate?.(reconciled);
|
|
2173
|
+
if (reconciled.status === "confirmed") {
|
|
2174
|
+
return {
|
|
2175
|
+
withdrawalId: execution.withdrawalId,
|
|
2176
|
+
txSignatures: reconciled.txSignatures,
|
|
2177
|
+
redeemedLamports: reconciled.redeemedLamports
|
|
2178
|
+
};
|
|
1859
2179
|
}
|
|
2180
|
+
if (reconciled.status === "failed") {
|
|
2181
|
+
throw new Error(reconciled.error ?? WITHDRAWAL_NO_LAMPORTS_MESSAGE);
|
|
2182
|
+
}
|
|
2183
|
+
if (nowMs() >= deadlineMs) {
|
|
2184
|
+
markLpRedemptionReconciling(state, reconciled, options);
|
|
2185
|
+
}
|
|
2186
|
+
await sleepWithAbort(sleep2, pollIntervalMs, options.signal);
|
|
1860
2187
|
}
|
|
1861
2188
|
};
|
|
1862
2189
|
const completeDkgBatch2 = async (positionId, options = {}, hasReservation = false) => {
|
|
@@ -1979,18 +2306,23 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
1979
2306
|
args.onPositionCode?.({ positionId, lpPositionCode: auth.code });
|
|
1980
2307
|
return { positionId, lpPositionCode: auth.code, position };
|
|
1981
2308
|
},
|
|
1982
|
-
|
|
2309
|
+
recoverPosition: recoverPosition2,
|
|
2310
|
+
async recoverPositionSummary(args) {
|
|
1983
2311
|
assertUsable();
|
|
1984
2312
|
const auth = await deriveLpPositionCodeAuth(args.code);
|
|
1985
2313
|
rememberAuth(auth);
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2314
|
+
return withSummarySupport(
|
|
2315
|
+
async () => {
|
|
2316
|
+
const summary = await client.getPositionSummary(auth.lpPositionId, auth, {
|
|
2317
|
+
deadlineMs: args.deadlineMs,
|
|
2318
|
+
signal: args.signal,
|
|
2319
|
+
redemptionHistory: "first_page"
|
|
2320
|
+
});
|
|
2321
|
+
assertPositionMatchesAuth(summary, auth);
|
|
2322
|
+
return summary;
|
|
2323
|
+
},
|
|
2324
|
+
async () => summarizeLpPosition(await recoverPosition2(args))
|
|
1991
2325
|
);
|
|
1992
|
-
assertPositionMatchesAuth(position, auth);
|
|
1993
|
-
return position;
|
|
1994
2326
|
},
|
|
1995
2327
|
confirmPositionCodeSaved(_positionId) {
|
|
1996
2328
|
assertUsable();
|
|
@@ -2129,154 +2461,130 @@ function createLpLifecycleClient(session, runtime = {}) {
|
|
|
2129
2461
|
const auth = requireAuth(positionId);
|
|
2130
2462
|
return rememberPosition(await client.reconcileFunding(positionId, auth));
|
|
2131
2463
|
},
|
|
2132
|
-
|
|
2464
|
+
withdrawPosition: withdrawPosition2,
|
|
2465
|
+
async reconcileFundingSummary(positionId) {
|
|
2466
|
+
assertUsable();
|
|
2467
|
+
assertAttested(currentSession);
|
|
2468
|
+
const auth = requireAuth(positionId);
|
|
2469
|
+
return withSummarySupport(
|
|
2470
|
+
() => client.reconcileFundingSummary(positionId, auth, { redemptionHistory: "first_page" }),
|
|
2471
|
+
async () => summarizeLpPosition(rememberPosition(await client.reconcileFunding(positionId, auth)))
|
|
2472
|
+
);
|
|
2473
|
+
},
|
|
2474
|
+
async refreshPositionSummary(positionId, options = {}) {
|
|
2475
|
+
assertUsable();
|
|
2476
|
+
const auth = requireAuth(positionId);
|
|
2477
|
+
return withSummarySupport(
|
|
2478
|
+
() => client.getPositionSummary(positionId, auth, {
|
|
2479
|
+
redemptionHistory: options.redemptionHistory
|
|
2480
|
+
}),
|
|
2481
|
+
async () => summarizeLpPosition(await refreshPosition2(positionId))
|
|
2482
|
+
);
|
|
2483
|
+
},
|
|
2484
|
+
async withdrawPositionSummary(positionId, args) {
|
|
2133
2485
|
assertUsable();
|
|
2134
2486
|
validateExplicitWithdrawalInput(args);
|
|
2135
2487
|
validateWithdrawalDestinations(args);
|
|
2136
2488
|
assertAttested(currentSession);
|
|
2137
2489
|
const auth = requireAuth(positionId);
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
}
|
|
2145
|
-
const existingRedemption = findOpenRedemptionHistory(before, args);
|
|
2146
|
-
if (existingRedemption !== void 0) {
|
|
2147
|
-
const execution2 = {
|
|
2148
|
-
feePolicyHash: existingRedemption.feePolicyHash,
|
|
2149
|
-
feeBasisRevision: existingRedemption.feeBasisRevision,
|
|
2150
|
-
withdrawalId: existingRedemption.redemptionId,
|
|
2151
|
-
txSignatures: [...existingRedemption.txSignatures],
|
|
2152
|
-
acceptedLamports: existingRedemption.acceptedLamports,
|
|
2153
|
-
acceptedDepositPrincipalLamports: existingRedemption.acceptedDepositPrincipalLamports,
|
|
2154
|
-
acceptedEarnedFeeLamports: existingRedemption.acceptedEarnedFeeLamports
|
|
2155
|
-
};
|
|
2156
|
-
const redemption2 = {
|
|
2157
|
-
...buildLpRedemptionRecord({
|
|
2158
|
-
execution: execution2,
|
|
2159
|
-
position: before,
|
|
2160
|
-
destinationAddresses: existingRedemption.destinationAddresses,
|
|
2161
|
-
acceptedLamports: existingRedemption.acceptedLamports,
|
|
2162
|
-
requestedTargetLamports: existingRedemption.acceptedLamports,
|
|
2163
|
-
landedBaselineLamports: 0,
|
|
2164
|
-
landedFeeBaselineLamports: 0,
|
|
2165
|
-
txSignatureBaseline: [],
|
|
2166
|
-
nowMs: existingRedemption.createdAtMs
|
|
2167
|
-
}),
|
|
2168
|
-
redeemedLamports: existingRedemption.landedLamports,
|
|
2169
|
-
coordinatorStateVersion: existingRedemption.stateVersion
|
|
2490
|
+
const viaFullPosition = async () => {
|
|
2491
|
+
const result2 = await withdrawPosition2(positionId, args);
|
|
2492
|
+
return {
|
|
2493
|
+
execution: result2.execution,
|
|
2494
|
+
summary: summarizeLpPosition(result2.position),
|
|
2495
|
+
redemption: result2.redemption
|
|
2170
2496
|
};
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2497
|
+
};
|
|
2498
|
+
let before;
|
|
2499
|
+
let plan;
|
|
2500
|
+
try {
|
|
2501
|
+
const reconciled = await withSummarySupport(
|
|
2502
|
+
() => client.reconcileFundingSummary(positionId, auth),
|
|
2503
|
+
async () => void 0
|
|
2504
|
+
);
|
|
2505
|
+
if (reconciled === void 0) return viaFullPosition();
|
|
2506
|
+
before = reconciled;
|
|
2507
|
+
assertPositionMatchesAuth(before, auth);
|
|
2508
|
+
plan = planWithdrawal(before, summaryWithdrawalBasis(before), args);
|
|
2509
|
+
} catch (error) {
|
|
2510
|
+
if (error instanceof LpWithdrawalNeedsFullInventoryError) return viaFullPosition();
|
|
2511
|
+
throw error;
|
|
2184
2512
|
}
|
|
2185
|
-
const
|
|
2513
|
+
const result = await executeWithdrawalPlan(
|
|
2186
2514
|
positionId,
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
withdrawalMode: args.withdrawalMode,
|
|
2193
|
-
requestedAtMs,
|
|
2194
|
-
feePolicyHash: before.feePolicy?.policy_hash,
|
|
2195
|
-
feeBasisRevision: before.actorSync?.feeBasisRevision,
|
|
2196
|
-
allowManyToOne: args.allowManyToOne === true || preview?.sourceCount === 1
|
|
2197
|
-
},
|
|
2198
|
-
auth
|
|
2515
|
+
args,
|
|
2516
|
+
auth,
|
|
2517
|
+
before,
|
|
2518
|
+
plan,
|
|
2519
|
+
() => client.reconcileFundingSummary(positionId, auth)
|
|
2199
2520
|
);
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
"INVALID_WITHDRAWAL_PLAN",
|
|
2204
|
-
"LP redemption response did not include the sealed accepted amount"
|
|
2205
|
-
);
|
|
2206
|
-
}
|
|
2207
|
-
const acceptedAmount = acceptedLamports ?? preview.depositPrincipalLamports + preview.earnedFeeLamports;
|
|
2208
|
-
const pendingRedemption = buildLpRedemptionRecord({
|
|
2209
|
-
execution,
|
|
2210
|
-
position: before,
|
|
2211
|
-
destinationAddresses: args.destinationAddresses,
|
|
2212
|
-
acceptedLamports: acceptedAmount,
|
|
2213
|
-
requestedTargetLamports: (before.actorSync?.withdrawalRequestedLamports ?? 0) + acceptedAmount,
|
|
2214
|
-
landedBaselineLamports: before.actorSync?.withdrawalLandedLamports ?? 0,
|
|
2215
|
-
landedFeeBaselineLamports: before.actorSync?.withdrawalLandedFeeLamports ?? 0,
|
|
2216
|
-
txSignatureBaseline: before.actorSync?.withdrawalTxHashes ?? [],
|
|
2217
|
-
nowMs: nowMs()
|
|
2218
|
-
});
|
|
2219
|
-
state.redemptions.set(execution.withdrawalId, pendingRedemption);
|
|
2220
|
-
const position = await client.getPosition(positionId, auth).then((refreshed) => rememberPosition(refreshed)).catch(() => before);
|
|
2221
|
-
const redemption = { ...pendingRedemption, lpPositionId: position.id };
|
|
2222
|
-
state.redemptions.set(execution.withdrawalId, redemption);
|
|
2223
|
-
return { execution, position, redemption };
|
|
2521
|
+
if (!result.submitted) return { ...result, summary: before };
|
|
2522
|
+
const summary = await client.getPositionSummary(positionId, auth).catch(() => before);
|
|
2523
|
+
return { execution: result.execution, summary, redemption: result.redemption };
|
|
2224
2524
|
},
|
|
2225
2525
|
async waitForWithdrawalConfirmation(positionId, execution, options = {}) {
|
|
2226
2526
|
assertUsable();
|
|
2227
2527
|
const auth = requireAuth(positionId);
|
|
2228
|
-
|
|
2229
|
-
state,
|
|
2528
|
+
return observeWithdrawalConfirmation(
|
|
2230
2529
|
positionId,
|
|
2231
2530
|
execution,
|
|
2232
|
-
options
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2531
|
+
options,
|
|
2532
|
+
async (deadlineMs) => rememberPosition(
|
|
2533
|
+
await client.getPosition(positionId, auth, { deadlineMs, signal: options.signal })
|
|
2534
|
+
),
|
|
2535
|
+
reconcileLpRedemptionFromActorSync,
|
|
2536
|
+
options.onPosition
|
|
2537
|
+
);
|
|
2538
|
+
},
|
|
2539
|
+
async waitForWithdrawalConfirmationSummary(positionId, execution, options = {}) {
|
|
2540
|
+
assertUsable();
|
|
2541
|
+
const auth = requireAuth(positionId);
|
|
2542
|
+
const { onSummary, ...observation } = options;
|
|
2543
|
+
const session2 = currentSession;
|
|
2544
|
+
const observeFull = () => observeWithdrawalConfirmation(
|
|
2545
|
+
positionId,
|
|
2546
|
+
execution,
|
|
2547
|
+
observation,
|
|
2548
|
+
async (deadlineMs) => rememberPosition(
|
|
2549
|
+
await client.getPosition(positionId, auth, { deadlineMs, signal: options.signal })
|
|
2550
|
+
),
|
|
2551
|
+
reconcileLpRedemptionFromCorrelatedHistory,
|
|
2552
|
+
onSummary === void 0 ? void 0 : (position) => onSummary(summarizeLpPosition(position))
|
|
2553
|
+
);
|
|
2554
|
+
if (summaryUnsupportedSessions.has(session2)) return observeFull();
|
|
2236
2555
|
const pollIntervalMs = runtime.withdrawalConfirmationPollIntervalMs ?? LP_WITHDRAWAL_CONFIRMATION_POLL_INTERVAL_MS;
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
const remainingMs = deadlineMs - nowMs();
|
|
2243
|
-
if (remainingMs <= 0) {
|
|
2244
|
-
markLpRedemptionReconciling(state, record, options);
|
|
2245
|
-
}
|
|
2246
|
-
let position;
|
|
2247
|
-
try {
|
|
2248
|
-
position = rememberPosition(
|
|
2249
|
-
await client.getPosition(positionId, auth, {
|
|
2556
|
+
let summaryObserved = false;
|
|
2557
|
+
const observeSummary = async (deadlineMs) => {
|
|
2558
|
+
for (; ; ) {
|
|
2559
|
+
try {
|
|
2560
|
+
const summary = await client.getPositionSummary(positionId, auth, {
|
|
2250
2561
|
deadlineMs,
|
|
2251
2562
|
signal: options.signal
|
|
2252
|
-
})
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2563
|
+
});
|
|
2564
|
+
summaryObserved = true;
|
|
2565
|
+
return summary;
|
|
2566
|
+
} catch (error) {
|
|
2567
|
+
if (!summaryObserved && isLpPositionSummaryUnsupportedError(error)) {
|
|
2568
|
+
summaryUnsupportedSessions.add(session2);
|
|
2569
|
+
throw new LpPositionSummaryUnsupportedProbe();
|
|
2570
|
+
}
|
|
2571
|
+
if (!isTransientLpObservationError(error) || nowMs() >= deadlineMs) throw error;
|
|
2572
|
+
await sleepWithAbort(sleep2, pollIntervalMs, options.signal);
|
|
2257
2573
|
}
|
|
2258
|
-
throw error;
|
|
2259
|
-
}
|
|
2260
|
-
throwIfWithdrawalConfirmationAborted(options.signal);
|
|
2261
|
-
options.onPosition?.(position);
|
|
2262
|
-
const reconciled = reconcileLpRedemptionFromActorSync(record, position);
|
|
2263
|
-
record = reconciled;
|
|
2264
|
-
state.redemptions.set(record.redemptionId, reconciled);
|
|
2265
|
-
options.onRedemptionUpdate?.(reconciled);
|
|
2266
|
-
if (reconciled.status === "confirmed") {
|
|
2267
|
-
return {
|
|
2268
|
-
withdrawalId: execution.withdrawalId,
|
|
2269
|
-
txSignatures: reconciled.txSignatures,
|
|
2270
|
-
redeemedLamports: reconciled.redeemedLamports
|
|
2271
|
-
};
|
|
2272
|
-
}
|
|
2273
|
-
if (reconciled.status === "failed") {
|
|
2274
|
-
throw new Error(reconciled.error ?? WITHDRAWAL_NO_LAMPORTS_MESSAGE);
|
|
2275
2574
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2575
|
+
};
|
|
2576
|
+
try {
|
|
2577
|
+
return await observeWithdrawalConfirmation(
|
|
2578
|
+
positionId,
|
|
2579
|
+
execution,
|
|
2580
|
+
observation,
|
|
2581
|
+
observeSummary,
|
|
2582
|
+
reconcileLpRedemptionFromCorrelatedHistory,
|
|
2583
|
+
onSummary
|
|
2584
|
+
);
|
|
2585
|
+
} catch (error) {
|
|
2586
|
+
if (!(error instanceof LpPositionSummaryUnsupportedProbe)) throw error;
|
|
2587
|
+
return observeFull();
|
|
2280
2588
|
}
|
|
2281
2589
|
},
|
|
2282
2590
|
async withdrawFees(_positionId, args) {
|
|
@@ -2377,7 +2685,92 @@ function resolveLpRefillShardCount(position, requestedShardCount) {
|
|
|
2377
2685
|
function isLpPositionReadyForInitialFunding(position) {
|
|
2378
2686
|
return position.status === "active" && position.shards.length >= position.targetShardCount;
|
|
2379
2687
|
}
|
|
2380
|
-
|
|
2688
|
+
var LpWithdrawalNeedsFullInventoryError = class extends Error {
|
|
2689
|
+
constructor() {
|
|
2690
|
+
super(LP_WITHDRAWAL_FULL_INVENTORY_REQUIRED_MESSAGE);
|
|
2691
|
+
this.name = "LpWithdrawalNeedsFullInventoryError";
|
|
2692
|
+
}
|
|
2693
|
+
};
|
|
2694
|
+
function fullWithdrawalBasis(position) {
|
|
2695
|
+
return {
|
|
2696
|
+
actorSync: position.actorSync,
|
|
2697
|
+
earnedLamports: position.earnedLamports,
|
|
2698
|
+
availableShards: position.shards.filter(
|
|
2699
|
+
(shard) => shard.status === "AVAILABLE" && shard.amountLamports > 0
|
|
2700
|
+
)
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
function summaryWithdrawalBasis(summary) {
|
|
2704
|
+
return { actorSync: summary.actorSync, earnedLamports: summary.earnedLamports };
|
|
2705
|
+
}
|
|
2706
|
+
function requireAvailableShards(basis) {
|
|
2707
|
+
if (basis.availableShards === void 0) throw new LpWithdrawalNeedsFullInventoryError();
|
|
2708
|
+
return basis.availableShards;
|
|
2709
|
+
}
|
|
2710
|
+
function previewWithdrawalFromBasis(basis, args) {
|
|
2711
|
+
const claim = resolveWithdrawalClaim(basis, args);
|
|
2712
|
+
return {
|
|
2713
|
+
...claim,
|
|
2714
|
+
sourceCount: lpWithdrawalSourceCountForClaim(basis, {
|
|
2715
|
+
...claim,
|
|
2716
|
+
allowManyToOne: args.allowManyToOne
|
|
2717
|
+
})
|
|
2718
|
+
};
|
|
2719
|
+
}
|
|
2720
|
+
function planWithdrawal(before, basis, args) {
|
|
2721
|
+
if (before.redemptionPermission?.state !== "enabled") {
|
|
2722
|
+
throw new PolicyValidationError(
|
|
2723
|
+
"INVALID_REDEMPTION_PLAN",
|
|
2724
|
+
LP_REDEMPTION_PERMISSION_UNAVAILABLE_MESSAGE
|
|
2725
|
+
);
|
|
2726
|
+
}
|
|
2727
|
+
const existingRedemption = findOpenRedemptionHistory(before.actorSync?.redemptionHistory, args);
|
|
2728
|
+
if (existingRedemption !== void 0) {
|
|
2729
|
+
const execution = {
|
|
2730
|
+
feePolicyHash: existingRedemption.feePolicyHash,
|
|
2731
|
+
feeBasisRevision: existingRedemption.feeBasisRevision,
|
|
2732
|
+
withdrawalId: existingRedemption.redemptionId,
|
|
2733
|
+
txSignatures: [...existingRedemption.txSignatures],
|
|
2734
|
+
acceptedLamports: existingRedemption.acceptedLamports,
|
|
2735
|
+
acceptedDepositPrincipalLamports: existingRedemption.acceptedDepositPrincipalLamports,
|
|
2736
|
+
acceptedEarnedFeeLamports: existingRedemption.acceptedEarnedFeeLamports
|
|
2737
|
+
};
|
|
2738
|
+
const redemption = {
|
|
2739
|
+
...buildLpRedemptionRecord({
|
|
2740
|
+
execution,
|
|
2741
|
+
position: before,
|
|
2742
|
+
destinationAddresses: existingRedemption.destinationAddresses,
|
|
2743
|
+
acceptedLamports: existingRedemption.acceptedLamports,
|
|
2744
|
+
requestedTargetLamports: existingRedemption.acceptedLamports,
|
|
2745
|
+
landedBaselineLamports: 0,
|
|
2746
|
+
landedFeeBaselineLamports: 0,
|
|
2747
|
+
txSignatureBaseline: [],
|
|
2748
|
+
nowMs: existingRedemption.createdAtMs
|
|
2749
|
+
}),
|
|
2750
|
+
redeemedLamports: existingRedemption.landedLamports,
|
|
2751
|
+
coordinatorStateVersion: existingRedemption.stateVersion
|
|
2752
|
+
};
|
|
2753
|
+
return { kind: "existing", execution, redemption };
|
|
2754
|
+
}
|
|
2755
|
+
if (args.withdrawalMode !== "exact") return { kind: "submit", preview: void 0 };
|
|
2756
|
+
validateLpPositionFeePolicy(before);
|
|
2757
|
+
const preview = previewWithdrawalFromBasis(basis, args);
|
|
2758
|
+
validateLpWithdrawalPlan({
|
|
2759
|
+
destinationAddresses: args.destinationAddresses,
|
|
2760
|
+
depositPrincipalLamports: preview.depositPrincipalLamports,
|
|
2761
|
+
earnedFeeLamports: preview.earnedFeeLamports,
|
|
2762
|
+
allowManyToOne: args.allowManyToOne ?? false,
|
|
2763
|
+
sourceCount: preview.sourceCount
|
|
2764
|
+
});
|
|
2765
|
+
return { kind: "submit", preview };
|
|
2766
|
+
}
|
|
2767
|
+
function reconcileLpRedemptionFromCorrelatedHistory(record, view) {
|
|
2768
|
+
const history = view.actorSync?.redemptionHistory?.find(
|
|
2769
|
+
(candidate) => candidate.redemptionId === record.redemptionId
|
|
2770
|
+
);
|
|
2771
|
+
return history === void 0 ? record : reconcileLpRedemptionFromHistory(record, history);
|
|
2772
|
+
}
|
|
2773
|
+
function resolveWithdrawalClaim(basis, args) {
|
|
2381
2774
|
if (args.depositPrincipalLamports !== void 0 || args.earnedFeeLamports !== void 0) {
|
|
2382
2775
|
const claim = {
|
|
2383
2776
|
depositPrincipalLamports: args.depositPrincipalLamports ?? 0,
|
|
@@ -2386,20 +2779,19 @@ function resolveWithdrawalClaim(position, args) {
|
|
|
2386
2779
|
validateLpWithdrawalClaim(claim);
|
|
2387
2780
|
return claim;
|
|
2388
2781
|
}
|
|
2389
|
-
const
|
|
2390
|
-
const
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
);
|
|
2394
|
-
const
|
|
2395
|
-
const hasActorProjection = hasActorRedeemableProjection(position.actorSync);
|
|
2782
|
+
const sync = basis.actorSync;
|
|
2783
|
+
const principalFromActorOnly = sync?.redeemableProjectionAvailable === true && sync.feePolicy !== void 0;
|
|
2784
|
+
const legacyDepositPrincipalLamports = principalFromActorOnly ? 0 : requireAvailableShards(basis).reduce((sum, shard) => sum + shard.amountLamports, 0);
|
|
2785
|
+
const actorRedeemablePrincipalLamports = Math.max(0, sync?.redeemablePrincipalLamports ?? 0);
|
|
2786
|
+
const actorRedeemableFeeLamports = Math.max(0, sync?.redeemableFeeLamports ?? 0);
|
|
2787
|
+
const hasActorProjection = hasActorRedeemableProjection(sync);
|
|
2396
2788
|
const depositPrincipalLamports = resolveRedeemablePrincipalLamports(
|
|
2397
|
-
|
|
2789
|
+
sync,
|
|
2398
2790
|
legacyDepositPrincipalLamports,
|
|
2399
2791
|
actorRedeemablePrincipalLamports,
|
|
2400
2792
|
actorRedeemableFeeLamports
|
|
2401
2793
|
);
|
|
2402
|
-
const earnedFeeLamports = hasActorProjection ? actorRedeemableFeeLamports : Math.max(0,
|
|
2794
|
+
const earnedFeeLamports = hasActorProjection ? actorRedeemableFeeLamports : Math.max(0, basis.earnedLamports);
|
|
2403
2795
|
const totalLamports = depositPrincipalLamports + earnedFeeLamports;
|
|
2404
2796
|
if (!Number.isSafeInteger(totalLamports) || totalLamports <= 0) {
|
|
2405
2797
|
throw new PolicyValidationError(
|
|
@@ -2409,12 +2801,12 @@ function resolveWithdrawalClaim(position, args) {
|
|
|
2409
2801
|
}
|
|
2410
2802
|
return { depositPrincipalLamports, earnedFeeLamports };
|
|
2411
2803
|
}
|
|
2412
|
-
function findOpenRedemptionHistory(
|
|
2804
|
+
function findOpenRedemptionHistory(history, args) {
|
|
2413
2805
|
const hasExplicitClaim = args.withdrawalMode === "exact";
|
|
2414
2806
|
const requestedPrincipalLamports = args.depositPrincipalLamports ?? 0;
|
|
2415
2807
|
const requestedFeeLamports = args.earnedFeeLamports ?? 0;
|
|
2416
|
-
return
|
|
2417
|
-
(
|
|
2808
|
+
return history?.find(
|
|
2809
|
+
(history2) => LP_REDEMPTION_HISTORY_OPEN_STATES.has(history2.state) && history2.detailsTruncated !== true && (history2.withdrawalMode ?? "exact") === args.withdrawalMode && sameStringList(history2.destinationAddresses, args.destinationAddresses) && (!hasExplicitClaim || history2.acceptedDepositPrincipalLamports === requestedPrincipalLamports && history2.acceptedEarnedFeeLamports === requestedFeeLamports)
|
|
2418
2810
|
);
|
|
2419
2811
|
}
|
|
2420
2812
|
function hasActorSyncLpActivity(sync) {
|
|
@@ -2488,27 +2880,31 @@ function resolveWithdrawalRecord({
|
|
|
2488
2880
|
landedFeeBaselineLamports: record.landedFeeBaselineLamports ?? 0
|
|
2489
2881
|
};
|
|
2490
2882
|
}
|
|
2491
|
-
function lpWithdrawalSourceCountForClaim(
|
|
2492
|
-
const actorSync =
|
|
2883
|
+
function lpWithdrawalSourceCountForClaim(basis, claim) {
|
|
2884
|
+
const actorSync = basis.actorSync;
|
|
2493
2885
|
const actorRedeemablePrincipalLamports = actorSync?.redeemablePrincipalLamports ?? 0;
|
|
2494
2886
|
const actorRedeemableFeeLamports = actorSync?.redeemableFeeLamports ?? 0;
|
|
2495
2887
|
const actorRedeemableSourceCount = actorSync?.redeemableSourceCount;
|
|
2496
2888
|
if (actorSync?.redeemableProjectionAvailable === true && claim.depositPrincipalLamports === actorRedeemablePrincipalLamports && claim.earnedFeeLamports === actorRedeemableFeeLamports && actorRedeemableSourceCount !== void 0) {
|
|
2497
2889
|
return actorRedeemableSourceCount;
|
|
2498
2890
|
}
|
|
2499
|
-
|
|
2891
|
+
const actorRedeemablePrincipalSourceCount = actorSync?.redeemablePrincipalSourceCount ?? 0;
|
|
2892
|
+
const actorPrincipalSourceOverride = claim.depositPrincipalLamports > 0 && actorSync?.redeemableProjectionAvailable === true && actorRedeemablePrincipalLamports >= claim.depositPrincipalLamports && actorRedeemablePrincipalSourceCount > 0;
|
|
2500
2893
|
let principalSourceCount = 0;
|
|
2501
|
-
|
|
2502
|
-
for (const shard of principalCandidates) {
|
|
2503
|
-
if (remainingPrincipalLamports <= 0) break;
|
|
2504
|
-
principalSourceCount += 1;
|
|
2505
|
-
remainingPrincipalLamports -= shard.amountLamports;
|
|
2506
|
-
}
|
|
2507
|
-
const actorRedeemablePrincipalSourceCount = position.actorSync?.redeemablePrincipalSourceCount ?? 0;
|
|
2508
|
-
if (claim.depositPrincipalLamports > 0 && position.actorSync?.redeemableProjectionAvailable === true && actorRedeemablePrincipalLamports >= claim.depositPrincipalLamports && actorRedeemablePrincipalSourceCount > 0) {
|
|
2894
|
+
if (actorPrincipalSourceOverride) {
|
|
2509
2895
|
principalSourceCount = actorRedeemablePrincipalSourceCount;
|
|
2896
|
+
} else if (claim.depositPrincipalLamports > 0) {
|
|
2897
|
+
let remainingPrincipalLamports = claim.depositPrincipalLamports;
|
|
2898
|
+
const principalCandidates = [...requireAvailableShards(basis)].sort(
|
|
2899
|
+
(left, right) => left.shardId.localeCompare(right.shardId)
|
|
2900
|
+
);
|
|
2901
|
+
for (const shard of principalCandidates) {
|
|
2902
|
+
if (remainingPrincipalLamports <= 0) break;
|
|
2903
|
+
principalSourceCount += 1;
|
|
2904
|
+
remainingPrincipalLamports -= shard.amountLamports;
|
|
2905
|
+
}
|
|
2510
2906
|
}
|
|
2511
|
-
const observedEarnedFeeSourceCount =
|
|
2907
|
+
const observedEarnedFeeSourceCount = actorSync?.redeemableProjectionAvailable === true ? actorSync.redeemableFeeSourceCount ?? 0 : actorSync?.redeemableFeeSourceCount || actorSync?.reimbursementDueSourceCount || 0;
|
|
2512
2908
|
if (claim.earnedFeeLamports > 0 && observedEarnedFeeSourceCount < 1 && claim.allowManyToOne !== true) {
|
|
2513
2909
|
throw new PolicyValidationError(
|
|
2514
2910
|
"INVALID_WITHDRAWAL_PLAN",
|
|
@@ -2731,6 +3127,9 @@ function createPosition(session, args) {
|
|
|
2731
3127
|
function recoverPosition(session, args) {
|
|
2732
3128
|
return defaultLpLifecycleClient(session).recoverPosition(args);
|
|
2733
3129
|
}
|
|
3130
|
+
function recoverPositionSummary(session, args) {
|
|
3131
|
+
return defaultLpLifecycleClient(session).recoverPositionSummary(args);
|
|
3132
|
+
}
|
|
2734
3133
|
function confirmPositionCodeSaved(session, positionId) {
|
|
2735
3134
|
defaultLpLifecycleClient(session).confirmPositionCodeSaved(positionId);
|
|
2736
3135
|
}
|
|
@@ -2758,6 +3157,19 @@ function reconcileFunding2(session, positionId) {
|
|
|
2758
3157
|
function withdrawPosition(session, positionId, args) {
|
|
2759
3158
|
return defaultLpLifecycleClient(session).withdrawPosition(positionId, args);
|
|
2760
3159
|
}
|
|
3160
|
+
function reconcileFundingSummary2(session, positionId) {
|
|
3161
|
+
return defaultLpLifecycleClient(session).reconcileFundingSummary(positionId);
|
|
3162
|
+
}
|
|
3163
|
+
function withdrawPositionSummary(session, positionId, args) {
|
|
3164
|
+
return defaultLpLifecycleClient(session).withdrawPositionSummary(positionId, args);
|
|
3165
|
+
}
|
|
3166
|
+
function waitForWithdrawalConfirmationSummary(session, positionId, execution, options = {}) {
|
|
3167
|
+
return defaultLpLifecycleClient(session).waitForWithdrawalConfirmationSummary(
|
|
3168
|
+
positionId,
|
|
3169
|
+
execution,
|
|
3170
|
+
options
|
|
3171
|
+
);
|
|
3172
|
+
}
|
|
2761
3173
|
function waitForWithdrawalConfirmation(session, positionId, execution, options = {}) {
|
|
2762
3174
|
return defaultLpLifecycleClient(session).waitForWithdrawalConfirmation(
|
|
2763
3175
|
positionId,
|
|
@@ -2774,6 +3186,6 @@ function listPositions(session) {
|
|
|
2774
3186
|
return defaultLpLifecycleClient(session).listPositions();
|
|
2775
3187
|
}
|
|
2776
3188
|
|
|
2777
|
-
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 };
|
|
3189
|
+
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_POSITION_SUMMARY_MAX_SHARDS, LP_POSITION_SUMMARY_SCHEMA_REJECTION_PREFIX, LP_POSITION_SUMMARY_SCHEMA_REJECTION_VIEW_TOKEN, LP_REDEMPTION_RECONCILING_MESSAGE, LP_SHARD_STATUSES, LP_WITHDRAWAL_FULL_INVENTORY_REQUIRED_MESSAGE, bytesToHex, completeDkgBatch, confirmPositionCodeSaved, createLpCoordinatorClient, createLpDkgBatch, createLpLifecycleClient, createPosition, defaultLpLifecycleClient, deriveLpPositionCodeAuth, generateLpPositionCode, isLpPositionAuthMissingError, isLpPositionSummaryUnsupportedError, isLpRedemptionReconcilingError, listPositions, mergeLpActorSync, normalizeLpActorSync, normalizeLpPositionCode, prepareInitialFunding, prepareTopUp2 as prepareTopUp, previewLpWithdrawalPlan, previewLpWithdrawalPlanFromSummary, reconcileFunding2 as reconcileFunding, reconcileFundingSummary2 as reconcileFundingSummary, recoverPosition, recoverPositionSummary, refill, refreshPosition, signLpCommandBytes, summarizeLpPosition, validateLpPositionFeePolicy, waitForTopUp, waitForWithdrawalConfirmation, waitForWithdrawalConfirmationSummary, withdrawFees, withdrawPosition, withdrawPositionSummary };
|
|
2778
3190
|
//# sourceMappingURL=lp.js.map
|
|
2779
3191
|
//# sourceMappingURL=lp.js.map
|