@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.
- package/README.md +129 -15
- package/dist/.invisible-sdk-build-target.json +7 -0
- package/dist/{chunk-QQSI3ZD7.js → chunk-3MDHAS4D.js} +109 -17
- package/dist/chunk-3MDHAS4D.js.map +1 -0
- package/dist/{chunk-NKRVQXRP.js → chunk-3TGQ4CZ3.js} +297 -11
- package/dist/chunk-3TGQ4CZ3.js.map +1 -0
- package/dist/chunk-DCTYBUY3.js +258 -0
- package/dist/chunk-DCTYBUY3.js.map +1 -0
- package/dist/{chunk-NHEHCUS5.js → chunk-EBWTAXNT.js} +3 -3
- package/dist/{chunk-NHEHCUS5.js.map → chunk-EBWTAXNT.js.map} +1 -1
- package/dist/{chunk-V5HXJRBW.js → chunk-HJFMDMPY.js} +3 -3
- package/dist/chunk-HJFMDMPY.js.map +1 -0
- package/dist/{chunk-GHBQF3A7.js → chunk-QRN46R3F.js} +5 -2
- package/dist/chunk-QRN46R3F.js.map +1 -0
- package/dist/chunk-Y7AK6RBV.js +4189 -0
- package/dist/chunk-Y7AK6RBV.js.map +1 -0
- package/dist/{coordinator-VVJ33WF2.js → coordinator-PEWHNZ7I.js} +3 -3
- package/dist/{coordinator-VVJ33WF2.js.map → coordinator-PEWHNZ7I.js.map} +1 -1
- package/dist/events.js +3 -3
- package/dist/index.d.ts +69 -353
- package/dist/index.js +161 -43
- package/dist/index.js.map +1 -1
- package/dist/lp.d.ts +76 -18
- package/dist/lp.js +511 -111
- package/dist/lp.js.map +1 -1
- package/dist/presets.d.ts +7 -40
- package/dist/presets.js +10 -68
- package/dist/presets.js.map +1 -1
- package/dist/stats.js +1 -1
- package/dist/storage.js +2 -243
- package/dist/storage.js.map +1 -1
- package/dist/{errors-N2touVm4.d.ts → types.generated-YhFu9ZBR.d.ts} +65 -4
- package/dist/user.d.ts +134 -8
- package/dist/user.js +991 -250
- package/dist/user.js.map +1 -1
- package/package.json +5 -31
- package/dist/chunk-BWCGNTN5.js +0 -1153
- package/dist/chunk-BWCGNTN5.js.map +0 -1
- package/dist/chunk-DIA6U2CV.js +0 -1927
- package/dist/chunk-DIA6U2CV.js.map +0 -1
- package/dist/chunk-GHBQF3A7.js.map +0 -1
- package/dist/chunk-NKRVQXRP.js.map +0 -1
- package/dist/chunk-QQSI3ZD7.js.map +0 -1
- package/dist/chunk-V5HXJRBW.js.map +0 -1
- 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
|
|
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({
|
|
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.
|
|
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
|
-
|
|
123
|
-
|
|
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
|
|
132
|
-
consumers can choose `browserStorage
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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-
|
|
2
|
-
import { TransportError, CommandError } from './chunk-
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
237
|
-
//# sourceMappingURL=chunk-
|
|
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"]}
|