@invisible-labs/sdk 0.13.1-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/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-NOKBFHDP.js';
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 hydratePositionResponse(session, lpPositionId, auth, initialResponse, options = {}) {
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-EQEL23A3.js');
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
- const claim = resolveWithdrawalClaim(position, args);
1735
- return {
1736
- ...claim,
1737
- sourceCount: lpWithdrawalSourceCountForClaim(position, {
1738
- ...claim,
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 (positionId, input, auth) => {
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 client.reconcileFunding(positionId, auth).catch(() => void 0);
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
- async recoverPosition(args) {
2309
+ recoverPosition: recoverPosition2,
2310
+ async recoverPositionSummary(args) {
1983
2311
  assertUsable();
1984
2312
  const auth = await deriveLpPositionCodeAuth(args.code);
1985
2313
  rememberAuth(auth);
1986
- const position = rememberPosition(
1987
- await client.getPosition(auth.lpPositionId, auth, {
1988
- deadlineMs: args.deadlineMs,
1989
- signal: args.signal
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
- async withdrawPosition(positionId, args) {
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 before = rememberPosition(await client.reconcileFunding(positionId, auth));
2139
- if (before.redemptionPermission?.state !== "enabled") {
2140
- throw new PolicyValidationError(
2141
- "INVALID_REDEMPTION_PLAN",
2142
- LP_REDEMPTION_PERMISSION_UNAVAILABLE_MESSAGE
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
- state.redemptions.set(execution2.withdrawalId, redemption2);
2172
- return { execution: execution2, position: before, redemption: redemption2 };
2173
- }
2174
- const preview = args.withdrawalMode === "exact" ? previewLpWithdrawalPlan(before, args) : void 0;
2175
- const requestedAtMs = nowMs();
2176
- if (args.withdrawalMode === "exact") {
2177
- validateLpWithdrawalPlan({
2178
- destinationAddresses: args.destinationAddresses,
2179
- depositPrincipalLamports: preview.depositPrincipalLamports,
2180
- earnedFeeLamports: preview.earnedFeeLamports,
2181
- allowManyToOne: args.allowManyToOne ?? false,
2182
- sourceCount: preview.sourceCount
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 execution = await executeWithdrawalAfterFundingReadiness(
2513
+ const result = await executeWithdrawalPlan(
2186
2514
  positionId,
2187
- {
2188
- lpPositionId: positionId,
2189
- destinationAddresses: args.destinationAddresses,
2190
- depositPrincipalLamports: args.withdrawalMode === "max_available" ? 0 : preview.depositPrincipalLamports,
2191
- earnedFeeLamports: args.withdrawalMode === "max_available" ? 0 : preview.earnedFeeLamports,
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
- const acceptedLamports = execution.acceptedLamports;
2201
- if (args.withdrawalMode === "max_available" && acceptedLamports === void 0) {
2202
- throw new PolicyValidationError(
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
- let record = resolveWithdrawalRecord({
2229
- state,
2528
+ return observeWithdrawalConfirmation(
2230
2529
  positionId,
2231
2530
  execution,
2232
- options
2233
- });
2234
- state.redemptions.set(record.redemptionId, record);
2235
- const deadlineMs = options.deadlineMs ?? nowMs() + (runtime.withdrawalConfirmationTimeoutMs ?? LP_WITHDRAWAL_CONFIRMATION_TIMEOUT_MS);
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
- for (; ; ) {
2238
- throwIfWithdrawalConfirmationAborted(options.signal);
2239
- if (nowMs() >= deadlineMs) {
2240
- markLpRedemptionReconciling(state, record, options);
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
- } catch (error) {
2255
- if (isLpPositionObservationDeadlineError(error, deadlineMs, nowMs)) {
2256
- markLpRedemptionReconciling(state, record, options);
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
- if (nowMs() >= deadlineMs) {
2277
- markLpRedemptionReconciling(state, reconciled, options);
2278
- }
2279
- await sleepWithAbort(sleep2, pollIntervalMs, options.signal);
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
- function resolveWithdrawalClaim(position, args) {
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 legacyDepositPrincipalLamports = position.shards.filter((shard) => shard.status === "AVAILABLE" && shard.amountLamports > 0).reduce((sum, shard) => sum + shard.amountLamports, 0);
2390
- const actorRedeemablePrincipalLamports = Math.max(
2391
- 0,
2392
- position.actorSync?.redeemablePrincipalLamports ?? 0
2393
- );
2394
- const actorRedeemableFeeLamports = Math.max(0, position.actorSync?.redeemableFeeLamports ?? 0);
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
- position.actorSync,
2789
+ sync,
2398
2790
  legacyDepositPrincipalLamports,
2399
2791
  actorRedeemablePrincipalLamports,
2400
2792
  actorRedeemableFeeLamports
2401
2793
  );
2402
- const earnedFeeLamports = hasActorProjection ? actorRedeemableFeeLamports : Math.max(0, position.earnedLamports);
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(position, args) {
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 position.actorSync?.redemptionHistory?.find(
2417
- (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)
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(position, claim) {
2492
- const actorSync = position.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
- let remainingPrincipalLamports = claim.depositPrincipalLamports;
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
- const principalCandidates = [...position.shards].filter((shard) => shard.status === "AVAILABLE" && shard.amountLamports > 0).sort((left, right) => left.shardId.localeCompare(right.shardId));
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 = position.actorSync?.redeemableProjectionAvailable === true ? position.actorSync.redeemableFeeSourceCount ?? 0 : position.actorSync?.redeemableFeeSourceCount || position.actorSync?.reimbursementDueSourceCount || 0;
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