@invisible-labs/sdk 0.8.0-devnet → 0.9.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 (46) hide show
  1. package/README.md +7 -0
  2. package/dist/.invisible-sdk-build-target.json +1 -1
  3. package/dist/{chunk-HJFMDMPY.js → chunk-6AKBRYKO.js} +3 -3
  4. package/dist/{chunk-HJFMDMPY.js.map → chunk-6AKBRYKO.js.map} +1 -1
  5. package/dist/{chunk-DCTYBUY3.js → chunk-AIKC2XQS.js} +3 -3
  6. package/dist/{chunk-DCTYBUY3.js.map → chunk-AIKC2XQS.js.map} +1 -1
  7. package/dist/{chunk-Y7AK6RBV.js → chunk-EOPZVOVP.js} +11 -6
  8. package/dist/chunk-EOPZVOVP.js.map +1 -0
  9. package/dist/{chunk-EBWTAXNT.js → chunk-EPWTRF5U.js} +3 -3
  10. package/dist/{chunk-EBWTAXNT.js.map → chunk-EPWTRF5U.js.map} +1 -1
  11. package/dist/{chunk-IG6JJFR2.js → chunk-HWRMSK7E.js} +8 -6
  12. package/dist/chunk-HWRMSK7E.js.map +1 -0
  13. package/dist/{chunk-MZKJU3UA.js → chunk-ISIWWGSR.js} +16 -6
  14. package/dist/chunk-ISIWWGSR.js.map +1 -0
  15. package/dist/{chunk-K67FTCQU.js → chunk-JNNVPZEU.js} +3 -3
  16. package/dist/chunk-JNNVPZEU.js.map +1 -0
  17. package/dist/{chunk-MPNVF727.js → chunk-QF5TSUQE.js} +178 -41
  18. package/dist/chunk-QF5TSUQE.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-DHL3AP7V.js +4 -0
  22. package/dist/{coordinator-E2TS6NR2.js.map → coordinator-DHL3AP7V.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 +1 -1
  28. package/dist/index.js +8 -8
  29. package/dist/lp.d.ts +10 -1
  30. package/dist/lp.js +178 -65
  31. package/dist/lp.js.map +1 -1
  32. package/dist/stats.js +1 -1
  33. package/dist/storage.js +2 -2
  34. package/dist/{types.generated-YhFu9ZBR.d.ts → types.generated-DrM2M4DZ.d.ts} +6 -2
  35. package/dist/user.d.ts +18 -9
  36. package/dist/user.js +86 -30
  37. package/dist/user.js.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-IG6JJFR2.js.map +0 -1
  40. package/dist/chunk-K67FTCQU.js.map +0 -1
  41. package/dist/chunk-MPNVF727.js.map +0 -1
  42. package/dist/chunk-MZKJU3UA.js.map +0 -1
  43. package/dist/chunk-QRN46R3F.js.map +0 -1
  44. package/dist/chunk-Y7AK6RBV.js.map +0 -1
  45. package/dist/coordinator-E2TS6NR2.js +0 -4
  46. 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
  }
package/dist/user.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { C as CommandError, P as PayoutPolicy } from './types.generated-DrM2M4DZ.js';
2
+ export { I as InvalidDepositAmountError } from './types.generated-DrM2M4DZ.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,7 +131,15 @@ 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;
134
144
  payoutSpec: PayoutSpec;
135
145
  payoutDeadlineMs?: number;
@@ -167,6 +177,7 @@ type RunSwapParams = {
167
177
  originAddress: string | undefined;
168
178
  }) => void | Promise<void>;
169
179
  payoutWindowMs?: number;
180
+ signal?: AbortSignal;
170
181
  };
171
182
  /**
172
183
  * Details returned once the coordinator has accepted, initialized, and
@@ -197,6 +208,8 @@ type ContractRequestResult = {
197
208
  };
198
209
  /** Inputs for resuming an already allocated pre-delegation contract. */
199
210
  type ResumePreDelegationParams = {
211
+ readonly onInitializationRetry?: RunSwapParams["onInitializationRetry"];
212
+ readonly signal?: AbortSignal;
200
213
  readonly swapId: string;
201
214
  readonly resumeSecret: Uint8Array;
202
215
  readonly syncSecret?: Uint8Array;
@@ -273,19 +286,13 @@ declare function recoveryCodeToHex(code: Uint8Array): string;
273
286
  declare function recoveryCodeFromHex(hex: string): Uint8Array;
274
287
  declare function recoveryCodeFromUserInput(input: string): Uint8Array;
275
288
 
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
289
  /** Inclusive minimum private-transfer entry amount in lamports. */
284
290
  declare const MIN_ENTRY_AMOUNT_LAMPORTS = 1500000000;
285
291
  /** Inclusive maximum private-transfer entry amount in lamports. */
286
292
  declare const MAX_ENTRY_AMOUNT_LAMPORTS = 100000000000;
287
293
  /** Arguments to start a new private-transfer pool entry. */
288
294
  interface ContractRequestArgs {
295
+ readonly onInitializationRetry?: RunSwapParams["onInitializationRetry"];
289
296
  /**
290
297
  * Gross private-transfer amount in lamports.
291
298
  *
@@ -338,6 +345,8 @@ interface ContractRequestArgs {
338
345
  swapId: string;
339
346
  delegateShare: Uint8Array;
340
347
  }) => void | Promise<void>;
348
+ /** Cancels only a pending pre-seal admission backoff; it cannot reverse an accepted contract. */
349
+ readonly signal?: AbortSignal;
341
350
  }
342
351
  /**
343
352
  * 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-QF5TSUQE.js';
2
+ import { validatePayoutPolicyShape, formatAjvErrors, persistTransferStatus, createSession, disabledClientPersistence, readPersistedTransferForResume, persistTransferReady, createExponentialBackoff, persistTransferTerminal, persistTransferRecoveryCode, persistTransferAllocation, persistTransferDkgMetadata } from './chunk-EOPZVOVP.js';
3
+ export { getPersistedTransfer, listPersistedTransfers, purgePersistedTransfers, removePersistedTransfer } from './chunk-EOPZVOVP.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-ISIWWGSR.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
@@ -172,11 +172,11 @@ function recoveryCodeFromUserInput(input) {
172
172
  var protocolPromise = null;
173
173
  var frostRuntimePromise = null;
174
174
  function loadProtocol() {
175
- protocolPromise ??= import('./coordinator-E2TS6NR2.js');
175
+ protocolPromise ??= import('./coordinator-DHL3AP7V.js');
176
176
  return protocolPromise;
177
177
  }
178
178
  function loadFrostRuntime() {
179
- frostRuntimePromise ??= import('./frostRuntime-6FTPKUCP.js');
179
+ frostRuntimePromise ??= import('./frostRuntime-JESDHN6O.js');
180
180
  return frostRuntimePromise;
181
181
  }
182
182
  function loadFrost() {
@@ -195,6 +195,7 @@ var MAX_EVENT_DEDUP_ENTRIES_PER_KIND = 1024;
195
195
  var SWAP_STATUS_RETRY_JITTER_RATIO = 0.2;
196
196
  var DEFAULT_REFUND_OUTCOME_POLL_BUDGET_MS = 5 * 60 * 1e3;
197
197
  var REFUND_OUTCOME_POLL_INTERVAL_MS = 3e3;
198
+ var INITIALIZATION_PUSH_TIMEOUT_MS = 3e4;
198
199
  var REFUND_OUTCOME_PER_POLL_TIMEOUT_MS = 5e3;
199
200
  var UNBOUND_RECONCILIATION_KEY = "__unbound__";
200
201
  var REQUEST_TIMEOUT_MESSAGE = "coordinator request timed out";
@@ -202,6 +203,9 @@ var REFUND_PENDING_FINALIZATION_MESSAGE = "refund accepted and pending finalizat
202
203
  var CURRENT_SCHEDULED_PAYOUT_WINDOW_SECONDS = new Set(scheduledPayoutWindowSeconds());
203
204
  var CURRENT_SCHEDULED_PAYOUT_WINDOW_MESSAGE = `scheduled payout_spec.window_seconds must be one of [${scheduledPayoutWindowSeconds().join(", ")}]`;
204
205
  var TERMINAL_SWAP_STATES = /* @__PURE__ */ new Set(["completed", "refunded", "failed"]);
206
+ function createRequestAbortError() {
207
+ return new DOMException("coordinator request aborted", "AbortError");
208
+ }
205
209
  function isBenignTransportDrop(err) {
206
210
  return typeof err === "object" && err !== null && err[BENIGN_TRANSPORT_DROP] === true;
207
211
  }
@@ -503,7 +507,8 @@ var UserCoordinatorSession = class {
503
507
  const dkg = await this.runDkg(
504
508
  context,
505
509
  params.onDelegateShareReady,
506
- persistedResumeRecord !== null
510
+ persistedResumeRecord !== null,
511
+ params
507
512
  );
508
513
  jointPublicKey = dkg.jointPublicKey;
509
514
  depositAddress = solanaAddressFromPublicKeyBytes(jointPublicKey);
@@ -515,14 +520,15 @@ var UserCoordinatorSession = class {
515
520
  const delegateAckPromise = this.awaitPush(CoordinatorMessageType.DelegateAck, context.swapId);
516
521
  let delegateResp;
517
522
  try {
518
- delegateResp = await this.request(
523
+ delegateResp = await this.requestInitialization(
519
524
  CoordinatorMessageType.DelegateShare,
520
525
  {
521
526
  share: delegateShare,
522
527
  recovery_commitment: new Uint8Array(params.recoveryCommitment),
523
528
  resume_secret: context.resumeSecret
524
529
  },
525
- { swapId: context.swapId }
530
+ context,
531
+ params
526
532
  );
527
533
  } catch (err) {
528
534
  void delegateAckPromise.catch(() => void 0);
@@ -972,8 +978,7 @@ var UserCoordinatorSession = class {
972
978
  if (generatedResumeSecret) {
973
979
  await params.onResumeSecretReady?.({ secretHex: resumeSecretHex });
974
980
  }
975
- const swapResp = await this.request(
976
- CoordinatorMessageType.ContractRequest,
981
+ const swapResp = await this.requestContract(
977
982
  {
978
983
  actor: "user",
979
984
  amount_lamports: params.amountLamports,
@@ -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,59 @@ 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
+ if (signal?.aborted) throw createRequestAbortError();
1554
+ return this.request(CoordinatorMessageType.ContractRequest, payload, {
1555
+ swapId: null,
1556
+ requireNonNullResponseSwapId: true
1557
+ });
1558
+ }
1517
1559
  awaitPush(type, swapId, timeoutMs = 3e4) {
1518
1560
  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 };
1561
+ const listener = { swapId, resolve, reject, timer: null };
1562
+ this.setPushTimeout(type, listener, timeoutMs);
1524
1563
  const listeners = this.pushListeners.get(type) ?? [];
1525
1564
  listeners.push(listener);
1526
1565
  this.pushListeners.set(type, listeners);
1527
1566
  });
1528
1567
  }
1568
+ setPushTimeout(type, listener, timeoutMs) {
1569
+ if (listener.timer) clearTimeout(listener.timer);
1570
+ listener.timer = timeoutMs === null ? null : setTimeout(() => {
1571
+ this.removePushListener(type, listener);
1572
+ listener.reject(
1573
+ new CommandError("REJECTED_STALE_JOB", `timed out waiting for ${type} push`)
1574
+ );
1575
+ }, timeoutMs);
1576
+ }
1529
1577
  rejectAllPushListeners(err) {
1530
1578
  for (const listeners of this.pushListeners.values()) {
1531
1579
  for (const listener of listeners) {
@@ -1829,7 +1877,7 @@ function bytesEqual(a, b) {
1829
1877
  return diff === 0;
1830
1878
  }
1831
1879
  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);
1880
+ 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
1881
  }
1834
1882
  function payoutSchedulesEqual(a, b) {
1835
1883
  if (a.length !== b.length) return false;
@@ -1909,6 +1957,10 @@ async function contractRequest(session, args) {
1909
1957
  },
1910
1958
  ...args.onDelegateShareReady !== void 0 && {
1911
1959
  onDelegateShareReady: args.onDelegateShareReady
1960
+ },
1961
+ ...args.signal !== void 0 && { signal: args.signal },
1962
+ ...args.onInitializationRetry !== void 0 && {
1963
+ onInitializationRetry: args.onInitializationRetry
1912
1964
  }
1913
1965
  });
1914
1966
  }
@@ -1920,6 +1972,10 @@ async function resumePreDelegation(session, args) {
1920
1972
  ...args.syncSecret !== void 0 && { syncSecret: new Uint8Array(args.syncSecret) },
1921
1973
  recoveryCommitment: new Uint8Array(args.recoveryCommitment),
1922
1974
  policySnapshot: args.policySnapshot,
1975
+ ...args.onInitializationRetry !== void 0 && {
1976
+ onInitializationRetry: args.onInitializationRetry
1977
+ },
1978
+ ...args.signal !== void 0 && { signal: args.signal },
1923
1979
  ...args.onDelegateShareReady !== void 0 && {
1924
1980
  onDelegateShareReady: args.onDelegateShareReady
1925
1981
  },