@invisible-labs/sdk 0.8.0-devnet → 0.10.0-devnet

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +17 -3
  2. package/dist/.invisible-sdk-build-target.json +2 -2
  3. package/dist/{chunk-MZKJU3UA.js → chunk-6AGC3IOB.js} +16 -6
  4. package/dist/chunk-6AGC3IOB.js.map +1 -0
  5. package/dist/{chunk-HJFMDMPY.js → chunk-6AKBRYKO.js} +3 -3
  6. package/dist/{chunk-HJFMDMPY.js.map → chunk-6AKBRYKO.js.map} +1 -1
  7. package/dist/{chunk-DCTYBUY3.js → chunk-AIKC2XQS.js} +3 -3
  8. package/dist/{chunk-DCTYBUY3.js.map → chunk-AIKC2XQS.js.map} +1 -1
  9. package/dist/{chunk-Y7AK6RBV.js → chunk-ANQMIQYS.js} +587 -19
  10. package/dist/chunk-ANQMIQYS.js.map +1 -0
  11. package/dist/{chunk-MPNVF727.js → chunk-DFBH5XLM.js} +569 -78
  12. package/dist/chunk-DFBH5XLM.js.map +1 -0
  13. package/dist/{chunk-EBWTAXNT.js → chunk-EPWTRF5U.js} +3 -3
  14. package/dist/{chunk-EBWTAXNT.js.map → chunk-EPWTRF5U.js.map} +1 -1
  15. package/dist/{chunk-IG6JJFR2.js → chunk-HWRMSK7E.js} +8 -6
  16. package/dist/chunk-HWRMSK7E.js.map +1 -0
  17. package/dist/{chunk-K67FTCQU.js → chunk-JNNVPZEU.js} +3 -3
  18. package/dist/chunk-JNNVPZEU.js.map +1 -0
  19. package/dist/{chunk-QRN46R3F.js → chunk-RWKG7N7I.js} +10 -3
  20. package/dist/chunk-RWKG7N7I.js.map +1 -0
  21. package/dist/coordinator-T2B7253V.js +4 -0
  22. package/dist/{coordinator-E2TS6NR2.js.map → coordinator-T2B7253V.js.map} +1 -1
  23. package/dist/dkgWorker.js +1 -1
  24. package/dist/events.js +3 -3
  25. package/dist/frostRuntime-JESDHN6O.js +4 -0
  26. package/dist/{frostRuntime-6FTPKUCP.js.map → frostRuntime-JESDHN6O.js.map} +1 -1
  27. package/dist/index.d.ts +4 -4
  28. package/dist/index.js +9 -9
  29. package/dist/index.js.map +1 -1
  30. package/dist/lp.d.ts +48 -1
  31. package/dist/lp.js +360 -82
  32. package/dist/lp.js.map +1 -1
  33. package/dist/stats.js +1 -1
  34. package/dist/storage.js +2 -2
  35. package/dist/{types.generated-YhFu9ZBR.d.ts → types.generated-CtMxCo9F.d.ts} +80 -2
  36. package/dist/user.d.ts +25 -11
  37. package/dist/user.js +124 -37
  38. package/dist/user.js.map +1 -1
  39. package/package.json +2 -2
  40. package/dist/chunk-IG6JJFR2.js.map +0 -1
  41. package/dist/chunk-K67FTCQU.js.map +0 -1
  42. package/dist/chunk-MPNVF727.js.map +0 -1
  43. package/dist/chunk-MZKJU3UA.js.map +0 -1
  44. package/dist/chunk-QRN46R3F.js.map +0 -1
  45. package/dist/chunk-Y7AK6RBV.js.map +0 -1
  46. package/dist/coordinator-E2TS6NR2.js +0 -4
  47. package/dist/frostRuntime-6FTPKUCP.js +0 -4
package/dist/lp.js CHANGED
@@ -1,10 +1,104 @@
1
- import { isValidLpPositionId, LP_DEFAULT_REFILL_BATCH_SIZE, LP_DEFAULT_TARGET_SHARDS, LP_MAX_TARGET_SHARDS, LP_MAX_REFILL_BATCH_SIZE } from './chunk-IG6JJFR2.js';
2
- import { publicKey, assertAttested, lamports } from './chunk-EBWTAXNT.js';
3
- import { requestEnvelope, CoordinatorMessageType } from './chunk-MZKJU3UA.js';
4
- import { getSessionState } from './chunk-HJFMDMPY.js';
5
- import { CommandError, WalletError, TransportError, PolicyValidationError, RoutingError, LpLifecycleError } from './chunk-QRN46R3F.js';
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-HWRMSK7E.js';
2
+ import { publicKey, assertAttested, lamports } from './chunk-EPWTRF5U.js';
3
+ import { requestEnvelope, CoordinatorMessageType } from './chunk-6AGC3IOB.js';
4
+ import { getSessionState } from './chunk-6AKBRYKO.js';
5
+ import { CommandError, WalletError, TransportError, PolicyValidationError, RoutingError, LpLifecycleError } from './chunk-RWKG7N7I.js';
6
6
  import './chunk-VR6T6OJS.js';
7
7
 
8
+ // src/lp/actorSync.ts
9
+ function normalizeLpActorSync(sync) {
10
+ const total = sync.totalNetFundsLamports;
11
+ if (total === void 0) return sync;
12
+ const available = sync.redeemablePrincipalLamports + sync.redeemableFeeLamports;
13
+ if (sync.redeemableProjectionAvailable === true && Number.isSafeInteger(total) && total >= 0 && Number.isSafeInteger(sync.redeemablePrincipalLamports) && sync.redeemablePrincipalLamports >= 0 && Number.isSafeInteger(sync.redeemableFeeLamports) && sync.redeemableFeeLamports >= 0 && Number.isSafeInteger(available) && available >= 0 && total >= available) {
14
+ return sync;
15
+ }
16
+ return { ...sync, totalNetFundsLamports: void 0 };
17
+ }
18
+ function mergeLpActorSync(previous, next) {
19
+ if (next === void 0) return void 0;
20
+ if (previous?.lpPositionId === next.lpPositionId && (next.stateVersion < previous.stateVersion || next.stateVersion === previous.stateVersion && next.updatedAtMs < previous.updatedAtMs)) {
21
+ return normalizeLpActorSync(previous);
22
+ }
23
+ return normalizeLpActorSync(next);
24
+ }
25
+
26
+ // src/lp/feePolicy.ts
27
+ var LP_FEE_POLICY_VERSION = 1;
28
+ var LP_PARTNER_COMMISSION_BPS = 6e3;
29
+ var LP_BASIS_POINT_DENOMINATOR = 10000n;
30
+ var LP_FEE_POLICY_HASHES = {
31
+ internal: "53479c39d822899c0abe21990aeff40ea74681277b2744ef86234152cc94ca5a",
32
+ partner: "3e1a307504043bc0b25f03ccffdff1b42cd2b38699f000f7eb70ce9433a5b2a7"
33
+ };
34
+ var LP_ECONOMIC_UNSIGNED_PATTERN = /^(0|[1-9][0-9]*)$/;
35
+ var LP_ECONOMIC_SIGNED_PATTERN = /^(0|-?[1-9][0-9]*)$/;
36
+ var LP_ECONOMIC_UNSIGNED_MAX = (1n << 128n) - 1n;
37
+ var LP_ECONOMIC_SIGNED_MIN = -(1n << 127n);
38
+ var LP_ECONOMIC_SIGNED_MAX = (1n << 127n) - 1n;
39
+ var LP_FEE_POLICY_INVALID_MESSAGE = "Coordinator LP fee policy evidence is missing or invalid";
40
+ function validateLpFeePolicy(value) {
41
+ if (typeof value !== "object" || value === null) {
42
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
43
+ }
44
+ const policy = value;
45
+ if (policy.version !== LP_FEE_POLICY_VERSION || policy.profile !== "internal" && policy.profile !== "partner" || policy.commission_bps !== (policy.profile === "partner" ? LP_PARTNER_COMMISSION_BPS : 0) || typeof policy.policy_hash !== "string" || policy.policy_hash !== LP_FEE_POLICY_HASHES[policy.profile]) {
46
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
47
+ }
48
+ return {
49
+ version: LP_FEE_POLICY_VERSION,
50
+ profile: policy.profile,
51
+ commission_bps: policy.profile === "partner" ? LP_PARTNER_COMMISSION_BPS : 0,
52
+ policy_hash: policy.policy_hash
53
+ };
54
+ }
55
+ function requireLpFeePolicyCapability(version) {
56
+ if (version !== LP_FEE_POLICY_VERSION) {
57
+ throw new RoutingError(
58
+ "VERSION_NOT_SUPPORTED",
59
+ "Coordinator does not support the LP fee policy contract"
60
+ );
61
+ }
62
+ }
63
+ function validateLpPositionFeePolicy(position, previous) {
64
+ if (position.feePolicy === void 0) {
65
+ if (previous?.feePolicy !== void 0 || position.actorSync?.feePolicy !== void 0 || position.actorSync?.feeBasisRevision !== void 0 || position.actorSync?.grossFeeLamports !== void 0 || position.actorSync?.protocolCommissionLamports !== void 0 || position.actorSync?.waivedProtocolCommissionLamports !== void 0) {
66
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
67
+ }
68
+ return;
69
+ }
70
+ requireLpFeePolicyCapability(position.lpFeePolicyVersion);
71
+ const policy = validateLpFeePolicy(position.feePolicy);
72
+ const sync = position.actorSync;
73
+ const actorPolicy = validateLpFeePolicy(sync?.feePolicy);
74
+ if (JSON.stringify(policy) !== JSON.stringify(actorPolicy) || previous !== void 0 && (previous.feePolicy === void 0 || JSON.stringify(policy) !== JSON.stringify(validateLpFeePolicy(previous.feePolicy))) || sync?.lpPositionId !== position.id || sync?.redeemableProjectionAvailable !== true || !Number.isSafeInteger(sync.feeBasisRevision) || sync.feeBasisRevision < 0 || !Number.isSafeInteger(sync.grossFeeLamports) || sync.grossFeeLamports < 0 || !Number.isSafeInteger(sync.protocolCommissionLamports) || sync.protocolCommissionLamports < 0 || !Number.isSafeInteger(sync.waivedProtocolCommissionLamports) || sync.waivedProtocolCommissionLamports < 0 || sync.economicReturn === void 0) {
75
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
76
+ }
77
+ if (BigInt(sync.protocolCommissionLamports) + BigInt(sync.waivedProtocolCommissionLamports) !== BigInt(sync.grossFeeLamports) * BigInt(policy.commission_bps) / LP_BASIS_POINT_DENOMINATOR) {
78
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
79
+ }
80
+ for (const history of sync.redemptionHistory ?? []) {
81
+ if (history.feePolicyHash !== policy.policy_hash || !Number.isSafeInteger(history.feeBasisRevision) || history.feeBasisRevision < 0) {
82
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
83
+ }
84
+ }
85
+ const summary = sync.economicReturn;
86
+ const totals = [
87
+ summary.providerRewardLamports,
88
+ summary.sourceExpenseCompensationLamports,
89
+ summary.chargedReimbursementLossLamports
90
+ ];
91
+ if (!totals.every(
92
+ (value) => typeof value === "string" && LP_ECONOMIC_UNSIGNED_PATTERN.test(value) && BigInt(value) <= LP_ECONOMIC_UNSIGNED_MAX
93
+ ) || typeof summary.netEconomicReturnLamports !== "string" || !LP_ECONOMIC_SIGNED_PATTERN.test(summary.netEconomicReturnLamports)) {
94
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
95
+ }
96
+ const net = BigInt(summary.netEconomicReturnLamports);
97
+ if (net < LP_ECONOMIC_SIGNED_MIN || net > LP_ECONOMIC_SIGNED_MAX || net !== BigInt(summary.providerRewardLamports) - BigInt(summary.chargedReimbursementLossLamports) - BigInt(sync.protocolCommissionLamports)) {
98
+ throw new CommandError("REJECTED_STATE", LP_FEE_POLICY_INVALID_MESSAGE);
99
+ }
100
+ }
101
+
8
102
  // src/lp/positionCode.ts
9
103
  var LEGACY_CODE_PREFIX = "ilp1";
10
104
  var CODE_PREFIX = "ilp2";
@@ -231,6 +325,12 @@ var COMMAND_TTL_MS = 3e4;
231
325
  var LP_POSITION_OPEN_COMMAND_TTL_MS = 55e3;
232
326
  var LP_POSITION_OPEN_REQUEST_TIMEOUT_MS = 2e4;
233
327
  var LP_COMMAND_REQUEST_TIMEOUT_MS = COMMAND_TTL_MS;
328
+ var LP_POSITION_HYDRATION_TIMEOUT_MS = LP_COMMAND_REQUEST_TIMEOUT_MS;
329
+ var LP_POSITION_SNAPSHOT_MAX_ATTEMPTS = 3;
330
+ var LP_SHARD_SNAPSHOT_CHANGED_MESSAGE = "LP shard snapshot changed";
331
+ var LP_SHARD_PAGE_INVALID_MESSAGE = "coordinator LP shard page is invalid";
332
+ var LP_POSITION_OPEN_IDENTITY_MISMATCH_MESSAGE = "Coordinator returned a different LP position identity or creation intent";
333
+ var LP_SHARD_SNAPSHOT_HASH_PATTERN = /^[0-9a-f]{64}$/;
234
334
  var LP_CREATION_CHALLENGE_REQUEST_TIMEOUT_MS = 3e4;
235
335
  var LP_CREATION_WALLET_SIGNATURE_TIMEOUT_MS = 45e3;
236
336
  var LP_CREATION_PROOF_REQUEST_TIMEOUT_MS = 15e3;
@@ -325,6 +425,16 @@ async function authorizePositionCreation(session, intent, signer) {
325
425
  "Coordinator returned an unexpected LP creation authorization response"
326
426
  );
327
427
  }
428
+ requireLpFeePolicyCapability(challenge.value.lp_fee_policy_version);
429
+ const feePolicy = validateLpFeePolicy(challenge.value.fee_policy);
430
+ const consentLine = `LP Fee Policy: ${feePolicy.policy_hash}`;
431
+ const policyResource = `&fee_policy_hash=${feePolicy.policy_hash}&fee_policy_version=${feePolicy.version}`;
432
+ if (!challenge.value.message.split("\n").includes(consentLine) || !challenge.value.message.includes(policyResource)) {
433
+ throw new CommandError(
434
+ "REJECTED_STATE",
435
+ "Coordinator LP creation challenge does not bind the authorized fee policy"
436
+ );
437
+ }
328
438
  const localAuthorizationDeadlineMs = challengeRequestStartedAtMs + challenge.value.valid_for_ms;
329
439
  const walletTimeoutMs = lpCreationAuthorizationStepTimeout(
330
440
  localAuthorizationDeadlineMs,
@@ -396,7 +506,11 @@ async function authorizePositionCreation(session, intent, signer) {
396
506
  LP_CREATION_AUTHORIZATION_MARGIN_MS,
397
507
  LP_CREATION_MIN_STEP_TIMEOUT_MS
398
508
  );
399
- return { authorizationId: authorization.value.authorization_id };
509
+ requireLpFeePolicyCapability(authorization.value.lp_fee_policy_version);
510
+ if (JSON.stringify(validateLpFeePolicy(authorization.value.fee_policy)) !== JSON.stringify(feePolicy)) {
511
+ throw new CommandError("REJECTED_STATE", "Coordinator changed the authorized LP fee policy");
512
+ }
513
+ return { authorizationId: authorization.value.authorization_id, feePolicy };
400
514
  }
401
515
  function lpCreationAuthorizationStepTimeout(localDeadlineMs, reservedMs, maximumTimeoutMs) {
402
516
  const availableMs = localDeadlineMs - Date.now() - reservedMs;
@@ -487,6 +601,7 @@ async function openPosition(session, input, auth, reconnectSession) {
487
601
  case: "positionOpen",
488
602
  value: {
489
603
  creation_authorization_id: input.creationAuthorizationId,
604
+ fee_policy: input.feePolicy,
490
605
  auth_public_key: Uint8Array.from(input.authPublicKey),
491
606
  refill_public_key: Uint8Array.from(input.refillPublicKey),
492
607
  redemption_commitment: Uint8Array.from(input.withdrawalCommitment),
@@ -506,6 +621,7 @@ async function openPosition(session, input, auth, reconnectSession) {
506
621
  timeoutMs: LP_POSITION_OPEN_REQUEST_TIMEOUT_MS
507
622
  };
508
623
  let response;
624
+ let responseSession = session;
509
625
  try {
510
626
  response = await requestForPosition(
511
627
  session,
@@ -517,17 +633,27 @@ async function openPosition(session, input, auth, reconnectSession) {
517
633
  );
518
634
  } catch (error) {
519
635
  if (!isAmbiguousLpPositionOpenFailure(error)) throw error;
520
- const replaySession = reconnectSession === void 0 ? session : await reconnectSessionWithinDeadline(reconnectSession, commandDeadlineMs);
521
- response = await requestForPosition(
522
- replaySession,
523
- input.lpPositionId,
524
- auth,
525
- "position_open",
526
- payload,
527
- commandOptions
636
+ responseSession = reconnectSession === void 0 ? session : await reconnectSessionWithinDeadline(reconnectSession, commandDeadlineMs);
637
+ }
638
+ const position = await hydratePositionResponse(
639
+ responseSession,
640
+ auth.lpPositionId,
641
+ auth,
642
+ response,
643
+ {
644
+ deadlineMs: commandDeadlineMs
645
+ }
646
+ );
647
+ if (position.authPublicKey !== bytesToHex(Uint8Array.from(input.authPublicKey)) || position.refillPublicKey !== bytesToHex(Uint8Array.from(input.refillPublicKey)) || position.withdrawalCommitment !== bytesToHex(Uint8Array.from(input.withdrawalCommitment)) || position.committedLamports !== input.committedLamports || position.targetShardCount !== input.shardCount || position.refillThreshold !== input.refillThreshold || position.createdAt !== input.createdAtMs) {
648
+ throw new CommandError("REJECTED_STATE", LP_POSITION_OPEN_IDENTITY_MISMATCH_MESSAGE);
649
+ }
650
+ if (input.feePolicy !== void 0 && position.feePolicy?.policy_hash !== input.feePolicy.policy_hash) {
651
+ throw new CommandError(
652
+ "REJECTED_STATE",
653
+ "Coordinator opened the LP position with a different fee policy"
528
654
  );
529
655
  }
530
- return expectPosition(response);
656
+ return position;
531
657
  }
532
658
  async function reconnectSessionWithinDeadline(reconnectSession, deadlineMs) {
533
659
  const remainingMs = deadlineMs - Date.now();
@@ -561,37 +687,131 @@ function isAmbiguousCoordinatorRequestFailure(error) {
561
687
  return error instanceof TransportError || error instanceof CommandError && error.code === "REJECTED_STALE_JOB";
562
688
  }
563
689
  async function getPosition(session, lpPositionId, auth, options = {}) {
564
- let cursor;
565
- let position;
566
- const seenCursors = /* @__PURE__ */ new Set();
567
- for (; ; ) {
568
- const pageOptions = lpPositionPageRequestOptions(options);
569
- const response = await requestForPosition(
570
- session,
571
- lpPositionId,
572
- auth,
573
- "position_get",
574
- {
575
- case: "positionGet",
576
- value: cursor === void 0 ? {} : { redemption_history_cursor: cursor }
577
- },
578
- pageOptions
579
- );
580
- const page = expectPosition(response);
581
- const mergedPosition = position === void 0 ? page : mergePositionHistoryPages(position, page);
582
- position = mergedPosition;
583
- const actorSync = page.actorSync;
584
- if (actorSync?.redemptionHistoryHasMore !== true) return mergedPosition;
585
- const nextCursor = actorSync.redemptionHistoryNextCursor;
586
- if (nextCursor === void 0 || seenCursors.has(nextCursor)) {
587
- throw new CommandError(
588
- "REJECTED_STATE",
589
- "coordinator LP actor sync returned an invalid redemption history cursor"
690
+ return hydratePositionResponse(session, lpPositionId, auth, void 0, options);
691
+ }
692
+ async function hydratePositionResponse(session, lpPositionId, auth, initialResponse, options = {}) {
693
+ const boundedOptions = {
694
+ ...options,
695
+ deadlineMs: options.deadlineMs ?? Date.now() + LP_POSITION_HYDRATION_TIMEOUT_MS
696
+ };
697
+ for (let attempt = 0; attempt < LP_POSITION_SNAPSHOT_MAX_ATTEMPTS; attempt += 1) {
698
+ try {
699
+ const response = initialResponse ?? await requestForPosition(
700
+ session,
701
+ lpPositionId,
702
+ auth,
703
+ "position_get",
704
+ { case: "positionGet", value: {} },
705
+ boundedOptions
590
706
  );
707
+ if (response.case !== "position")
708
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
709
+ const first = response.value;
710
+ let full = first;
711
+ if (first.shards_snapshot_hash !== void 0 || first.shards_total_count !== void 0 || first.shards_next_index !== void 0) {
712
+ assertShardPage(first, first, lpPositionId, auth, 0);
713
+ const shards = [...first.shards];
714
+ let nextIndex = first.shards_next_index;
715
+ while (nextIndex !== void 0) {
716
+ const nextResponse = await requestForPosition(
717
+ session,
718
+ lpPositionId,
719
+ auth,
720
+ "position_get",
721
+ {
722
+ case: "positionGet",
723
+ value: {
724
+ shard_start_index: nextIndex,
725
+ shards_snapshot_hash: first.shards_snapshot_hash
726
+ }
727
+ },
728
+ boundedOptions
729
+ );
730
+ if (nextResponse.case !== "position")
731
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
732
+ assertShardPage(first, nextResponse.value, lpPositionId, auth, nextIndex);
733
+ shards.push(...nextResponse.value.shards);
734
+ nextIndex = nextResponse.value.shards_next_index;
735
+ }
736
+ if (shards.length !== first.shards_total_count)
737
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
738
+ full = { ...first, shards };
739
+ } else if (first.target_shard_count > LP_MAX_TOTAL_SHARDS || first.lp_position_id !== lpPositionId || first.shards.length > LP_MAX_INITIAL_SHARDS || first.status !== "dkg_pending" && first.target_shard_count > LP_MAX_INITIAL_SHARDS && first.shards.length !== first.target_shard_count || first.status === "dkg_pending" && first.target_shard_count > LP_MAX_INITIAL_SHARDS && first.target_shard_count - first.shards.length > LP_MAX_REFILL_BATCH_SIZE) {
740
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
741
+ }
742
+ let position = mapPosition(full);
743
+ let historyPage = first;
744
+ const seenCursors = /* @__PURE__ */ new Set();
745
+ while (historyPage.actor_sync?.redemption_history_has_more === true) {
746
+ const cursor = historyPage.actor_sync.redemption_history_next_cursor;
747
+ if (cursor === void 0 || seenCursors.has(cursor)) {
748
+ throw new CommandError(
749
+ "REJECTED_STATE",
750
+ "coordinator LP actor sync returned an invalid redemption history cursor"
751
+ );
752
+ }
753
+ seenCursors.add(cursor);
754
+ const nextResponse = await requestForPosition(
755
+ session,
756
+ lpPositionId,
757
+ auth,
758
+ "position_get",
759
+ {
760
+ case: "positionGet",
761
+ value: {
762
+ redemption_history_cursor: cursor,
763
+ ...first.shards_snapshot_hash === void 0 ? {} : { shard_start_index: 0, shards_snapshot_hash: first.shards_snapshot_hash }
764
+ }
765
+ },
766
+ boundedOptions
767
+ );
768
+ if (nextResponse.case !== "position")
769
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
770
+ historyPage = nextResponse.value;
771
+ if (first.shards_snapshot_hash !== void 0)
772
+ assertShardPage(first, historyPage, lpPositionId, auth, 0);
773
+ const historyView = mapPosition(historyPage);
774
+ validateLpPositionFeePolicy(historyView, position);
775
+ const merged = mergePositionHistoryPages(position, historyView);
776
+ position = first.shards_snapshot_hash === void 0 ? merged : {
777
+ ...position,
778
+ actorSync: position.actorSync === void 0 ? void 0 : {
779
+ ...position.actorSync,
780
+ redemptionHistory: merged.actorSync?.redemptionHistory,
781
+ redemptionHistoryHasMore: historyView.actorSync?.redemptionHistoryHasMore ?? false,
782
+ redemptionHistoryNextCursor: historyView.actorSync?.redemptionHistoryNextCursor
783
+ }
784
+ };
785
+ }
786
+ lpPositionPageRequestOptions(boundedOptions);
787
+ return position;
788
+ } catch (error) {
789
+ if (!(error instanceof CommandError) || !error.message.includes(LP_SHARD_SNAPSHOT_CHANGED_MESSAGE) || attempt + 1 >= LP_POSITION_SNAPSHOT_MAX_ATTEMPTS)
790
+ throw error;
791
+ initialResponse = void 0;
792
+ lpPositionPageRequestOptions(boundedOptions);
591
793
  }
592
- seenCursors.add(nextCursor);
593
- cursor = nextCursor;
594
794
  }
795
+ throw new CommandError("REJECTED_STATE", LP_SHARD_SNAPSHOT_CHANGED_MESSAGE);
796
+ }
797
+ function assertShardPage(first, page, lpPositionId, auth, startIndex) {
798
+ const total = first.shards_total_count;
799
+ const invalid = () => {
800
+ throw new CommandError("REJECTED_STATE", LP_SHARD_PAGE_INVALID_MESSAGE);
801
+ };
802
+ if (total === void 0 || !Number.isInteger(total) || total < 1 || total > LP_MAX_TOTAL_SHARDS || total > first.target_shard_count || first.status !== "dkg_pending" && total !== first.target_shard_count || first.shards_snapshot_hash === void 0 || !LP_SHARD_SNAPSHOT_HASH_PATTERN.test(first.shards_snapshot_hash) || page.lp_position_id !== lpPositionId || page.shards_snapshot_hash !== first.shards_snapshot_hash || page.shards_total_count !== total || page.target_shard_count !== first.target_shard_count || page.status !== "dkg_pending" && total !== page.target_shard_count || page.created_at_ms !== first.created_at_ms || page.committed_lamports !== first.committed_lamports || page.earned_lamports !== first.earned_lamports || page.refill_threshold !== first.refill_threshold || page.fee_policy?.policy_hash !== first.fee_policy?.policy_hash || page.lp_fee_policy_version !== first.lp_fee_policy_version || bytesToHex(page.auth_public_key) !== bytesToHex(auth.authPublicKey) || bytesToHex(page.refill_public_key) !== bytesToHex(first.refill_public_key) || bytesToHex(page.redemption_commitment) !== bytesToHex(first.redemption_commitment) || page.shards.length !== Math.min(LP_SHARD_PAGE_SIZE, total - startIndex) || page.shards.length === 0)
803
+ invalid();
804
+ for (const [offset, shard] of page.shards.entries()) {
805
+ const index = startIndex + offset;
806
+ if (shard.index !== index || shard.lp_position_id !== lpPositionId || shard.shard_id !== `${lpPositionId}:shard:${index}`)
807
+ invalid();
808
+ }
809
+ const end = startIndex + page.shards.length;
810
+ if (total === void 0) invalid();
811
+ if (end < total ? page.shards_next_index !== end : page.shards_next_index !== void 0)
812
+ invalid();
813
+ if (page.status !== first.status)
814
+ throw new CommandError("REJECTED_STATE", LP_SHARD_SNAPSHOT_CHANGED_MESSAGE);
595
815
  }
596
816
  function lpPositionPageRequestOptions(options) {
597
817
  if (options.deadlineMs === void 0) return options;
@@ -614,7 +834,7 @@ async function finalizeDkgBatch(session, input, auth) {
614
834
  finalized_at_ms: input.finalizedAtMs
615
835
  }
616
836
  });
617
- return expectPosition(response);
837
+ return hydratePositionResponse(session, auth.lpPositionId, auth, response);
618
838
  }
619
839
  async function refillPosition(session, input, auth) {
620
840
  const response = await requestForPosition(session, input.lpPositionId, auth, "refill", {
@@ -626,14 +846,14 @@ async function refillPosition(session, input, auth) {
626
846
  authorized_at_ms: input.authorizedAtMs
627
847
  }
628
848
  });
629
- return expectPosition(response);
849
+ return hydratePositionResponse(session, auth.lpPositionId, auth, response);
630
850
  }
631
851
  async function reconcileFunding(session, lpPositionId, auth) {
632
852
  const response = await requestForPosition(session, lpPositionId, auth, "reconcile_funding", {
633
853
  case: "reconcileFunding",
634
854
  value: {}
635
855
  });
636
- return expectPosition(response);
856
+ return hydratePositionResponse(session, auth.lpPositionId, auth, response);
637
857
  }
638
858
  async function planFunding(session, input, auth) {
639
859
  const response = await requestForPosition(session, input.lpPositionId, auth, "funding_plan", {
@@ -707,13 +927,21 @@ async function executeWithdrawal(session, input, auth) {
707
927
  deposit_principal_lamports: input.withdrawalMode === "max_available" ? 0 : input.depositPrincipalLamports,
708
928
  earned_fee_lamports: input.withdrawalMode === "max_available" ? 0 : input.earnedFeeLamports,
709
929
  withdrawal_mode: input.withdrawalMode,
710
- requested_at_ms: input.requestedAtMs
930
+ requested_at_ms: input.requestedAtMs,
931
+ fee_policy_hash: input.feePolicyHash,
932
+ fee_basis_revision: input.feeBasisRevision
711
933
  }
712
934
  });
713
935
  if (response.case !== "withdrawalExecution") {
714
936
  throw new Error("Unexpected LP withdrawal execution response");
715
937
  }
716
938
  const execution = response.value;
939
+ if (execution.fee_policy_hash !== input.feePolicyHash || execution.fee_basis_revision !== input.feeBasisRevision) {
940
+ throw new PolicyValidationError(
941
+ "INVALID_WITHDRAWAL_PLAN",
942
+ "Coordinator accepted a different LP fee policy or fee basis"
943
+ );
944
+ }
717
945
  if (BigInt(execution.accepted_lamports) !== BigInt(execution.accepted_deposit_principal_lamports) + BigInt(execution.accepted_earned_fee_lamports)) {
718
946
  throw new PolicyValidationError(
719
947
  "INVALID_WITHDRAWAL_PLAN",
@@ -727,6 +955,8 @@ async function executeWithdrawal(session, input, auth) {
727
955
  );
728
956
  }
729
957
  return {
958
+ feePolicyHash: execution.fee_policy_hash,
959
+ feeBasisRevision: execution.fee_basis_revision,
730
960
  withdrawalId: execution.withdrawal_id,
731
961
  txSignatures: [...execution.tx_signatures],
732
962
  acceptedLamports: execution.accepted_lamports,
@@ -738,7 +968,7 @@ function request(session, auth, action, payload) {
738
968
  return requestForPosition(session, auth.lpPositionId, auth, action, payload);
739
969
  }
740
970
  async function requestForPosition(session, lpPositionId, auth, action, payload, options = {}) {
741
- const timeoutMs = options.timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS;
971
+ const timeoutMs = lpPositionPageRequestOptions(options).timeoutMs ?? LP_COMMAND_REQUEST_TIMEOUT_MS;
742
972
  assertAuthMatchesPosition(lpPositionId, auth);
743
973
  const protocol = await loadProtocol();
744
974
  const state = getSessionState(session);
@@ -773,12 +1003,10 @@ function assertAuthMatchesPosition(lpPositionId, auth) {
773
1003
  "LP Position Code does not match the target LP position"
774
1004
  );
775
1005
  }
776
- function expectPosition(response) {
777
- if (response.case !== "position") throw new Error("Unexpected LP position response");
778
- return mapPosition(response.value);
779
- }
780
1006
  function mapPosition(position) {
781
- return {
1007
+ const mapped = {
1008
+ feePolicy: position.fee_policy === void 0 ? void 0 : validateLpFeePolicy(position.fee_policy),
1009
+ lpFeePolicyVersion: position.lp_fee_policy_version,
782
1010
  id: position.lp_position_id,
783
1011
  status: position.status,
784
1012
  targetShardCount: position.target_shard_count,
@@ -793,6 +1021,8 @@ function mapPosition(position) {
793
1021
  redemptionPermission: mapLpRedemptionPermission(position.redemption_permission),
794
1022
  ...position.actor_sync === void 0 ? {} : { actorSync: mapLpActorSync(position.actor_sync) }
795
1023
  };
1024
+ validateLpPositionFeePolicy(mapped);
1025
+ return mapped;
796
1026
  }
797
1027
  function mapLpRedemptionPermission(permission) {
798
1028
  if (permission === void 0) {
@@ -822,10 +1052,22 @@ function mapLpActorSync(actorSync) {
822
1052
  );
823
1053
  }
824
1054
  const redeemableProjectionAvailable = redeemableBucketCount === redeemableBucketValues.length;
825
- return {
1055
+ return normalizeLpActorSync({
1056
+ ...actorSync.economic_return === void 0 ? {} : {
1057
+ economicReturn: mapLpEconomicReturn(
1058
+ actorSync.economic_return,
1059
+ actorSync.protocol_commission_lamports ?? 0
1060
+ )
1061
+ },
1062
+ feePolicy: actorSync.fee_policy === void 0 ? void 0 : validateLpFeePolicy(actorSync.fee_policy),
1063
+ feeBasisRevision: actorSync.fee_basis_revision,
1064
+ grossFeeLamports: actorSync.gross_fee_lamports,
1065
+ protocolCommissionLamports: actorSync.protocol_commission_lamports,
1066
+ waivedProtocolCommissionLamports: actorSync.waived_protocol_commission_lamports,
826
1067
  lpPositionId: actorSync.lp_position_id,
827
1068
  status: actorSync.status,
828
1069
  sourceLiquidityUse: actorSync.source_liquidity_use,
1070
+ totalNetFundsLamports: actorSync.total_net_funds_lamports,
829
1071
  redeemableProjectionAvailable,
830
1072
  redeemablePrincipalLamports: actorSync.redeemable_principal_lamports ?? 0,
831
1073
  redeemableFeeLamports: actorSync.redeemable_fee_lamports ?? 0,
@@ -851,6 +1093,33 @@ function mapLpActorSync(actorSync) {
851
1093
  ...actorSync.redemption_history_next_cursor === void 0 ? {} : { redemptionHistoryNextCursor: actorSync.redemption_history_next_cursor },
852
1094
  stateVersion: actorSync.state_version,
853
1095
  updatedAtMs: actorSync.updated_at_ms
1096
+ });
1097
+ }
1098
+ var LP_ECONOMIC_UNSIGNED_TOTAL_MAX = (1n << 128n) - 1n;
1099
+ var LP_ECONOMIC_SIGNED_TOTAL_MIN = -(1n << 127n);
1100
+ var LP_ECONOMIC_SIGNED_TOTAL_MAX = (1n << 127n) - 1n;
1101
+ var LP_ECONOMIC_UNSIGNED_DECIMAL = /^(0|[1-9][0-9]*)$/;
1102
+ var LP_ECONOMIC_SIGNED_DECIMAL = /^(0|-?[1-9][0-9]*)$/;
1103
+ function mapLpEconomicReturn(summary, protocolCommissionLamports) {
1104
+ const unsigned = [
1105
+ summary.provider_reward_lamports,
1106
+ summary.source_expense_compensation_lamports,
1107
+ summary.charged_reimbursement_loss_lamports
1108
+ ];
1109
+ const valid = unsigned.every(
1110
+ (value) => typeof value === "string" && LP_ECONOMIC_UNSIGNED_DECIMAL.test(value) && BigInt(value) <= LP_ECONOMIC_UNSIGNED_TOTAL_MAX
1111
+ ) && typeof summary.net_economic_return_lamports === "string" && LP_ECONOMIC_SIGNED_DECIMAL.test(summary.net_economic_return_lamports);
1112
+ if (!valid)
1113
+ throw new CommandError("REJECTED_STATE", "coordinator LP economic return totals are invalid");
1114
+ const net = BigInt(summary.net_economic_return_lamports);
1115
+ if (net < LP_ECONOMIC_SIGNED_TOTAL_MIN || net > LP_ECONOMIC_SIGNED_TOTAL_MAX || net !== BigInt(summary.provider_reward_lamports) - BigInt(summary.charged_reimbursement_loss_lamports) - BigInt(protocolCommissionLamports)) {
1116
+ throw new CommandError("REJECTED_STATE", "coordinator LP economic return invariant is invalid");
1117
+ }
1118
+ return {
1119
+ providerRewardLamports: summary.provider_reward_lamports,
1120
+ sourceExpenseCompensationLamports: summary.source_expense_compensation_lamports,
1121
+ chargedReimbursementLossLamports: summary.charged_reimbursement_loss_lamports,
1122
+ netEconomicReturnLamports: summary.net_economic_return_lamports
854
1123
  };
855
1124
  }
856
1125
  function mergePositionHistoryPages(first, next) {
@@ -874,6 +1143,8 @@ function mergePositionHistoryPages(first, next) {
874
1143
  }
875
1144
  function mapLpRedemptionHistory(history) {
876
1145
  return {
1146
+ feePolicyHash: history.fee_policy_hash,
1147
+ feeBasisRevision: history.fee_basis_revision,
877
1148
  redemptionId: history.redemption_id,
878
1149
  state: history.state,
879
1150
  ...history.withdrawal_mode === void 0 ? {} : { withdrawalMode: history.withdrawal_mode },
@@ -955,7 +1226,7 @@ function randomBytes(length) {
955
1226
  return bytes;
956
1227
  }
957
1228
  function loadProtocol() {
958
- protocolPromise ??= import('./coordinator-E2TS6NR2.js');
1229
+ protocolPromise ??= import('./coordinator-T2B7253V.js');
959
1230
  return protocolPromise;
960
1231
  }
961
1232
 
@@ -1253,6 +1524,7 @@ function isLpPositionAuthMissingError(error) {
1253
1524
  return error instanceof LpPositionAuthMissingError || error instanceof Error && error.message === LP_MISSING_POSITION_CODE_MESSAGE;
1254
1525
  }
1255
1526
  function previewLpWithdrawalPlan(position, args = {}) {
1527
+ validateLpPositionFeePolicy(position);
1256
1528
  const claim = resolveWithdrawalClaim(position, args);
1257
1529
  return {
1258
1530
  ...claim,
@@ -1285,11 +1557,13 @@ function createLpLifecycleClient(session, runtime = {}) {
1285
1557
  return auth;
1286
1558
  };
1287
1559
  const rememberPosition = (position) => {
1560
+ validateLpPositionFeePolicy(position, state.positions.get(position.id));
1288
1561
  const snapshot = clonePosition(position);
1289
1562
  const previous = state.positions.get(snapshot.id);
1290
- const merged = previous === void 0 ? snapshot : {
1563
+ const merged = {
1291
1564
  ...snapshot,
1292
- redemptionPermission: mergeLpRedemptionPermission(
1565
+ actorSync: mergeLpActorSync(previous?.actorSync, snapshot.actorSync),
1566
+ redemptionPermission: previous === void 0 ? snapshot.redemptionPermission : mergeLpRedemptionPermission(
1293
1567
  previous.redemptionPermission,
1294
1568
  snapshot.redemptionPermission
1295
1569
  )
@@ -1327,7 +1601,7 @@ function createLpLifecycleClient(session, runtime = {}) {
1327
1601
  const current = rememberPosition(await client.getPosition(positionId, auth));
1328
1602
  options.onPosition?.(current);
1329
1603
  const startIndex = current.shards.length;
1330
- const remaining = current.targetShardCount - startIndex;
1604
+ const remaining = Math.min(current.targetShardCount - startIndex, LP_MAX_INITIAL_SHARDS);
1331
1605
  if (remaining <= 0) return current;
1332
1606
  emitDkgProgress(options, current, startIndex, remaining, 0);
1333
1607
  let expectedAddresses = null;
@@ -1357,7 +1631,9 @@ function createLpLifecycleClient(session, runtime = {}) {
1357
1631
  );
1358
1632
  options.onPosition?.(position);
1359
1633
  emitDkgProgress(options, position, startIndex, remaining, remaining);
1360
- return rememberPosition(position);
1634
+ rememberPosition(position);
1635
+ if (position.shards.length < position.targetShardCount) continue;
1636
+ return position;
1361
1637
  } catch (error) {
1362
1638
  const reconciled = await tryRefreshCompletedDkgWindow({
1363
1639
  client,
@@ -1387,7 +1663,7 @@ function createLpLifecycleClient(session, runtime = {}) {
1387
1663
  async createPosition(args) {
1388
1664
  assertNoUnsupportedFeePolicy(args.feePolicy);
1389
1665
  const shardCount = args.shardCount ?? LP_DEFAULT_TARGET_SHARDS;
1390
- assertShardCount(shardCount, LP_MAX_TARGET_SHARDS, "shardCount");
1666
+ assertShardCount(shardCount, LP_MAX_INITIAL_SHARDS, "shardCount");
1391
1667
  assertAttested(currentSession);
1392
1668
  const committedLamports = args.committedLamports ?? DEFAULT_SHARD_FUNDING_LAMPORTS;
1393
1669
  const refillThreshold = args.refillThreshold ?? Math.ceil(shardCount * DEFAULT_REFILL_THRESHOLD_RATIO);
@@ -1408,6 +1684,7 @@ function createLpLifecycleClient(session, runtime = {}) {
1408
1684
  {
1409
1685
  lpPositionId: positionId,
1410
1686
  creationAuthorizationId: creationAuthorization.authorizationId,
1687
+ feePolicy: creationAuthorization.feePolicy,
1411
1688
  authPublicKey: Array.from(auth.authPublicKey),
1412
1689
  refillPublicKey: Array.from(auth.refillPublicKey),
1413
1690
  withdrawalCommitment: Array.from(auth.withdrawalCommitment),
@@ -1448,11 +1725,7 @@ function createLpLifecycleClient(session, runtime = {}) {
1448
1725
  const auth = requireAuth(positionId);
1449
1726
  const current = await refreshPosition2(positionId);
1450
1727
  args.onPosition?.(current);
1451
- const refillShardCount = resolveLpRefillShardCount(
1452
- current,
1453
- requestedShardCount,
1454
- args.shardCount === void 0
1455
- );
1728
+ const refillShardCount = resolveLpRefillShardCount(current, requestedShardCount);
1456
1729
  const authorizedPosition = rememberPosition(
1457
1730
  await client.refillPosition(
1458
1731
  {
@@ -1572,6 +1845,8 @@ function createLpLifecycleClient(session, runtime = {}) {
1572
1845
  const existingRedemption = findOpenRedemptionHistory(before, args);
1573
1846
  if (existingRedemption !== void 0) {
1574
1847
  const execution2 = {
1848
+ feePolicyHash: existingRedemption.feePolicyHash,
1849
+ feeBasisRevision: existingRedemption.feeBasisRevision,
1575
1850
  withdrawalId: existingRedemption.redemptionId,
1576
1851
  txSignatures: [...existingRedemption.txSignatures],
1577
1852
  acceptedLamports: existingRedemption.acceptedLamports,
@@ -1616,6 +1891,8 @@ function createLpLifecycleClient(session, runtime = {}) {
1616
1891
  earnedFeeLamports: args.withdrawalMode === "max_available" ? 0 : preview.earnedFeeLamports,
1617
1892
  withdrawalMode: args.withdrawalMode,
1618
1893
  requestedAtMs,
1894
+ feePolicyHash: before.feePolicy?.policy_hash,
1895
+ feeBasisRevision: before.actorSync?.feeBasisRevision,
1619
1896
  allowManyToOne: args.allowManyToOne === true || preview?.sourceCount === 1
1620
1897
  },
1621
1898
  auth
@@ -1744,6 +2021,7 @@ async function tryRefreshCompletedDkgWindow({
1744
2021
  const position = await client.getPosition(positionId, auth).catch(() => null);
1745
2022
  if (position === null) return null;
1746
2023
  if (!hasCompletedDkgWindow(position, startIndex, total, expectedAddresses)) return null;
2024
+ validateLpPositionFeePolicy(position, state.positions.get(position.id));
1747
2025
  state.positions.set(position.id, clonePosition(position));
1748
2026
  return position;
1749
2027
  }
@@ -1785,21 +2063,12 @@ function assertShardCount(value, max, field) {
1785
2063
  );
1786
2064
  }
1787
2065
  }
1788
- function resolveLpRefillShardCount(position, requestedShardCount, capDefaultBatch) {
1789
- const remainingShardCapacity = LP_MAX_TARGET_SHARDS - position.shards.length;
1790
- if (remainingShardCapacity <= 0) {
1791
- throw new PolicyValidationError(
1792
- "INVALID_AMOUNT",
1793
- `LP refill target_shard_count is already at ${LP_MAX_TARGET_SHARDS}`
1794
- );
1795
- }
1796
- const refillShardCount = capDefaultBatch ? Math.min(requestedShardCount, remainingShardCapacity) : requestedShardCount;
1797
- if (position.shards.length + refillShardCount > LP_MAX_TARGET_SHARDS) {
1798
- throw new PolicyValidationError(
1799
- "INVALID_AMOUNT",
1800
- `LP refill target_shard_count must be <= ${LP_MAX_TARGET_SHARDS}`
1801
- );
2066
+ function resolveLpRefillShardCount(position, requestedShardCount) {
2067
+ const nextTarget = position.shards.length + requestedShardCount;
2068
+ if (!Number.isSafeInteger(nextTarget) || nextTarget > LP_MAX_TOTAL_SHARDS) {
2069
+ throw new PolicyValidationError("INVALID_AMOUNT", "LP refill target_shard_count overflows u32");
1802
2070
  }
2071
+ const refillShardCount = requestedShardCount;
1803
2072
  return refillShardCount;
1804
2073
  }
1805
2074
  function isLpPositionReadyForInitialFunding(position) {
@@ -1851,7 +2120,9 @@ function hasActorSyncLpActivity(sync) {
1851
2120
  }
1852
2121
  function resolveRedeemablePrincipalLamports(sync, legacyAvailableLamports, actorRedeemablePrincipalLamports, actorRedeemableFeeLamports) {
1853
2122
  if (sync?.redeemableProjectionAvailable !== true) return legacyAvailableLamports;
1854
- if (legacyAvailableLamports <= 0) return actorRedeemablePrincipalLamports;
2123
+ if (sync.feePolicy !== void 0 || legacyAvailableLamports <= 0) {
2124
+ return actorRedeemablePrincipalLamports;
2125
+ }
1855
2126
  if (actorRedeemablePrincipalLamports >= legacyAvailableLamports || hasActorSyncLpActivity(sync)) {
1856
2127
  return actorRedeemablePrincipalLamports;
1857
2128
  }
@@ -1956,6 +2227,8 @@ function buildLpRedemptionRecord({
1956
2227
  nowMs
1957
2228
  }) {
1958
2229
  return {
2230
+ feePolicyHash: execution.feePolicyHash,
2231
+ feeBasisRevision: execution.feeBasisRevision,
1959
2232
  redemptionId: execution.withdrawalId,
1960
2233
  lpPositionId: position.id,
1961
2234
  requestedAt: nowMs,
@@ -2004,7 +2277,7 @@ function reconcileLpRedemptionFromActorSync(record, position) {
2004
2277
  function reconcileLpRedemptionFromHistory(record, history) {
2005
2278
  const observedStateVersion = record.coordinatorStateVersion ?? 0;
2006
2279
  if (history.stateVersion < observedStateVersion) return record;
2007
- if (record.acceptedLamports !== void 0 && history.acceptedLamports !== record.acceptedLamports || history.detailsTruncated !== true && !sameStringList(history.destinationAddresses, record.destinationAddresses)) {
2280
+ if (history.feePolicyHash !== record.feePolicyHash || history.feeBasisRevision !== record.feeBasisRevision || record.acceptedLamports !== void 0 && history.acceptedLamports !== record.acceptedLamports || history.detailsTruncated !== true && !sameStringList(history.destinationAddresses, record.destinationAddresses)) {
2008
2281
  return {
2009
2282
  ...record,
2010
2283
  status: "failed",
@@ -2017,6 +2290,7 @@ function reconcileLpRedemptionFromHistory(record, history) {
2017
2290
  ...record,
2018
2291
  coordinatorStateVersion: history.stateVersion,
2019
2292
  redeemedLamports: history.landedLamports,
2293
+ networkFeeLossLamports: history.networkFeeLossLamports,
2020
2294
  txSignatures,
2021
2295
  destinationCount: history.destinationCount,
2022
2296
  txSignatureCount: history.txSignatureCount,
@@ -2053,6 +2327,8 @@ function hydrateLpRedemptionsFromPosition(state, position) {
2053
2327
  }
2054
2328
  function lpWithdrawalRecordFromHistory(position, history) {
2055
2329
  const record = {
2330
+ feePolicyHash: history.feePolicyHash,
2331
+ feeBasisRevision: history.feeBasisRevision,
2056
2332
  redemptionId: history.redemptionId,
2057
2333
  lpPositionId: position.id,
2058
2334
  requestedAt: history.createdAtMs,
@@ -2063,6 +2339,7 @@ function lpWithdrawalRecordFromHistory(position, history) {
2063
2339
  landedBaselineLamports: 0,
2064
2340
  landedFeeBaselineLamports: 0,
2065
2341
  redeemedLamports: history.landedLamports,
2342
+ networkFeeLossLamports: history.networkFeeLossLamports,
2066
2343
  txSignatures: [...history.txSignatures],
2067
2344
  txSignatureBaseline: [],
2068
2345
  coordinatorStateVersion: history.stateVersion,
@@ -2081,6 +2358,7 @@ function uniqueStrings(values) {
2081
2358
  function clonePosition(position) {
2082
2359
  return {
2083
2360
  ...position,
2361
+ feePolicy: position.feePolicy === void 0 ? void 0 : { ...position.feePolicy },
2084
2362
  shards: position.shards.map((shard) => ({ ...shard })),
2085
2363
  actorSync: position.actorSync === void 0 ? void 0 : {
2086
2364
  ...position.actorSync,
@@ -2193,6 +2471,6 @@ function listPositions(session) {
2193
2471
  return defaultLpLifecycleClient(session).listPositions();
2194
2472
  }
2195
2473
 
2196
- export { LP_COMMAND_REQUEST_TIMEOUT_MS, LP_DKG_ABORT_CLEANUP_TIMEOUT_MS, LP_DKG_ABORT_REQUEST_TIMEOUT_MS, LP_DKG_WORKER_REQUEST_TIMEOUT_MESSAGE, LP_DKG_WORKER_REQUEST_TIMEOUT_MS, LP_FEE_SOURCE_COUNT_UNAVAILABLE_MESSAGE, LP_MISSING_POSITION_CODE_MESSAGE, LP_REDEMPTION_RECONCILING_MESSAGE, bytesToHex, completeDkgBatch, confirmPositionCodeSaved, createLpCoordinatorClient, createLpDkgBatch, createLpLifecycleClient, createPosition, defaultLpLifecycleClient, deriveLpPositionCodeAuth, generateLpPositionCode, isLpPositionAuthMissingError, isLpRedemptionReconcilingError, listPositions, normalizeLpPositionCode, prepareInitialFunding, prepareTopUp2 as prepareTopUp, previewLpWithdrawalPlan, reconcileFunding2 as reconcileFunding, recoverPosition, refill, refreshPosition, signLpCommandBytes, waitForTopUp, waitForWithdrawalConfirmation, withdrawFees, withdrawPosition };
2474
+ 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 };
2197
2475
  //# sourceMappingURL=lp.js.map
2198
2476
  //# sourceMappingURL=lp.js.map