@invisible-labs/sdk 0.6.0-devnet.3 → 0.6.0-devnet.5

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 (45) hide show
  1. package/README.md +129 -15
  2. package/dist/.invisible-sdk-build-target.json +7 -0
  3. package/dist/{chunk-QQSI3ZD7.js → chunk-3MDHAS4D.js} +109 -17
  4. package/dist/chunk-3MDHAS4D.js.map +1 -0
  5. package/dist/{chunk-NKRVQXRP.js → chunk-3TGQ4CZ3.js} +297 -11
  6. package/dist/chunk-3TGQ4CZ3.js.map +1 -0
  7. package/dist/chunk-DCTYBUY3.js +258 -0
  8. package/dist/chunk-DCTYBUY3.js.map +1 -0
  9. package/dist/{chunk-NHEHCUS5.js → chunk-EBWTAXNT.js} +3 -3
  10. package/dist/{chunk-NHEHCUS5.js.map → chunk-EBWTAXNT.js.map} +1 -1
  11. package/dist/{chunk-V5HXJRBW.js → chunk-HJFMDMPY.js} +3 -3
  12. package/dist/chunk-HJFMDMPY.js.map +1 -0
  13. package/dist/{chunk-GHBQF3A7.js → chunk-QRN46R3F.js} +5 -2
  14. package/dist/chunk-QRN46R3F.js.map +1 -0
  15. package/dist/chunk-Y7AK6RBV.js +4189 -0
  16. package/dist/chunk-Y7AK6RBV.js.map +1 -0
  17. package/dist/{coordinator-VVJ33WF2.js → coordinator-PEWHNZ7I.js} +3 -3
  18. package/dist/{coordinator-VVJ33WF2.js.map → coordinator-PEWHNZ7I.js.map} +1 -1
  19. package/dist/events.js +3 -3
  20. package/dist/index.d.ts +69 -353
  21. package/dist/index.js +161 -43
  22. package/dist/index.js.map +1 -1
  23. package/dist/lp.d.ts +76 -18
  24. package/dist/lp.js +511 -111
  25. package/dist/lp.js.map +1 -1
  26. package/dist/presets.d.ts +7 -40
  27. package/dist/presets.js +10 -68
  28. package/dist/presets.js.map +1 -1
  29. package/dist/stats.js +1 -1
  30. package/dist/storage.js +2 -243
  31. package/dist/storage.js.map +1 -1
  32. package/dist/{errors-N2touVm4.d.ts → types.generated-YhFu9ZBR.d.ts} +65 -4
  33. package/dist/user.d.ts +134 -8
  34. package/dist/user.js +991 -250
  35. package/dist/user.js.map +1 -1
  36. package/package.json +5 -31
  37. package/dist/chunk-BWCGNTN5.js +0 -1153
  38. package/dist/chunk-BWCGNTN5.js.map +0 -1
  39. package/dist/chunk-DIA6U2CV.js +0 -1927
  40. package/dist/chunk-DIA6U2CV.js.map +0 -1
  41. package/dist/chunk-GHBQF3A7.js.map +0 -1
  42. package/dist/chunk-NKRVQXRP.js.map +0 -1
  43. package/dist/chunk-QQSI3ZD7.js.map +0 -1
  44. package/dist/chunk-V5HXJRBW.js.map +0 -1
  45. package/dist/types.generated-BSEBz4jR.d.ts +0 -68
package/README.md CHANGED
@@ -19,6 +19,38 @@ coordinator. The normal-user surface uses one functional sequence over a caller-
19
19
  npm install @invisible-labs/sdk@devnet
20
20
  ```
21
21
 
22
+ The public package requires Node.js 22 or newer for server runtimes. Browser consumers need Web
23
+ Crypto and WebSocket. The default transport uses the platform `WebSocket`.
24
+
25
+ ## Session boundary
26
+
27
+ The public artifact exposes a production-only root facade:
28
+
29
+ ```ts
30
+ import { closeSession, createSession } from "@invisible-labs/sdk";
31
+ import { INVISIBLE_COORDINATOR_URL } from "@invisible-labs/sdk/presets";
32
+
33
+ const session = await createSession({ coordinatorUrl: INVISIBLE_COORDINATOR_URL });
34
+
35
+ // Use the session with @invisible-labs/sdk/user or /lp, then:
36
+ closeSession(session);
37
+ ```
38
+
39
+ The public constructor uses `coordinatorUrl` to open and attest the session. Its accepted `storage`
40
+ and `wallet` fields are compatibility-only and are not consumed by the published constructor, so
41
+ they do not enable persistence or signing. Persist recovery material explicitly through the user
42
+ callbacks and your own storage boundary.
43
+
44
+ The public build embeds the approved production attestation tuple. It accepts a
45
+ non-loopback `wss://` URL, but it does not accept `requiredMode`, a coordinator
46
+ pool, release-pin overrides, or local-attestation controls. The private
47
+ workspace build keeps the low-level pool constructor and exposes
48
+ `createDevSession` for explicit local and test flows; that facade is not in the
49
+ public artifact.
50
+
51
+ `sdk.attestation.productionPolicy()` exposes the embedded tuple as read-only
52
+ metadata. It is not a caller-controlled trust input.
53
+
22
54
  ## Entrypoints
23
55
 
24
56
  | Import | Covers |
@@ -46,18 +78,15 @@ import {
46
78
  requestRefund,
47
79
  sync,
48
80
  } from "@invisible-labs/sdk/user";
81
+ import { INVISIBLE_COORDINATOR_URL } from "@invisible-labs/sdk/presets";
49
82
 
50
- const coordinator = {
51
- endpoints: [
52
- /* CoordinatorEndpoint[] - supply your own, or use @invisible-labs/sdk/presets */
53
- ],
54
- };
83
+ const coordinatorUrl = INVISIBLE_COORDINATOR_URL;
55
84
  const payoutPolicy = {
56
85
  destinations: [{ address: receiverPublicKey, sharePercent: 100 }],
57
86
  totalDeadlineMs: 0,
58
87
  };
59
88
 
60
- const session = await createSession({ coordinator });
89
+ const session = await createSession({ coordinatorUrl });
61
90
  try {
62
91
  const contract = await contractRequest(session, {
63
92
  amountLamports: 3_000_000_000,
@@ -68,6 +97,8 @@ try {
68
97
 
69
98
  if (status.actor_sync?.snapshot.refundability === "available_now") {
70
99
  const receipt = await requestRefund(session, {
100
+ swapId: contract.swapId,
101
+ syncSecret: contract.syncSecret,
71
102
  recoveryCode: recoveryCodeFromHex(contract.recoveryCodeHex!),
72
103
  });
73
104
  console.log(receipt.requestId, receipt.amountLamports);
@@ -79,12 +110,18 @@ try {
79
110
 
80
111
  `contractRequest` resolves after durable delegation and before the deposit is observed. Its result
81
112
  contains `swapId`, `depositAddress`, `depositExpiresAtMs`, `syncSecret`, and the generated Recovery
82
- Code. Persist the sync secret and Recovery Code before asking the user to deposit. Send exactly
113
+ Code. With client persistence disabled, persist the sync secret and Recovery Code before asking the user to deposit. In opt-in mode, the SDK writes them at the flow boundaries. Send exactly
83
114
  `amountLamports` to the deposit address. The `sync` response contains actor-scoped lifecycle truth
84
115
  and the coordinator response timestamp; it does not expose an internal payout due timestamp. A
85
116
  refund receipt also carries the coordinator-authoritative accepted amount; use that value for
86
117
  pending refund accounting and use `sync` for final landing, cancellation, and fee-loss outcomes.
87
118
 
119
+ For crash recovery before delegation, the automatic mode does not persist `resumeSecret` or
120
+ delegate shares. With client persistence disabled, persist `policySnapshot` from the contract result
121
+ and call `resumePreDelegation` with it, the `resumeSecret`, and the Recovery Code commitment. When
122
+ resuming DKG, `onDelegateShareReady` is invoked before `DkgRound2` so the generated Alice share can
123
+ be persisted. Resume fails closed if the coordinator acknowledges a different spending policy.
124
+
88
125
  ## Private-transfer amount limits
89
126
 
90
127
  Use the public user-entry constants for inclusive preflight validation. Values are expressed in
@@ -119,8 +156,43 @@ Other target surfaces throw `NotImplementedError` until each is finalized. No co
119
156
 
120
157
  ## Recovery material and storage
121
158
 
122
- The SDK does not persist recovery material automatically. Consumers that need restart or tab-close
123
- recovery must store the relevant values themselves:
159
+ Client persistence is opt-in. `clientPersistence: false` or an omitted option performs no storage
160
+ reads or writes; supplying `storage` alone does not enable it. Enable SDK-owned normal-user records
161
+ with the public session option:
162
+
163
+ ```ts
164
+ const session = await createSession({
165
+ coordinatorUrl,
166
+ clientPersistence: true,
167
+ });
168
+ ```
169
+
170
+ With the option enabled, an explicit `StorageAdapter` takes precedence. Without one, the SDK uses
171
+ `chrome.storage.local` in a Chrome extension or `localStorage` in an ordinary web page. An extension
172
+ never falls back to page storage, and unsupported or denied storage fails before the coordinator
173
+ connection opens.
174
+
175
+ The `/user` entrypoint exposes `listPersistedTransfers`, `getPersistedTransfer`,
176
+ `removePersistedTransfer`, and `purgePersistedTransfers`. Listing and reading are local-only and
177
+ never trigger sync, refund, resume, signing, or another mutation. A fresh session must still run
178
+ Noise and attestation before the caller explicitly passes restored bytes to `sync` or
179
+ `requestRefund`.
180
+
181
+ Each SDK-owned record contains one `swapId`, bounded amount/destination/policy metadata, lifecycle
182
+ timestamps, optional coordinator `stateVersion`, `syncSecret`, and the Recovery Code when the SDK
183
+ generated or received it. It never stores `resumeSecret`, delegate shares, LP or wallet material,
184
+ transport or attestation state, UI state, raw transactions, or logs. Terminal records retain
185
+ bounded non-secret metadata and remove bearer secrets. The limits are 64 KiB per record, 100
186
+ records, and 1 MiB for the SDK namespace.
187
+
188
+ The storage is not a secure vault. Browser and extension storage may be readable or removable by
189
+ same-origin JavaScript, a compromised extension, XSS, local profile access, or browser/profile
190
+ clearing. Use a caller-controlled encrypted adapter when that tradeoff is unacceptable. If a write
191
+ fails after coordinator acceptance, the SDK throws a typed `StorageError` with the affected swap
192
+ and `remoteAccepted: true`; do not blindly retry the coordinator command.
193
+
194
+ When client persistence is disabled, consumers that need restart or tab-close recovery must store
195
+ the relevant values themselves:
124
196
 
125
197
  | Material | Needed for | Guidance |
126
198
  | ----------------------- | ----------------------------------------------- | ------------------------------------------------------- |
@@ -128,8 +200,11 @@ recovery must store the relevant values themselves:
128
200
  | User Recovery Code | Request an origin-bound private-transfer refund | Treat it like a seed phrase and persist it immediately. |
129
201
  | LP Position Code | Recover and operate an LP position | Keep it out of logs and treat it like a seed phrase. |
130
202
 
131
- The web app persists private-transfer recovery material locally so users can resume flows. SDK
132
- consumers can choose `browserStorage`, `extensionStorage`, or their own encrypted storage layer.
203
+ The web app persists private-transfer recovery material locally as a product tradeoff so users can
204
+ resume flows. SDK consumers can opt in, choose `browserStorage` or `extensionStorage`, or provide
205
+ their own encrypted storage layer for caller-managed material. Browser and extension adapters store
206
+ caller-supplied bytes; they do not encrypt them. Encrypt before storing or use an access-controlled
207
+ vault for production recovery material.
133
208
 
134
209
  LP DKG requests are bounded. If a browser worker stops responding, the SDK terminates the local
135
210
  workers and attempts the signed position-scoped DKG abort command within a bounded cleanup window
@@ -169,10 +244,49 @@ FROST WASM are inlined into the published bundle, while published third-party pa
169
244
  external dependencies.
170
245
 
171
246
  ```bash
172
- npm run build
247
+ npm run build:private
173
248
  npm run verify:exports
249
+ npm run verify:private-artifact
250
+ ```
251
+
252
+ The public artifact is built separately with approved release inputs:
253
+
254
+ ```bash
255
+ SDK_PRODUCTION_BINARY_HASH=<64-hex-binary-sha256> \
256
+ AZURE_PROD_EXPECTED_BINARY_HASH=<same-64-hex-binary-sha256> \
257
+ SDK_PRODUCTION_COORDINATOR_MRTD=<96-hex-mrtd> \
258
+ SDK_PRODUCTION_RUNTIME_PROFILE=prod-devnet-simplified \
259
+ npm run build:public
260
+ npm run verify:exports
261
+ npm run verify:public-build-marker
262
+ npm run verify:public-artifact
263
+ ```
264
+
265
+ The public production smoke consumes that already verified artifact. It requires
266
+ `--prebuilt-sdk` plus an operator-approved release manifest whose exact file
267
+ SHA-256 is supplied separately:
268
+
269
+ ```bash
270
+ SDK_APPROVED_RELEASE_MANIFEST_PATH=<approved-release-manifest> \
271
+ SDK_APPROVED_RELEASE_MANIFEST_SHA256=<sha256-of-manifest-bytes> \
272
+ npm --workspace @invisible-labs/sdk run smoke:prod-attestation -- \
273
+ --host tee-azure.invisible.exchange --mrtd <96-hex-mrtd> \
274
+ --binary-hash <64-hex-binary-sha256> --target public \
275
+ --runtime-profile prod-devnet-simplified --prebuilt-sdk
174
276
  ```
175
277
 
176
- The prod-attestation smoke normally rebuilds the SDK. Its `--prebuilt-sdk`
177
- option is reserved for an integrity-bound runtime that already contains the
178
- exact built `dist`; ordinary operator runs must omit it.
278
+ Do not pack the workspace directly. Use the private or public staged publish
279
+ commands so the selected build target and artifact marker are checked.
280
+
281
+ Private smoke runs may rebuild the private SDK. Public smoke must use
282
+ `--prebuilt-sdk` so it cannot rebuild after the public artifact gates.
283
+
284
+ For an explicitly authorized Devnet deposit-address probe, append
285
+ `--no-fund-contract-probe --payout-address <public-key>` to the private smoke with
286
+ `--runtime-profile prod-devnet-simplified-locked`. It requests the SDK minimum
287
+ entry amount, completes DKG/delegation, and requires authenticated Sync to report
288
+ `awaiting_deposit`. It creates an unfunded coordinator contract; it sends no SOL.
289
+ The `TEE_NO_FUND_CONTRACT_SMOKE` receipt contains only the deposit address, expiry,
290
+ and status. Recovery material stays in process memory and is discarded on exit.
291
+ Never fund this disposable probe address. This proves address preparation only,
292
+ not deposit observation, settlement, persistence after restart, or Owner isolation.
@@ -0,0 +1,7 @@
1
+ {
2
+ "package": "@invisible-labs/sdk",
3
+ "target": "public",
4
+ "productionBinaryHash": "e08f16d1c303f402e8210302e85ff8ce497e4152d7511143849c7771d56a1663",
5
+ "productionMrtd": "a2e61f1316e9e367e9c1f7a0adc98c48eb13875c399c85d286cee5ea2b05e57f2df9f61d903b0ae7ac5607d843dfffc1",
6
+ "productionRuntimeProfile": "prod-devnet-simplified-locked"
7
+ }
@@ -1,7 +1,8 @@
1
- import { getSessionState } from './chunk-V5HXJRBW.js';
2
- import { TransportError, CommandError } from './chunk-GHBQF3A7.js';
1
+ import { getSessionState } from './chunk-HJFMDMPY.js';
2
+ import { TransportError, CommandError } from './chunk-QRN46R3F.js';
3
3
 
4
4
  // src/coordinator/protocolClient.ts
5
+ var MAX_COORDINATOR_REQUEST_ID = 4294967295;
5
6
  var OUT_OF_BAND_REQUEST_ID = 0;
6
7
  var EnvelopeKind = {
7
8
  REQUEST: "request",
@@ -11,6 +12,7 @@ var EnvelopeKind = {
11
12
  };
12
13
  var CoordinatorMessageType = {
13
14
  ContractRequest: "ContractRequest",
15
+ LpCreateAuthorization: "LpCreateAuthorization",
14
16
  DkgInit: "DkgInit",
15
17
  DkgRound1: "DkgRound1",
16
18
  DkgRound2: "DkgRound2",
@@ -30,19 +32,25 @@ var CoordinatorMessageType = {
30
32
  };
31
33
  var protocolPromise = null;
32
34
  function loadProtocol() {
33
- protocolPromise ??= import('./coordinator-VVJ33WF2.js');
35
+ protocolPromise ??= import('./coordinator-PEWHNZ7I.js');
34
36
  return protocolPromise;
35
37
  }
36
38
  var runtimes = /* @__PURE__ */ new WeakMap();
37
39
  async function requestEnvelope(session, type, payload, options = {}) {
40
+ throwIfRequestAborted(options.signal);
38
41
  const protocol = await loadProtocol();
42
+ throwIfRequestAborted(options.signal);
39
43
  const state = getSessionState(session);
40
44
  const runtime = ensureProtocolRuntime(state);
41
45
  const channel = state.channel;
42
46
  if (!state.attested || channel === null) {
43
47
  throw new TransportError("CONNECTION_LOST", "coordinator request requires an attested channel");
44
48
  }
45
- const reqId = ++runtime.reqCounter;
49
+ if (runtime.reqCounter >= MAX_COORDINATOR_REQUEST_ID) {
50
+ throw new CommandError("REJECTED_STATE", "coordinator request id space exhausted");
51
+ }
52
+ const reqId = runtime.reqCounter + 1;
53
+ runtime.reqCounter = reqId;
46
54
  const envelope = {
47
55
  version: protocol.ENVELOPE_VERSION,
48
56
  kind: protocol.EnvelopeKind.REQUEST,
@@ -54,9 +62,11 @@ async function requestEnvelope(session, type, payload, options = {}) {
54
62
  };
55
63
  const frame = protocol.encodeValidated(envelope);
56
64
  return new Promise((resolve, reject) => {
65
+ const abortHandler = options.signal === void 0 ? void 0 : () => rejectPending(runtime, reqId, createRequestAbortError());
57
66
  const timer = options.timeoutMs === void 0 ? null : setTimeout(() => {
58
- runtime.pending.delete(reqId);
59
- reject(
67
+ rejectPending(
68
+ runtime,
69
+ reqId,
60
70
  new CommandError(
61
71
  "REJECTED_STALE_JOB",
62
72
  `coordinator request timed out for ${type} after ${options.timeoutMs}ms`
@@ -64,19 +74,28 @@ async function requestEnvelope(session, type, payload, options = {}) {
64
74
  );
65
75
  }, options.timeoutMs);
66
76
  runtime.pending.set(reqId, {
77
+ expectedSwapId: options.swapId ?? null,
67
78
  resolve,
68
79
  reject,
69
80
  timer,
81
+ signal: options.signal,
82
+ abortHandler,
70
83
  swapId: envelope.swap_id,
71
- rejectMatchingOutOfBandErrors: options.rejectMatchingOutOfBandErrors === true
84
+ rejectMatchingOutOfBandErrors: options.rejectMatchingOutOfBandErrors === true,
85
+ requireNonNullResponseSwapId: options.requireNonNullResponseSwapId === true
72
86
  });
87
+ if (abortHandler !== void 0) {
88
+ options.signal?.addEventListener("abort", abortHandler, { once: true });
89
+ if (options.signal?.aborted === true) {
90
+ abortHandler();
91
+ return;
92
+ }
93
+ }
73
94
  options.onLog?.(`-> ${type} req_id=${reqId}`, "out");
74
95
  try {
75
96
  channel.send(frame);
76
97
  } catch (error) {
77
- runtime.pending.delete(reqId);
78
- if (timer) clearTimeout(timer);
79
- reject(error instanceof Error ? error : new Error(String(error)));
98
+ rejectPending(runtime, reqId, error instanceof Error ? error : new Error(String(error)));
80
99
  }
81
100
  });
82
101
  }
@@ -129,9 +148,36 @@ async function handleFrameAsync(runtime, frame) {
129
148
  return;
130
149
  }
131
150
  const envelope = decoded.value;
151
+ if (envelope.kind === protocol.EnvelopeKind.RESPONSE) {
152
+ const pending2 = runtime.pending.get(envelope.req_id);
153
+ if (pending2 && !pendingRequestMatchesSwapId(pending2, envelope.swap_id)) {
154
+ rejectPending(
155
+ runtime,
156
+ envelope.req_id,
157
+ requestSwapIdMismatchError(envelope.req_id, pending2.expectedSwapId, envelope.swap_id)
158
+ );
159
+ return;
160
+ }
161
+ }
162
+ const errorPayload = envelope.kind === protocol.EnvelopeKind.ERROR ? protocol.asErrorPayload(envelope) : null;
163
+ if (errorPayload?.failed_req_id !== void 0) {
164
+ const pending2 = runtime.pending.get(errorPayload.failed_req_id);
165
+ if (pending2 && !pendingRequestMatchesSwapId(pending2, envelope.swap_id, false)) {
166
+ rejectPending(
167
+ runtime,
168
+ errorPayload.failed_req_id,
169
+ requestSwapIdMismatchError(
170
+ errorPayload.failed_req_id,
171
+ pending2.expectedSwapId,
172
+ envelope.swap_id
173
+ )
174
+ );
175
+ return;
176
+ }
177
+ }
132
178
  for (const handler of runtime.envelopeHandlers) handler(envelope);
133
179
  if (envelope.kind === protocol.EnvelopeKind.ERROR) {
134
- const payload = protocol.asErrorPayload(envelope);
180
+ const payload = errorPayload;
135
181
  const error = commandErrorFromCoordinatorError(payload);
136
182
  if (payload.failed_req_id === void 0 || payload.failed_req_id === OUT_OF_BAND_REQUEST_ID) {
137
183
  if (envelope.swap_id !== null) {
@@ -139,6 +185,16 @@ async function handleFrameAsync(runtime, frame) {
139
185
  }
140
186
  return;
141
187
  }
188
+ const pending2 = runtime.pending.get(payload.failed_req_id);
189
+ if (!pending2) return;
190
+ if (!pendingRequestMatchesSwapId(pending2, envelope.swap_id, false)) {
191
+ rejectPending(
192
+ runtime,
193
+ payload.failed_req_id,
194
+ requestSwapIdMismatchError(payload.failed_req_id, pending2.expectedSwapId, envelope.swap_id)
195
+ );
196
+ return;
197
+ }
142
198
  rejectPending(runtime, payload.failed_req_id, error);
143
199
  return;
144
200
  }
@@ -149,13 +205,37 @@ async function handleFrameAsync(runtime, frame) {
149
205
  if (envelope.kind !== protocol.EnvelopeKind.RESPONSE) return;
150
206
  const pending = runtime.pending.get(envelope.req_id);
151
207
  if (!pending) return;
208
+ if (!pendingRequestMatchesSwapId(pending, envelope.swap_id)) {
209
+ rejectPending(
210
+ runtime,
211
+ envelope.req_id,
212
+ requestSwapIdMismatchError(envelope.req_id, pending.expectedSwapId, envelope.swap_id)
213
+ );
214
+ return;
215
+ }
152
216
  runtime.pending.delete(envelope.req_id);
153
- if (pending.timer) clearTimeout(pending.timer);
217
+ cleanupPendingRequest(pending);
154
218
  pending.resolve(envelope);
155
219
  }
220
+ function pendingRequestMatchesSwapId(pending, responseSwapId, enforceNonNullResponseSwapId = true) {
221
+ if (enforceNonNullResponseSwapId && pending.requireNonNullResponseSwapId && responseSwapId === null) {
222
+ return false;
223
+ }
224
+ return pending.expectedSwapId === null || pending.expectedSwapId === responseSwapId;
225
+ }
226
+ function requestSwapIdMismatchError(reqId, expectedSwapId, receivedSwapId) {
227
+ return new CommandError(
228
+ "REJECTED_STATE",
229
+ `coordinator response swap_id mismatch for req_id=${reqId}: expected ${expectedSwapId ?? "null"}, received ${receivedSwapId ?? "null"}`,
230
+ { failedReqId: reqId }
231
+ );
232
+ }
156
233
  function resolvePushWaiter(runtime, envelope) {
157
234
  const waiters = runtime.pushWaiters.get(envelope.type);
158
- const waiter = waiters?.shift();
235
+ const waiterIndex = waiters?.findIndex(
236
+ (candidate) => candidate.swapId === void 0 || candidate.swapId === envelope.swap_id
237
+ );
238
+ const waiter = waiters && waiterIndex !== void 0 && waiterIndex >= 0 ? waiters.splice(waiterIndex, 1)[0] : void 0;
159
239
  if (!waiter || !waiters) return;
160
240
  if (waiters.length === 0) {
161
241
  runtime.pushWaiters.delete(envelope.type);
@@ -167,9 +247,21 @@ function rejectPending(runtime, reqId, error) {
167
247
  const pending = runtime.pending.get(reqId);
168
248
  if (!pending) return;
169
249
  runtime.pending.delete(reqId);
170
- if (pending.timer) clearTimeout(pending.timer);
250
+ cleanupPendingRequest(pending);
171
251
  pending.reject(error);
172
252
  }
253
+ function cleanupPendingRequest(pending) {
254
+ if (pending.timer) clearTimeout(pending.timer);
255
+ if (pending.signal !== void 0 && pending.abortHandler !== void 0) {
256
+ pending.signal.removeEventListener("abort", pending.abortHandler);
257
+ }
258
+ }
259
+ function throwIfRequestAborted(signal) {
260
+ if (signal?.aborted === true) throw createRequestAbortError();
261
+ }
262
+ function createRequestAbortError() {
263
+ return new DOMException("coordinator request aborted", "AbortError");
264
+ }
173
265
  function rejectMatchingOutOfBandErrors(runtime, swapId, error) {
174
266
  for (const [reqId, pending] of runtime.pending) {
175
267
  if (!pending.rejectMatchingOutOfBandErrors || pending.swapId !== swapId) continue;
@@ -220,7 +312,7 @@ function toCoordinatorWireErrorCode(code) {
220
312
  function rejectAll(runtime, error) {
221
313
  for (const [reqId, pending] of runtime.pending.entries()) {
222
314
  runtime.pending.delete(reqId);
223
- if (pending.timer) clearTimeout(pending.timer);
315
+ cleanupPendingRequest(pending);
224
316
  pending.reject(error);
225
317
  }
226
318
  for (const [type, waiters] of runtime.pushWaiters.entries()) {
@@ -233,5 +325,5 @@ function rejectAll(runtime, error) {
233
325
  }
234
326
 
235
327
  export { CoordinatorMessageType, EnvelopeKind, closeProtocolRuntime, onEnvelope, requestEnvelope };
236
- //# sourceMappingURL=chunk-QQSI3ZD7.js.map
237
- //# sourceMappingURL=chunk-QQSI3ZD7.js.map
328
+ //# sourceMappingURL=chunk-3MDHAS4D.js.map
329
+ //# sourceMappingURL=chunk-3MDHAS4D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/coordinator/protocolClient.ts"],"names":["pending"],"mappings":"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","file":"chunk-3MDHAS4D.js","sourcesContent":["import {\n CommandError,\n TransportError,\n type CommandErrorCode,\n type CoordinatorWireErrorCode,\n} from \"../core/errors.js\";\nimport type { Session } from \"../core/session.js\";\nimport { getSessionState, type SessionState } from \"../session/state.js\";\nimport type { Unsubscribe } from \"../transport/types.js\";\n\nconst COORDINATOR_ENVELOPE_VERSION = 2;\nconst MAX_COORDINATOR_REQUEST_ID = 0xffff_ffff;\nconst OUT_OF_BAND_REQUEST_ID = 0;\n\nexport const EnvelopeKind = {\n REQUEST: \"request\",\n RESPONSE: \"response\",\n PUSH: \"push\",\n ERROR: \"error\",\n} as const;\n\nexport type EnvelopeKind = (typeof EnvelopeKind)[keyof typeof EnvelopeKind];\n\nexport const CoordinatorMessageType = {\n ContractRequest: \"ContractRequest\",\n LpCreateAuthorization: \"LpCreateAuthorization\",\n DkgInit: \"DkgInit\",\n DkgRound1: \"DkgRound1\",\n DkgRound2: \"DkgRound2\",\n DkgComplete: \"DkgComplete\",\n DelegateShare: \"DelegateShare\",\n DelegateAck: \"DelegateAck\",\n DepositConfirmed: \"DepositConfirmed\",\n Sync: \"Sync\",\n SyncRequired: \"SyncRequired\",\n Refill: \"Refill\",\n PayoutExecuted: \"PayoutExecuted\",\n WithdrawRequest: \"WithdrawRequest\",\n WithdrawAccepted: \"WithdrawAccepted\",\n WithdrawExecuted: \"WithdrawExecuted\",\n LpCommand: \"LpCommand\",\n Error: \"Error\",\n} as const;\n\nexport type CoordinatorMessageType =\n (typeof CoordinatorMessageType)[keyof typeof CoordinatorMessageType];\n\nexport type Envelope = {\n readonly version: typeof COORDINATOR_ENVELOPE_VERSION;\n readonly kind: EnvelopeKind;\n readonly type: CoordinatorMessageType;\n readonly swap_id: string | null;\n readonly req_id: number;\n readonly timestamp_ms: number;\n readonly payload: unknown;\n};\n\ntype ProtocolModule = {\n readonly ENVELOPE_VERSION: typeof COORDINATOR_ENVELOPE_VERSION;\n readonly EnvelopeKind: typeof EnvelopeKind;\n readonly CoordinatorMessageType: typeof CoordinatorMessageType;\n readonly encodeValidated: (envelope: Envelope) => Uint8Array;\n readonly decode: (raw: Uint8Array) => { ok: true; value: Envelope } | { ok: false; error: Error };\n readonly asErrorPayload: (envelope: Envelope) => {\n readonly code: string;\n readonly failed_req_id?: number;\n readonly message: string;\n };\n};\n\nlet protocolPromise: Promise<ProtocolModule> | null = null;\n\nfunction loadProtocol(): Promise<ProtocolModule> {\n protocolPromise ??= import(\"protocol/coordinator\") as Promise<ProtocolModule>;\n return protocolPromise;\n}\n\nexport type ProtocolLogDirection = \"in\" | \"out\" | \"info\";\nexport type ProtocolLogHandler = (message: string, direction: ProtocolLogDirection) => void;\nexport type ProtocolEnvelopeHandler = (envelope: Envelope) => void;\n\nexport interface RequestEnvelopeOptions {\n readonly swapId?: string | null;\n readonly timeoutMs?: number;\n readonly signal?: AbortSignal;\n readonly onLog?: ProtocolLogHandler;\n /** Reject this request when the coordinator reports a swap-scoped error without a request id. */\n readonly rejectMatchingOutOfBandErrors?: boolean;\n /** Contract allocation responses must carry the server-assigned swap_id. */\n readonly requireNonNullResponseSwapId?: boolean;\n}\n\nexport interface AwaitPushOptions {\n /** Exact business routing key. Omit only for legacy wildcard waiters. */\n readonly swapId?: string | null;\n readonly timeoutMs?: number | null;\n}\n\ntype PendingRequest = {\n readonly expectedSwapId: string | null;\n readonly resolve: (envelope: Envelope) => void;\n readonly reject: (error: Error) => void;\n readonly timer: ReturnType<typeof setTimeout> | null;\n readonly signal?: AbortSignal;\n readonly abortHandler?: () => void;\n readonly swapId: string | null;\n readonly rejectMatchingOutOfBandErrors: boolean;\n readonly requireNonNullResponseSwapId: boolean;\n};\n\ntype PushWaiter = {\n readonly swapId?: string | null;\n readonly resolve: (envelope: Envelope) => void;\n readonly reject: (error: Error) => void;\n readonly timer: ReturnType<typeof setTimeout> | null;\n};\n\ntype ProtocolRuntime = {\n reqCounter: number;\n readonly pending: Map<number, PendingRequest>;\n readonly pushWaiters: Map<CoordinatorMessageType, PushWaiter[]>;\n readonly envelopeHandlers: Set<ProtocolEnvelopeHandler>;\n unsubscribeChannel: Unsubscribe | null;\n unsubscribeTransport: Unsubscribe | null;\n};\n\nconst runtimes = new WeakMap<SessionState, ProtocolRuntime>();\n\nexport async function requestEnvelope(\n session: Session,\n type: CoordinatorMessageType,\n payload: unknown,\n options: RequestEnvelopeOptions = {},\n): Promise<Envelope> {\n throwIfRequestAborted(options.signal);\n const protocol = await loadProtocol();\n throwIfRequestAborted(options.signal);\n const state = getSessionState(session);\n const runtime = ensureProtocolRuntime(state);\n const channel = state.channel;\n if (!state.attested || channel === null) {\n throw new TransportError(\"CONNECTION_LOST\", \"coordinator request requires an attested channel\");\n }\n\n if (runtime.reqCounter >= MAX_COORDINATOR_REQUEST_ID) {\n throw new CommandError(\"REJECTED_STATE\", \"coordinator request id space exhausted\");\n }\n const reqId = runtime.reqCounter + 1;\n runtime.reqCounter = reqId;\n const envelope: Envelope = {\n version: protocol.ENVELOPE_VERSION,\n kind: protocol.EnvelopeKind.REQUEST,\n type,\n swap_id: options.swapId ?? null,\n req_id: reqId,\n timestamp_ms: Date.now(),\n payload,\n };\n const frame = protocol.encodeValidated(envelope);\n\n return new Promise((resolve, reject) => {\n const abortHandler =\n options.signal === undefined\n ? undefined\n : () => rejectPending(runtime, reqId, createRequestAbortError());\n const timer =\n options.timeoutMs === undefined\n ? null\n : setTimeout(() => {\n rejectPending(\n runtime,\n reqId,\n new CommandError(\n \"REJECTED_STALE_JOB\",\n `coordinator request timed out for ${type} after ${options.timeoutMs}ms`,\n ),\n );\n }, options.timeoutMs);\n\n runtime.pending.set(reqId, {\n expectedSwapId: options.swapId ?? null,\n resolve,\n reject,\n timer,\n signal: options.signal,\n abortHandler,\n swapId: envelope.swap_id,\n rejectMatchingOutOfBandErrors: options.rejectMatchingOutOfBandErrors === true,\n requireNonNullResponseSwapId: options.requireNonNullResponseSwapId === true,\n });\n if (abortHandler !== undefined) {\n options.signal?.addEventListener(\"abort\", abortHandler, { once: true });\n if (options.signal?.aborted === true) {\n abortHandler();\n return;\n }\n }\n options.onLog?.(`-> ${type} req_id=${reqId}`, \"out\");\n try {\n channel.send(frame);\n } catch (error) {\n rejectPending(runtime, reqId, error instanceof Error ? error : new Error(String(error)));\n }\n });\n}\n\nexport function awaitPush(\n session: Session,\n type: CoordinatorMessageType,\n options: AwaitPushOptions = {},\n): Promise<Envelope> {\n const state = getSessionState(session);\n const runtime = ensureProtocolRuntime(state);\n const timeoutMs = options.timeoutMs === undefined ? 30_000 : options.timeoutMs;\n\n return new Promise((resolve, reject) => {\n const timer =\n timeoutMs === null\n ? null\n : setTimeout(() => {\n removePushWaiter(runtime, type, waiter);\n reject(new CommandError(\"REJECTED_STALE_JOB\", `timed out waiting for ${type} push`));\n }, timeoutMs);\n const waiter: PushWaiter = { swapId: options.swapId, resolve, reject, timer };\n const waiters = runtime.pushWaiters.get(type) ?? [];\n waiters.push(waiter);\n runtime.pushWaiters.set(type, waiters);\n });\n}\n\nexport function onEnvelope(session: Session, handler: ProtocolEnvelopeHandler): Unsubscribe {\n const runtime = ensureProtocolRuntime(getSessionState(session));\n runtime.envelopeHandlers.add(handler);\n return () => runtime.envelopeHandlers.delete(handler);\n}\n\nexport function closeProtocolRuntime(session: Session): void {\n const state = getSessionState(session);\n const runtime = runtimes.get(state);\n if (!runtime) return;\n const error = new TransportError(\"CONNECTION_LOST\", \"coordinator protocol runtime closed\");\n rejectAll(runtime, error);\n runtime.unsubscribeChannel?.();\n runtime.unsubscribeTransport?.();\n runtimes.delete(state);\n}\n\nfunction ensureProtocolRuntime(state: SessionState): ProtocolRuntime {\n const existing = runtimes.get(state);\n if (existing) return existing;\n\n const runtime: ProtocolRuntime = {\n reqCounter: 0,\n pending: new Map(),\n pushWaiters: new Map(),\n envelopeHandlers: new Set(),\n unsubscribeChannel: null,\n unsubscribeTransport: null,\n };\n\n if (state.channel === null) {\n throw new TransportError(\"CONNECTION_LOST\", \"coordinator protocol requires a live channel\");\n }\n runtime.unsubscribeChannel = state.channel.onMessage((frame) => handleFrame(runtime, frame));\n runtime.unsubscribeTransport = state.transport.onStateChange((transportState) => {\n if (transportState === \"closing\" || transportState === \"closed\") {\n rejectAll(runtime, new TransportError(\"CONNECTION_LOST\", \"coordinator transport closed\"));\n }\n });\n\n runtimes.set(state, runtime);\n return runtime;\n}\n\nfunction handleFrame(runtime: ProtocolRuntime, frame: Uint8Array): void {\n void handleFrameAsync(runtime, frame);\n}\n\nasync function handleFrameAsync(runtime: ProtocolRuntime, frame: Uint8Array): Promise<void> {\n const protocol = await loadProtocol();\n const decoded = protocol.decode(frame);\n if (!decoded.ok) {\n rejectAll(runtime, decoded.error);\n return;\n }\n\n const envelope = decoded.value;\n if (envelope.kind === protocol.EnvelopeKind.RESPONSE) {\n const pending = runtime.pending.get(envelope.req_id);\n if (pending && !pendingRequestMatchesSwapId(pending, envelope.swap_id)) {\n rejectPending(\n runtime,\n envelope.req_id,\n requestSwapIdMismatchError(envelope.req_id, pending.expectedSwapId, envelope.swap_id),\n );\n return;\n }\n }\n\n const errorPayload =\n envelope.kind === protocol.EnvelopeKind.ERROR ? protocol.asErrorPayload(envelope) : null;\n if (errorPayload?.failed_req_id !== undefined) {\n const pending = runtime.pending.get(errorPayload.failed_req_id);\n if (pending && !pendingRequestMatchesSwapId(pending, envelope.swap_id, false)) {\n rejectPending(\n runtime,\n errorPayload.failed_req_id,\n requestSwapIdMismatchError(\n errorPayload.failed_req_id,\n pending.expectedSwapId,\n envelope.swap_id,\n ),\n );\n return;\n }\n }\n\n for (const handler of runtime.envelopeHandlers) handler(envelope);\n\n if (envelope.kind === protocol.EnvelopeKind.ERROR) {\n const payload = errorPayload!;\n const error = commandErrorFromCoordinatorError(payload);\n if (payload.failed_req_id === undefined || payload.failed_req_id === OUT_OF_BAND_REQUEST_ID) {\n if (envelope.swap_id !== null) {\n rejectMatchingOutOfBandErrors(runtime, envelope.swap_id, error);\n }\n return;\n }\n const pending = runtime.pending.get(payload.failed_req_id);\n if (!pending) return;\n if (!pendingRequestMatchesSwapId(pending, envelope.swap_id, false)) {\n rejectPending(\n runtime,\n payload.failed_req_id,\n requestSwapIdMismatchError(payload.failed_req_id, pending.expectedSwapId, envelope.swap_id),\n );\n return;\n }\n rejectPending(runtime, payload.failed_req_id, error);\n return;\n }\n\n if (envelope.kind === protocol.EnvelopeKind.PUSH) {\n resolvePushWaiter(runtime, envelope);\n return;\n }\n\n if (envelope.kind !== protocol.EnvelopeKind.RESPONSE) return;\n const pending = runtime.pending.get(envelope.req_id);\n if (!pending) return;\n if (!pendingRequestMatchesSwapId(pending, envelope.swap_id)) {\n rejectPending(\n runtime,\n envelope.req_id,\n requestSwapIdMismatchError(envelope.req_id, pending.expectedSwapId, envelope.swap_id),\n );\n return;\n }\n runtime.pending.delete(envelope.req_id);\n cleanupPendingRequest(pending);\n pending.resolve(envelope);\n}\n\nfunction pendingRequestMatchesSwapId(\n pending: PendingRequest,\n responseSwapId: string | null,\n enforceNonNullResponseSwapId = true,\n): boolean {\n if (\n enforceNonNullResponseSwapId &&\n pending.requireNonNullResponseSwapId &&\n responseSwapId === null\n ) {\n return false;\n }\n return pending.expectedSwapId === null || pending.expectedSwapId === responseSwapId;\n}\n\nfunction requestSwapIdMismatchError(\n reqId: number,\n expectedSwapId: string | null,\n receivedSwapId: string | null,\n): CommandError {\n return new CommandError(\n \"REJECTED_STATE\",\n `coordinator response swap_id mismatch for req_id=${reqId}: expected ${expectedSwapId ?? \"null\"}, received ${receivedSwapId ?? \"null\"}`,\n { failedReqId: reqId },\n );\n}\n\nfunction resolvePushWaiter(runtime: ProtocolRuntime, envelope: Envelope): void {\n const waiters = runtime.pushWaiters.get(envelope.type);\n const waiterIndex = waiters?.findIndex(\n (candidate) => candidate.swapId === undefined || candidate.swapId === envelope.swap_id,\n );\n const waiter =\n waiters && waiterIndex !== undefined && waiterIndex >= 0\n ? waiters.splice(waiterIndex, 1)[0]\n : undefined;\n if (!waiter || !waiters) return;\n if (waiters.length === 0) {\n runtime.pushWaiters.delete(envelope.type);\n }\n if (waiter.timer) clearTimeout(waiter.timer);\n waiter.resolve(envelope);\n}\n\nfunction rejectPending(runtime: ProtocolRuntime, reqId: number, error: Error): void {\n const pending = runtime.pending.get(reqId);\n if (!pending) return;\n runtime.pending.delete(reqId);\n cleanupPendingRequest(pending);\n pending.reject(error);\n}\n\nfunction cleanupPendingRequest(pending: PendingRequest): void {\n if (pending.timer) clearTimeout(pending.timer);\n if (pending.signal !== undefined && pending.abortHandler !== undefined) {\n pending.signal.removeEventListener(\"abort\", pending.abortHandler);\n }\n}\n\nfunction throwIfRequestAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) throw createRequestAbortError();\n}\n\nfunction createRequestAbortError(): DOMException {\n return new DOMException(\"coordinator request aborted\", \"AbortError\");\n}\n\nfunction rejectMatchingOutOfBandErrors(\n runtime: ProtocolRuntime,\n swapId: string,\n error: Error,\n): void {\n for (const [reqId, pending] of runtime.pending) {\n if (!pending.rejectMatchingOutOfBandErrors || pending.swapId !== swapId) continue;\n rejectPending(runtime, reqId, error);\n }\n}\n\nfunction commandErrorFromCoordinatorError(payload: {\n readonly code: string;\n readonly failed_req_id?: number;\n readonly message: string;\n}): CommandError {\n const coordinatorCode = toCoordinatorWireErrorCode(payload.code);\n return new CommandError(commandCodeFromCoordinatorCode(coordinatorCode), payload.message, {\n coordinatorCode,\n ...(payload.failed_req_id !== undefined ? { failedReqId: payload.failed_req_id } : {}),\n });\n}\n\nfunction commandCodeFromCoordinatorCode(code: CoordinatorWireErrorCode): CommandErrorCode {\n switch (code) {\n case \"ERR_UNEXPECTED_TYPE\":\n case \"ERR_UNKNOWN_SWAP\":\n case \"ERR_SWAP_NOT_REFUNDABLE\":\n return \"REJECTED_STATE\";\n case \"ERR_INTERNAL\":\n case \"ERR_SETTLEMENT_FAILED\":\n return \"REJECTED_STALE_JOB\";\n case \"ERR_INVALID_PAYLOAD\":\n case \"ERR_POLICY_VIOLATION\":\n case \"ERR_INVALID_RECOVERY_CODE\":\n case \"ERR_DKG_FAILURE\":\n case \"ERR_INVALID_DEPOSIT\":\n return \"REJECTED_GUARD\";\n }\n}\n\nfunction toCoordinatorWireErrorCode(code: string): CoordinatorWireErrorCode {\n switch (code) {\n case \"ERR_INVALID_PAYLOAD\":\n case \"ERR_UNEXPECTED_TYPE\":\n case \"ERR_UNKNOWN_SWAP\":\n case \"ERR_POLICY_VIOLATION\":\n case \"ERR_INVALID_RECOVERY_CODE\":\n case \"ERR_SWAP_NOT_REFUNDABLE\":\n case \"ERR_DKG_FAILURE\":\n case \"ERR_INTERNAL\":\n case \"ERR_INVALID_DEPOSIT\":\n case \"ERR_SETTLEMENT_FAILED\":\n return code;\n default:\n return \"ERR_INTERNAL\";\n }\n}\n\nfunction removePushWaiter(\n runtime: ProtocolRuntime,\n type: CoordinatorMessageType,\n waiter: PushWaiter,\n): void {\n const waiters = runtime.pushWaiters.get(type);\n if (!waiters) return;\n const index = waiters.indexOf(waiter);\n if (index >= 0) waiters.splice(index, 1);\n if (waiters.length === 0) runtime.pushWaiters.delete(type);\n}\n\nfunction rejectAll(runtime: ProtocolRuntime, error: Error): void {\n for (const [reqId, pending] of runtime.pending.entries()) {\n runtime.pending.delete(reqId);\n cleanupPendingRequest(pending);\n pending.reject(error);\n }\n for (const [type, waiters] of runtime.pushWaiters.entries()) {\n runtime.pushWaiters.delete(type);\n for (const waiter of waiters) {\n if (waiter.timer) clearTimeout(waiter.timer);\n waiter.reject(error);\n }\n }\n}\n"]}