@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/stats.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NotImplementedError } from './chunk-QRN46R3F.js';
1
+ import { NotImplementedError } from './chunk-RWKG7N7I.js';
2
2
  import './chunk-VR6T6OJS.js';
3
3
 
4
4
  // src/stats/index.ts
package/dist/storage.js CHANGED
@@ -1,5 +1,5 @@
1
- export { browserStorage, extensionStorage, inMemoryStorage } from './chunk-DCTYBUY3.js';
2
- import './chunk-QRN46R3F.js';
1
+ export { browserStorage, extensionStorage, inMemoryStorage } from './chunk-AIKC2XQS.js';
2
+ import './chunk-RWKG7N7I.js';
3
3
  import './chunk-VR6T6OJS.js';
4
4
  //# sourceMappingURL=storage.js.map
5
5
  //# sourceMappingURL=storage.js.map
@@ -18,9 +18,10 @@ type TransportErrorCode = "WS_HANDSHAKE_FAILED" | "NOISE_HANDSHAKE_FAILED" | "NO
18
18
  /** Leader/role routing failures. Failover and re-attest. */
19
19
  type RoutingErrorCode = "WRONG_ROLE" | "STALE_LEADER_EPOCH" | "POOL_DEGRADED" | "VERSION_NOT_SUPPORTED";
20
20
  /** Coordinator-side command rejections. Product decides whether to retry. */
21
- type CommandErrorCode = "REJECTED_GUARD" | "REJECTED_STATE" | "REJECTED_EXPIRED" | "REJECTED_STALE_JOB" | "REJECTED_RESOURCE_CAP";
21
+ type CommandErrorCode = "REJECTED_GUARD" | "REJECTED_STATE" | "REJECTED_EXPIRED" | "REJECTED_STALE_JOB" | "REJECTED_RESOURCE_CAP" | "RETRYABLE_BUSY";
22
+ declare const COORDINATOR_CAPACITY_FULL_ERROR_CODE: "ERR_ADMISSION_CAPACITY_FULL";
22
23
  /** Coordinator wire error code preserved on command rejections. */
23
- type CoordinatorWireErrorCode = "ERR_INVALID_PAYLOAD" | "ERR_UNEXPECTED_TYPE" | "ERR_UNKNOWN_SWAP" | "ERR_POLICY_VIOLATION" | "ERR_INVALID_RECOVERY_CODE" | "ERR_SWAP_NOT_REFUNDABLE" | "ERR_DKG_FAILURE" | "ERR_INTERNAL" | "ERR_INVALID_DEPOSIT" | "ERR_SETTLEMENT_FAILED";
24
+ type CoordinatorWireErrorCode = "ERR_INVALID_PAYLOAD" | "ERR_UNEXPECTED_TYPE" | "ERR_UNKNOWN_SWAP" | "ERR_POLICY_VIOLATION" | "ERR_INVALID_RECOVERY_CODE" | "ERR_SWAP_NOT_REFUNDABLE" | "ERR_DKG_FAILURE" | "ERR_INTERNAL" | "ERR_PRESEAL_ADMISSION_BUSY" | "ERR_INITIALIZATION_BUSY" | typeof COORDINATOR_CAPACITY_FULL_ERROR_CODE | "ERR_INVALID_DEPOSIT" | "ERR_SETTLEMENT_FAILED";
24
25
  /** Local input-validation failures. Never sent on the wire; fix the input. */
25
26
  type PolicyValidationErrorCode = "INVALID_PAYOUT_PLAN" | "INVALID_WITHDRAWAL_PLAN" | "INVALID_POSITION_AUTH" | "INVALID_REDEMPTION_PLAN" | "INVALID_DESTINATION_ADDRESS" | "INVALID_AMOUNT";
26
27
  /** Storage-adapter failures. */
@@ -53,6 +54,8 @@ interface StorageErrorOptions extends InvisibleErrorOptions {
53
54
  interface CommandErrorOptions extends InvisibleErrorOptions {
54
55
  /** Exact coordinator `Error` envelope code, when the rejection came from the wire. */
55
56
  readonly coordinatorCode?: CoordinatorWireErrorCode;
57
+ /** Exact coordinator `Error` envelope message, when `message` is user-facing copy. */
58
+ readonly coordinatorMessage?: string;
56
59
  /** Request id rejected by the coordinator, when present in the `Error` envelope. */
57
60
  readonly failedReqId?: number;
58
61
  }
@@ -84,6 +87,7 @@ declare class RoutingError extends InvisibleError {
84
87
  declare class CommandError extends InvisibleError {
85
88
  readonly code: CommandErrorCode;
86
89
  readonly coordinatorCode?: CoordinatorWireErrorCode;
90
+ readonly coordinatorMessage?: string;
87
91
  readonly failedReqId?: number;
88
92
  constructor(code: CommandErrorCode, message: string, options?: CommandErrorOptions);
89
93
  }
@@ -142,6 +146,12 @@ type RuntimeMeasurements = {
142
146
  readonly rtmr2: string;
143
147
  readonly rtmr3: string;
144
148
  };
149
+ type LpFeePolicy = {
150
+ readonly version: 1;
151
+ readonly profile: "internal" | "partner";
152
+ readonly commission_bps: 0 | 6000;
153
+ readonly policy_hash: string;
154
+ };
145
155
  type LpPositionView = {
146
156
  readonly id: string;
147
157
  readonly status: "dkg_pending" | "active" | "withdrawing" | "closed";
@@ -161,6 +171,74 @@ type LpPositionView = {
161
171
  readonly grantRevision: number;
162
172
  readonly observedAtMs: number;
163
173
  };
174
+ readonly feePolicy?: LpFeePolicy;
175
+ readonly lpFeePolicyVersion?: 1;
176
+ readonly actorSync?: {
177
+ readonly economicReturn?: {
178
+ readonly providerRewardLamports: string;
179
+ readonly sourceExpenseCompensationLamports: string;
180
+ readonly chargedReimbursementLossLamports: string;
181
+ readonly netEconomicReturnLamports: string;
182
+ };
183
+ readonly lpPositionId: string;
184
+ readonly status: "idle" | "settling" | "reimbursement_due";
185
+ readonly sourceLiquidityUse: "not_materialized" | "available" | "locked_for_payout" | "pending_finality" | "spent" | "released";
186
+ readonly redeemablePrincipalLamports?: number;
187
+ readonly redeemableFeeLamports?: number;
188
+ readonly lifetimeEarnedLamports?: number;
189
+ readonly redeemablePrincipalSourceCount?: number;
190
+ readonly redeemableFeeSourceCount?: number;
191
+ readonly redeemableSourceCount?: number;
192
+ readonly pendingReservationCount: number;
193
+ readonly reservedPayoutLamports: number;
194
+ readonly estimatedNetworkFeeLamports: number;
195
+ readonly reimbursementDueCount: number;
196
+ readonly reimbursementDueSourceCount: number;
197
+ readonly reimbursementDuePayoutLamports: number;
198
+ readonly reimbursementDueNetworkFeeLamports: number;
199
+ readonly withdrawalRequestedLamports: number;
200
+ readonly withdrawalLandedLamports: number;
201
+ readonly withdrawalLandedFeeLamports: number;
202
+ readonly withdrawalCanceledLamports: number;
203
+ readonly withdrawalNetworkFeeLossLamports: number;
204
+ readonly withdrawalTxHashes: readonly string[];
205
+ readonly redemptionHistory?: readonly {
206
+ readonly redemptionId: string;
207
+ readonly state: "requested" | "match_requested" | "reserved" | "pending" | "confirmed" | "rejected";
208
+ readonly withdrawalMode?: "exact" | "max_available";
209
+ readonly acceptedLamports: number;
210
+ readonly acceptedDepositPrincipalLamports: number;
211
+ readonly acceptedEarnedFeeLamports: number;
212
+ readonly landedLamports: number;
213
+ readonly landedDepositPrincipalLamports: number;
214
+ readonly landedEarnedFeeLamports: number;
215
+ readonly canceledLamports: number;
216
+ readonly canceledDepositPrincipalLamports: number;
217
+ readonly canceledEarnedFeeLamports: number;
218
+ readonly networkFeeLamports: number;
219
+ readonly networkFeeLossLamports: number;
220
+ readonly failedAttempts: number;
221
+ readonly destinationAddresses: readonly string[];
222
+ readonly destinationCount: number;
223
+ readonly txSignatures: readonly string[];
224
+ readonly txSignatureCount: number;
225
+ readonly detailsTruncated: boolean;
226
+ readonly stateVersion: number;
227
+ readonly createdAtMs: number;
228
+ readonly updatedAtMs: number;
229
+ readonly feePolicyHash?: string;
230
+ readonly feeBasisRevision?: number;
231
+ }[];
232
+ readonly redemptionHistoryHasMore?: boolean;
233
+ readonly redemptionHistoryNextCursor?: string;
234
+ readonly stateVersion: number;
235
+ readonly updatedAtMs: number;
236
+ readonly feePolicy?: LpFeePolicy;
237
+ readonly feeBasisRevision?: number;
238
+ readonly grossFeeLamports?: number;
239
+ readonly protocolCommissionLamports?: number;
240
+ readonly redeemableProjectionAvailable: boolean;
241
+ };
164
242
  };
165
243
  type PayoutDestination = {
166
244
  readonly address: string;
package/dist/user.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { C as CommandError, P as PayoutPolicy } from './types.generated-CtMxCo9F.js';
2
+ export { I as InvalidDepositAmountError } from './types.generated-CtMxCo9F.js';
1
3
  import { S as Session } from './session-DFuy54C-.js';
2
- import { P as PayoutPolicy } from './types.generated-YhFu9ZBR.js';
3
- export { I as InvalidDepositAmountError } from './types.generated-YhFu9ZBR.js';
4
4
 
5
5
  /**
6
6
  * Acceptance receipts (spec section 8.2).
@@ -30,6 +30,7 @@ type PayoutSpec = {
30
30
  readonly destination_addresses: readonly string[];
31
31
  };
32
32
  type SpendingPolicySnapshot = {
33
+ readonly economics?: "legacy" | "zero_protocol_fees";
33
34
  readonly asset: "SOL";
34
35
  readonly entry_amount_lamports: number;
35
36
  readonly total_committed_lamports: number;
@@ -79,6 +80,7 @@ type NormalUserRefundStatus = "queued" | "reserved" | "submitted" | "confirming"
79
80
  type SourceLiquidityUse = "not_materialized" | "available" | "locked_for_payout" | "pending_finality" | "spent" | "released";
80
81
  type NormalUserContractSyncSnapshot = {
81
82
  readonly contract_id: string;
83
+ readonly deposit_origin_address?: string | null;
82
84
  readonly status: NormalUserContractStatus;
83
85
  readonly settlement_phase: NormalUserSettlementPhase;
84
86
  readonly refundability: NormalUserRefundability;
@@ -129,8 +131,17 @@ type RefundAcceptanceReceipt = AcceptanceReceipt & {
129
131
  readonly amountLamports: number;
130
132
  readonly acceptedAtMs?: number;
131
133
  };
134
+ /** Caller-owned delay/continuation for a proven, same-command initialization rejection. */
135
+ type InitializationRetry = {
136
+ readonly swapId: string;
137
+ readonly stage: "DkgRound2" | "DelegateShare";
138
+ readonly error: CommandError;
139
+ };
132
140
  type RunSwapParams = {
141
+ /** No automatic policy: absent this callback, initialization busy is returned to the caller. */
142
+ onInitializationRetry?: (retry: InitializationRetry) => Promise<void>;
133
143
  amountLamports: number;
144
+ batchExclusionId?: string;
134
145
  payoutSpec: PayoutSpec;
135
146
  payoutDeadlineMs?: number;
136
147
  onPolicySnapshot?: (policy: SpendingPolicySnapshot) => void;
@@ -167,6 +178,7 @@ type RunSwapParams = {
167
178
  originAddress: string | undefined;
168
179
  }) => void | Promise<void>;
169
180
  payoutWindowMs?: number;
181
+ signal?: AbortSignal;
170
182
  };
171
183
  /**
172
184
  * Details returned once the coordinator has accepted, initialized, and
@@ -197,6 +209,8 @@ type ContractRequestResult = {
197
209
  };
198
210
  /** Inputs for resuming an already allocated pre-delegation contract. */
199
211
  type ResumePreDelegationParams = {
212
+ readonly onInitializationRetry?: RunSwapParams["onInitializationRetry"];
213
+ readonly signal?: AbortSignal;
200
214
  readonly swapId: string;
201
215
  readonly resumeSecret: Uint8Array;
202
216
  readonly syncSecret?: Uint8Array;
@@ -273,19 +287,13 @@ declare function recoveryCodeToHex(code: Uint8Array): string;
273
287
  declare function recoveryCodeFromHex(hex: string): Uint8Array;
274
288
  declare function recoveryCodeFromUserInput(input: string): Uint8Array;
275
289
 
276
- /**
277
- * `@invisible-labs/sdk/user` - normal-user (private transfer) commands (spec 4.3).
278
- *
279
- * The normal-user API is functional and operates on the caller-owned attested
280
- * Session. Importing this module must not pull in `/lp`, `/stats`, or `/events`.
281
- */
282
-
283
290
  /** Inclusive minimum private-transfer entry amount in lamports. */
284
291
  declare const MIN_ENTRY_AMOUNT_LAMPORTS = 1500000000;
285
292
  /** Inclusive maximum private-transfer entry amount in lamports. */
286
293
  declare const MAX_ENTRY_AMOUNT_LAMPORTS = 100000000000;
287
294
  /** Arguments to start a new private-transfer pool entry. */
288
295
  interface ContractRequestArgs {
296
+ readonly onInitializationRetry?: RunSwapParams["onInitializationRetry"];
289
297
  /**
290
298
  * Gross private-transfer amount in lamports.
291
299
  *
@@ -300,8 +308,12 @@ interface ContractRequestArgs {
300
308
  /**
301
309
  * Where and how the output is delivered. V0 normal-user requests support
302
310
  * exactly one payout destination and validate the policy locally before
303
- * submission. `batchExclusionId` is rejected in V0; its planned V1 meaning
304
- * is campaign-scoped batch exclusion, never a stable actor identity.
311
+ * submission. Reuse the same `batchExclusionId` for each contract belonging
312
+ * to one user so liquidity from their own deposits, including deposits that
313
+ * later reimbursed an LP, cannot fund their own payout. The payout waits
314
+ * when no other liquidity is available.
315
+ * This opaque value is not proof of identity; integrators are responsible
316
+ * for assigning and retaining it.
305
317
  * `destinations[*].minDelayMs` and `destinations[*].maxDelayMs` are also
306
318
  * rejected in V0 because the current runtime does not honor them.
307
319
  * `totalDeadlineMs` selects the payout window: use `0` for instant payout,
@@ -338,6 +350,8 @@ interface ContractRequestArgs {
338
350
  swapId: string;
339
351
  delegateShare: Uint8Array;
340
352
  }) => void | Promise<void>;
353
+ /** Cancels only a pending pre-seal admission backoff; it cannot reverse an accepted contract. */
354
+ readonly signal?: AbortSignal;
341
355
  }
342
356
  /**
343
357
  * Start a new pool entry through the current normal-user coordinator flow.
package/dist/user.js CHANGED
@@ -1,13 +1,13 @@
1
- import { scheduledPayoutWindowSeconds } from './chunk-MPNVF727.js';
2
- import { validatePayoutPolicyShape, formatAjvErrors, persistTransferStatus, createSession, disabledClientPersistence, readPersistedTransferForResume, persistTransferReady, createExponentialBackoff, persistTransferTerminal, persistTransferRecoveryCode, persistTransferAllocation, persistTransferDkgMetadata } from './chunk-Y7AK6RBV.js';
3
- export { getPersistedTransfer, listPersistedTransfers, purgePersistedTransfers, removePersistedTransfer } from './chunk-Y7AK6RBV.js';
4
- import { PRODUCT_MAX_ENTRY_LAMPORTS, PRODUCT_MIN_ENTRY_LAMPORTS } from './chunk-IG6JJFR2.js';
5
- import { assertAttested, publicKey, solanaAddressFromPublicKeyBytes } from './chunk-EBWTAXNT.js';
6
- import { requestEnvelope, CoordinatorMessageType, onEnvelope, closeProtocolRuntime, EnvelopeKind } from './chunk-MZKJU3UA.js';
7
- import { getSessionState } from './chunk-HJFMDMPY.js';
8
- import './chunk-DCTYBUY3.js';
9
- import { PolicyValidationError, CommandError, StorageError, TransportError, normalizeError, InvalidDepositAmountError, AttestationError, RoutingError } from './chunk-QRN46R3F.js';
10
- export { InvalidDepositAmountError } from './chunk-QRN46R3F.js';
1
+ import { scheduledPayoutWindowSeconds, ErrorCode } from './chunk-DFBH5XLM.js';
2
+ import { validatePayoutPolicyShape, formatAjvErrors, persistTransferStatus, createSession, disabledClientPersistence, readPersistedTransferForResume, persistTransferReady, createExponentialBackoff, persistTransferTerminal, persistTransferRecoveryCode, persistTransferAllocation, persistTransferDkgMetadata } from './chunk-ANQMIQYS.js';
3
+ export { getPersistedTransfer, listPersistedTransfers, purgePersistedTransfers, removePersistedTransfer } from './chunk-ANQMIQYS.js';
4
+ import { PRODUCT_MAX_ENTRY_LAMPORTS, PRODUCT_MIN_ENTRY_LAMPORTS } from './chunk-HWRMSK7E.js';
5
+ import { assertAttested, publicKey, solanaAddressFromPublicKeyBytes } from './chunk-EPWTRF5U.js';
6
+ import { requestEnvelope, CoordinatorMessageType, onEnvelope, closeProtocolRuntime, EnvelopeKind } from './chunk-6AGC3IOB.js';
7
+ import { getSessionState } from './chunk-6AKBRYKO.js';
8
+ import './chunk-AIKC2XQS.js';
9
+ import { PolicyValidationError, CommandError, StorageError, TransportError, normalizeError, InvalidDepositAmountError, AttestationError, RoutingError } from './chunk-RWKG7N7I.js';
10
+ export { InvalidDepositAmountError } from './chunk-RWKG7N7I.js';
11
11
  import './chunk-VR6T6OJS.js';
12
12
 
13
13
  // src/validation/payoutPolicy.ts
@@ -27,7 +27,6 @@ Math.max(...SUPPORTED_TOTAL_DEADLINE_MS);
27
27
  var SHARE_SUM_TOLERANCE = 0.01;
28
28
  var CURRENT_USER_PAYOUT_DESTINATION_LIMIT = 1;
29
29
  var CURRENT_USER_PAYOUT_DESTINATION_LIMIT_MESSAGE = "current V0 normal-user SDK and coordinator support exactly one payout destination; multi-address receive is not supported yet";
30
- var CURRENT_USER_BATCH_EXCLUSION_ID_UNSUPPORTED_MESSAGE = "batchExclusionId is not supported in V0 normal-user payout requests; V1 defines it as campaign-scoped batch exclusion, never a stable actor identity";
31
30
  var CURRENT_USER_MIN_DELAY_UNSUPPORTED_MESSAGE = "destinations[*].minDelayMs is not supported in V0 normal-user payout requests";
32
31
  var CURRENT_USER_MAX_DELAY_UNSUPPORTED_MESSAGE = "destinations[*].maxDelayMs is not supported in V0 normal-user payout requests";
33
32
  var CURRENT_USER_PAYOUT_FRAGMENT_LIMIT = 1;
@@ -91,12 +90,6 @@ function validatePayoutPolicy(input, ctx = {}) {
91
90
  return policy;
92
91
  }
93
92
  function assertCurrentUserUnsupportedPayoutFeatures(policy) {
94
- if (policy.batchExclusionId !== void 0) {
95
- throw new PolicyValidationError(
96
- "INVALID_PAYOUT_PLAN",
97
- CURRENT_USER_BATCH_EXCLUSION_ID_UNSUPPORTED_MESSAGE
98
- );
99
- }
100
93
  for (const destination of policy.destinations) {
101
94
  if (destination.minDelayMs !== void 0) {
102
95
  throw new PolicyValidationError(
@@ -172,11 +165,11 @@ function recoveryCodeFromUserInput(input) {
172
165
  var protocolPromise = null;
173
166
  var frostRuntimePromise = null;
174
167
  function loadProtocol() {
175
- protocolPromise ??= import('./coordinator-E2TS6NR2.js');
168
+ protocolPromise ??= import('./coordinator-T2B7253V.js');
176
169
  return protocolPromise;
177
170
  }
178
171
  function loadFrostRuntime() {
179
- frostRuntimePromise ??= import('./frostRuntime-6FTPKUCP.js');
172
+ frostRuntimePromise ??= import('./frostRuntime-JESDHN6O.js');
180
173
  return frostRuntimePromise;
181
174
  }
182
175
  function loadFrost() {
@@ -195,6 +188,11 @@ var MAX_EVENT_DEDUP_ENTRIES_PER_KIND = 1024;
195
188
  var SWAP_STATUS_RETRY_JITTER_RATIO = 0.2;
196
189
  var DEFAULT_REFUND_OUTCOME_POLL_BUDGET_MS = 5 * 60 * 1e3;
197
190
  var REFUND_OUTCOME_POLL_INTERVAL_MS = 3e3;
191
+ var INITIALIZATION_PUSH_TIMEOUT_MS = 3e4;
192
+ var CONTRACT_ADMISSION_BUSY_MAX_ATTEMPTS = 6;
193
+ var CONTRACT_ADMISSION_BUSY_INITIAL_DELAY_MS = 250;
194
+ var CONTRACT_ADMISSION_BUSY_MAX_DELAY_MS = 4e3;
195
+ var CONTRACT_ADMISSION_BUSY_JITTER_RATIO = 0.2;
198
196
  var REFUND_OUTCOME_PER_POLL_TIMEOUT_MS = 5e3;
199
197
  var UNBOUND_RECONCILIATION_KEY = "__unbound__";
200
198
  var REQUEST_TIMEOUT_MESSAGE = "coordinator request timed out";
@@ -202,6 +200,9 @@ var REFUND_PENDING_FINALIZATION_MESSAGE = "refund accepted and pending finalizat
202
200
  var CURRENT_SCHEDULED_PAYOUT_WINDOW_SECONDS = new Set(scheduledPayoutWindowSeconds());
203
201
  var CURRENT_SCHEDULED_PAYOUT_WINDOW_MESSAGE = `scheduled payout_spec.window_seconds must be one of [${scheduledPayoutWindowSeconds().join(", ")}]`;
204
202
  var TERMINAL_SWAP_STATES = /* @__PURE__ */ new Set(["completed", "refunded", "failed"]);
203
+ function createRequestAbortError() {
204
+ return new DOMException("coordinator request aborted", "AbortError");
205
+ }
205
206
  function isBenignTransportDrop(err) {
206
207
  return typeof err === "object" && err !== null && err[BENIGN_TRANSPORT_DROP] === true;
207
208
  }
@@ -503,7 +504,8 @@ var UserCoordinatorSession = class {
503
504
  const dkg = await this.runDkg(
504
505
  context,
505
506
  params.onDelegateShareReady,
506
- persistedResumeRecord !== null
507
+ persistedResumeRecord !== null,
508
+ params
507
509
  );
508
510
  jointPublicKey = dkg.jointPublicKey;
509
511
  depositAddress = solanaAddressFromPublicKeyBytes(jointPublicKey);
@@ -515,14 +517,15 @@ var UserCoordinatorSession = class {
515
517
  const delegateAckPromise = this.awaitPush(CoordinatorMessageType.DelegateAck, context.swapId);
516
518
  let delegateResp;
517
519
  try {
518
- delegateResp = await this.request(
520
+ delegateResp = await this.requestInitialization(
519
521
  CoordinatorMessageType.DelegateShare,
520
522
  {
521
523
  share: delegateShare,
522
524
  recovery_commitment: new Uint8Array(params.recoveryCommitment),
523
525
  resume_secret: context.resumeSecret
524
526
  },
525
- { swapId: context.swapId }
527
+ context,
528
+ params
526
529
  );
527
530
  } catch (err) {
528
531
  void delegateAckPromise.catch(() => void 0);
@@ -972,11 +975,13 @@ var UserCoordinatorSession = class {
972
975
  if (generatedResumeSecret) {
973
976
  await params.onResumeSecretReady?.({ secretHex: resumeSecretHex });
974
977
  }
975
- const swapResp = await this.request(
976
- CoordinatorMessageType.ContractRequest,
978
+ const swapResp = await this.requestContract(
977
979
  {
978
980
  actor: "user",
979
981
  amount_lamports: params.amountLamports,
982
+ ...params.batchExclusionId !== void 0 && {
983
+ batch_exclusion_id: params.batchExclusionId
984
+ },
980
985
  payout_spec: params.payoutSpec,
981
986
  sync_commitment: syncCommitment,
982
987
  resume_commitment: resumeCommitment,
@@ -984,7 +989,7 @@ var UserCoordinatorSession = class {
984
989
  payout_deadline_ms: params.payoutDeadlineMs ?? payoutDeadlineMs
985
990
  }
986
991
  },
987
- { swapId: null, requireNonNullResponseSwapId: true }
992
+ params.signal
988
993
  );
989
994
  const swapPayload = protocol.asSwapRequestResponsePayload(swapResp);
990
995
  const swapId = swapPayload.swap_id;
@@ -1022,7 +1027,12 @@ var UserCoordinatorSession = class {
1022
1027
  null
1023
1028
  );
1024
1029
  void depositConfirmedPromise.catch(() => void 0);
1025
- const { jointPublicKey, keyHandle, depositExpiresAtMs, coordinatorTimestampMs } = await this.runDkg(context, params.delegateShare ? void 0 : params.onDelegateShareReady);
1030
+ const { jointPublicKey, keyHandle, depositExpiresAtMs, coordinatorTimestampMs } = await this.runDkg(
1031
+ context,
1032
+ params.delegateShare ? void 0 : params.onDelegateShareReady,
1033
+ true,
1034
+ params
1035
+ );
1026
1036
  this.updateContextState(context, "awaiting_deposit");
1027
1037
  let recoveryCommitment = params.recoveryCommitment;
1028
1038
  let recoveryCodeHex;
@@ -1045,14 +1055,15 @@ var UserCoordinatorSession = class {
1045
1055
  const share = params.delegateShare ?? keyHandle.secretShareBytes();
1046
1056
  let delegateResp;
1047
1057
  try {
1048
- delegateResp = await this.request(
1058
+ delegateResp = await this.requestInitialization(
1049
1059
  CoordinatorMessageType.DelegateShare,
1050
1060
  {
1051
1061
  share,
1052
1062
  recovery_commitment: recoveryCommitment,
1053
1063
  resume_secret: context.resumeSecret
1054
1064
  },
1055
- { swapId: context.swapId }
1065
+ context,
1066
+ params
1056
1067
  );
1057
1068
  } catch (err) {
1058
1069
  void delegateAckPromise.catch(() => void 0);
@@ -1119,7 +1130,7 @@ var UserCoordinatorSession = class {
1119
1130
  }
1120
1131
  }
1121
1132
  }
1122
- async runDkg(context, onDelegateShareReady, persistDkgMetadata = true) {
1133
+ async runDkg(context, onDelegateShareReady, persistDkgMetadata = true, retryOptions = {}) {
1123
1134
  await ensureFrostWasm();
1124
1135
  const protocol = this.requireProtocol();
1125
1136
  const { dkgRound1 } = await loadFrost();
@@ -1159,13 +1170,14 @@ var UserCoordinatorSession = class {
1159
1170
  });
1160
1171
  const dkgCompletePromise = this.awaitPush(CoordinatorMessageType.DkgComplete, context.swapId);
1161
1172
  void dkgCompletePromise.catch(() => void 0);
1162
- await this.request(
1173
+ await this.requestInitialization(
1163
1174
  CoordinatorMessageType.DkgRound2,
1164
1175
  {
1165
1176
  package: aliceRound2Bytes,
1166
1177
  resume_secret: context.resumeSecret
1167
1178
  },
1168
- { swapId: context.swapId }
1179
+ context,
1180
+ retryOptions
1169
1181
  );
1170
1182
  const completeEnvelope = await dkgCompletePromise;
1171
1183
  const complete = readDkgComplete(protocol, completeEnvelope);
@@ -1509,23 +1521,72 @@ var UserCoordinatorSession = class {
1509
1521
  return requestEnvelope(this.session, type, payload, {
1510
1522
  swapId: options.swapId === void 0 ? this.swapId : options.swapId,
1511
1523
  timeoutMs: options.timeoutMs,
1524
+ signal: options.signal,
1512
1525
  rejectMatchingOutOfBandErrors: options.rejectMatchingOutOfBandErrors,
1513
1526
  requireNonNullResponseSwapId: options.requireNonNullResponseSwapId,
1514
1527
  onLog: (message, direction) => this.log(message, direction)
1515
1528
  });
1516
1529
  }
1530
+ async requestInitialization(stage, payload, context, options) {
1531
+ let retrying = false;
1532
+ for (; ; ) {
1533
+ if (retrying && options.signal?.aborted) throw createRequestAbortError();
1534
+ try {
1535
+ return await this.request(stage, payload, { swapId: context.swapId });
1536
+ } catch (error) {
1537
+ if (!(error instanceof CommandError) || error.coordinatorCode !== ErrorCode.ERR_INITIALIZATION_BUSY || error.failedReqId === void 0 || !options.onInitializationRetry)
1538
+ throw error;
1539
+ const pushType = stage === CoordinatorMessageType.DkgRound2 ? CoordinatorMessageType.DkgComplete : CoordinatorMessageType.DelegateAck;
1540
+ const listener = this.pushListeners.get(pushType)?.find((candidate) => candidate.swapId === context.swapId);
1541
+ if (listener) this.setPushTimeout(pushType, listener, null);
1542
+ try {
1543
+ await options.onInitializationRetry({ swapId: context.swapId, stage, error });
1544
+ } finally {
1545
+ if (listener && this.pushListeners.get(pushType)?.includes(listener))
1546
+ this.setPushTimeout(pushType, listener, INITIALIZATION_PUSH_TIMEOUT_MS);
1547
+ }
1548
+ retrying = true;
1549
+ }
1550
+ }
1551
+ }
1552
+ async requestContract(payload, signal) {
1553
+ const busyBackoff = createExponentialBackoff({
1554
+ initialDelayMs: CONTRACT_ADMISSION_BUSY_INITIAL_DELAY_MS,
1555
+ maxDelayMs: CONTRACT_ADMISSION_BUSY_MAX_DELAY_MS,
1556
+ jitterRatio: CONTRACT_ADMISSION_BUSY_JITTER_RATIO
1557
+ });
1558
+ for (let attempt = 1; ; attempt += 1) {
1559
+ if (signal?.aborted) throw createRequestAbortError();
1560
+ try {
1561
+ return await this.request(CoordinatorMessageType.ContractRequest, payload, {
1562
+ swapId: null,
1563
+ requireNonNullResponseSwapId: true
1564
+ });
1565
+ } catch (error) {
1566
+ if (!(error instanceof CommandError) || error.coordinatorCode !== ErrorCode.ERR_PRESEAL_ADMISSION_BUSY || error.failedReqId === void 0 || attempt >= CONTRACT_ADMISSION_BUSY_MAX_ATTEMPTS)
1567
+ throw error;
1568
+ await abortableDelay(busyBackoff.nextDelayMs(), signal);
1569
+ }
1570
+ }
1571
+ }
1517
1572
  awaitPush(type, swapId, timeoutMs = 3e4) {
1518
1573
  return new Promise((resolve, reject) => {
1519
- const timer = timeoutMs === null ? null : setTimeout(() => {
1520
- this.removePushListener(type, listener);
1521
- reject(new CommandError("REJECTED_STALE_JOB", `timed out waiting for ${type} push`));
1522
- }, timeoutMs);
1523
- const listener = { swapId, resolve, reject, timer };
1574
+ const listener = { swapId, resolve, reject, timer: null };
1575
+ this.setPushTimeout(type, listener, timeoutMs);
1524
1576
  const listeners = this.pushListeners.get(type) ?? [];
1525
1577
  listeners.push(listener);
1526
1578
  this.pushListeners.set(type, listeners);
1527
1579
  });
1528
1580
  }
1581
+ setPushTimeout(type, listener, timeoutMs) {
1582
+ if (listener.timer) clearTimeout(listener.timer);
1583
+ listener.timer = timeoutMs === null ? null : setTimeout(() => {
1584
+ this.removePushListener(type, listener);
1585
+ listener.reject(
1586
+ new CommandError("REJECTED_STALE_JOB", `timed out waiting for ${type} push`)
1587
+ );
1588
+ }, timeoutMs);
1589
+ }
1529
1590
  rejectAllPushListeners(err) {
1530
1591
  for (const listeners of this.pushListeners.values()) {
1531
1592
  for (const listener of listeners) {
@@ -1787,6 +1848,21 @@ function bytesToHex(bytes) {
1787
1848
  function delay(ms) {
1788
1849
  return new Promise((resolve) => setTimeout(resolve, ms));
1789
1850
  }
1851
+ function abortableDelay(ms, signal) {
1852
+ if (signal === void 0) return delay(ms);
1853
+ if (signal.aborted) return Promise.reject(createRequestAbortError());
1854
+ return new Promise((resolve, reject) => {
1855
+ const onAbort = () => {
1856
+ clearTimeout(timer);
1857
+ reject(createRequestAbortError());
1858
+ };
1859
+ const timer = setTimeout(() => {
1860
+ signal.removeEventListener("abort", onAbort);
1861
+ resolve();
1862
+ }, ms);
1863
+ signal.addEventListener("abort", onAbort, { once: true });
1864
+ });
1865
+ }
1790
1866
  function payoutWindowMsFromSpec(payoutSpec) {
1791
1867
  if (payoutSpec.mode === "instant") return void 0;
1792
1868
  return payoutSpec.window_seconds * 1e3;
@@ -1829,7 +1905,7 @@ function bytesEqual(a, b) {
1829
1905
  return diff === 0;
1830
1906
  }
1831
1907
  function spendingPoliciesEqual(a, b) {
1832
- return a.asset === b.asset && a.entry_amount_lamports === b.entry_amount_lamports && a.total_committed_lamports === b.total_committed_lamports && a.payout_deadline_ms === b.payout_deadline_ms && a.payout_window_ms === b.payout_window_ms && a.fragment_count === b.fragment_count && a.payout_mode === b.payout_mode && a.matching_mode === b.matching_mode && a.fragmentation_allowed === b.fragmentation_allowed && a.min_fee_bps === b.min_fee_bps && a.fee_bps === b.fee_bps && a.fee_lamports === b.fee_lamports && a.net_payout_lamports === b.net_payout_lamports && payoutSchedulesEqual(a.payout_schedule, b.payout_schedule);
1908
+ return (a.economics ?? "legacy") === (b.economics ?? "legacy") && a.asset === b.asset && a.entry_amount_lamports === b.entry_amount_lamports && a.total_committed_lamports === b.total_committed_lamports && a.payout_deadline_ms === b.payout_deadline_ms && a.payout_window_ms === b.payout_window_ms && a.fragment_count === b.fragment_count && a.payout_mode === b.payout_mode && a.matching_mode === b.matching_mode && a.fragmentation_allowed === b.fragmentation_allowed && a.min_fee_bps === b.min_fee_bps && a.fee_bps === b.fee_bps && a.fee_lamports === b.fee_lamports && a.net_payout_lamports === b.net_payout_lamports && payoutSchedulesEqual(a.payout_schedule, b.payout_schedule);
1833
1909
  }
1834
1910
  function payoutSchedulesEqual(a, b) {
1835
1911
  if (a.length !== b.length) return false;
@@ -1890,6 +1966,9 @@ async function contractRequest(session, args) {
1890
1966
  return contractRequestOnSession(session, {
1891
1967
  amountLamports: args.amountLamports,
1892
1968
  payoutSpec: wirePayoutSpec,
1969
+ ...payoutPolicy.batchExclusionId !== void 0 && {
1970
+ batchExclusionId: payoutPolicy.batchExclusionId
1971
+ },
1893
1972
  ...args.syncSecret !== void 0 && { syncSecret: args.syncSecret },
1894
1973
  ...args.recoveryCommitment !== void 0 && {
1895
1974
  recoveryCommitment: args.recoveryCommitment
@@ -1909,6 +1988,10 @@ async function contractRequest(session, args) {
1909
1988
  },
1910
1989
  ...args.onDelegateShareReady !== void 0 && {
1911
1990
  onDelegateShareReady: args.onDelegateShareReady
1991
+ },
1992
+ ...args.signal !== void 0 && { signal: args.signal },
1993
+ ...args.onInitializationRetry !== void 0 && {
1994
+ onInitializationRetry: args.onInitializationRetry
1912
1995
  }
1913
1996
  });
1914
1997
  }
@@ -1920,6 +2003,10 @@ async function resumePreDelegation(session, args) {
1920
2003
  ...args.syncSecret !== void 0 && { syncSecret: new Uint8Array(args.syncSecret) },
1921
2004
  recoveryCommitment: new Uint8Array(args.recoveryCommitment),
1922
2005
  policySnapshot: args.policySnapshot,
2006
+ ...args.onInitializationRetry !== void 0 && {
2007
+ onInitializationRetry: args.onInitializationRetry
2008
+ },
2009
+ ...args.signal !== void 0 && { signal: args.signal },
1923
2010
  ...args.onDelegateShareReady !== void 0 && {
1924
2011
  onDelegateShareReady: args.onDelegateShareReady
1925
2012
  },