@invisible-labs/sdk 0.6.0-devnet.2 → 0.6.0-devnet.4

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 +186 -70
  2. package/dist/.invisible-sdk-build-target.json +7 -0
  3. package/dist/{chunk-TQNNTV5F.js → chunk-4X5OCCQW.js} +3 -3
  4. package/dist/{chunk-TQNNTV5F.js.map → chunk-4X5OCCQW.js.map} +1 -1
  5. package/dist/{chunk-7DSVN3MV.js → chunk-5NNEO7IK.js} +41 -36
  6. package/dist/chunk-5NNEO7IK.js.map +1 -0
  7. package/dist/chunk-BRDLLGCZ.js +59 -0
  8. package/dist/chunk-BRDLLGCZ.js.map +1 -0
  9. package/dist/{chunk-NCY4FCYU.js → chunk-DIA6U2CV.js} +19 -3
  10. package/dist/chunk-DIA6U2CV.js.map +1 -0
  11. package/dist/{chunk-LBC7ALYO.js → chunk-E4DCEDAG.js} +177 -12
  12. package/dist/chunk-E4DCEDAG.js.map +1 -0
  13. package/dist/{chunk-OHIM2YWU.js → chunk-GHBQF3A7.js} +2 -2
  14. package/dist/chunk-GHBQF3A7.js.map +1 -0
  15. package/dist/{chunk-SZAYO2L5.js → chunk-NHEHCUS5.js} +3 -3
  16. package/dist/{chunk-SZAYO2L5.js.map → chunk-NHEHCUS5.js.map} +1 -1
  17. package/dist/{chunk-XUWBGET5.js → chunk-UADJCUPK.js} +125 -18
  18. package/dist/chunk-UADJCUPK.js.map +1 -0
  19. package/dist/{chunk-JRMKCE3S.js → chunk-V5HXJRBW.js} +3 -3
  20. package/dist/{chunk-JRMKCE3S.js.map → chunk-V5HXJRBW.js.map} +1 -1
  21. package/dist/{coordinator-7Y45MCCZ.js → coordinator-ZNLGAYXD.js} +3 -3
  22. package/dist/{coordinator-7Y45MCCZ.js.map → coordinator-ZNLGAYXD.js.map} +1 -1
  23. package/dist/events.js +3 -3
  24. package/dist/index.d.ts +62 -300
  25. package/dist/index.js +98 -43
  26. package/dist/index.js.map +1 -1
  27. package/dist/lp.d.ts +51 -10
  28. package/dist/lp.js +313 -86
  29. package/dist/lp.js.map +1 -1
  30. package/dist/presets.d.ts +5 -42
  31. package/dist/presets.js +11 -62
  32. package/dist/presets.js.map +1 -1
  33. package/dist/stats.js +1 -1
  34. package/dist/storage.js +1 -1
  35. package/dist/{createSession-D3ym-Ira.d.ts → types.generated-DJBTjLpP.d.ts} +37 -53
  36. package/dist/user.d.ts +94 -112
  37. package/dist/user.js +649 -248
  38. package/dist/user.js.map +1 -1
  39. package/package.json +2 -28
  40. package/dist/chunk-7DSVN3MV.js.map +0 -1
  41. package/dist/chunk-LBC7ALYO.js.map +0 -1
  42. package/dist/chunk-NCY4FCYU.js.map +0 -1
  43. package/dist/chunk-OHIM2YWU.js.map +0 -1
  44. package/dist/chunk-XUWBGET5.js.map +0 -1
  45. package/dist/types.generated-CHGSbmLp.d.ts +0 -67
package/README.md CHANGED
@@ -7,8 +7,11 @@ TypeScript SDK for building private SOL transfer integrations with Invisible.
7
7
  [API reference](https://docs.invisible.exchange/docs/sdk/reference/) ·
8
8
  [Trust model](https://docs.invisible.exchange/docs/security/)
9
9
 
10
- > Devnet beta. This release targets Solana devnet. APIs may change before a
11
- > stable release.
10
+ > Devnet beta. This release targets Solana devnet. APIs may change before a stable release.
11
+
12
+ This package is the programmatic entrypoint for user and LP interaction with an attested Invisible
13
+ coordinator. The normal-user surface uses one functional sequence over a caller-owned session:
14
+ `createSession`, `contractRequest`, `sync`, `requestRefund`, then `closeSession`.
12
15
 
13
16
  ## Install
14
17
 
@@ -16,86 +19,162 @@ TypeScript SDK for building private SOL transfer integrations with Invisible.
16
19
  npm install @invisible-labs/sdk@devnet
17
20
  ```
18
21
 
19
- ## What the SDK provides
22
+ ## Session boundary
23
+
24
+ The public artifact exposes a production-only root facade:
25
+
26
+ ```ts
27
+ import { closeSession, createSession } from "@invisible-labs/sdk";
20
28
 
21
- - Attested coordinator sessions over WSS and Noise XX.
22
- - Private SOL transfer, status-sync, and refund flows.
23
- - Imports limited to the features an application needs.
24
- - Typed errors and runtime validation at protocol boundaries.
29
+ const session = await createSession({
30
+ coordinatorUrl: "wss://tee-azure.invisible.exchange/ws-noise",
31
+ });
32
+
33
+ // Use the session with @invisible-labs/sdk/user or /lp, then:
34
+ closeSession(session);
35
+ ```
36
+
37
+ The public build embeds the approved production attestation tuple. It accepts a
38
+ non-loopback `wss://` URL, but it does not accept `requiredMode`, a coordinator
39
+ pool, release-pin overrides, or local-attestation controls. The private
40
+ workspace build keeps the low-level pool constructor and exposes
41
+ `createDevSession` for explicit local and test flows; that facade is not in the
42
+ public artifact.
43
+
44
+ `sdk.attestation.productionPolicy()` exposes the embedded tuple as read-only
45
+ metadata. It is not a caller-controlled trust input.
25
46
 
26
47
  ## Entrypoints
27
48
 
28
- | Import | Purpose |
29
- | ----------------------------- | --------------------------------------------------- |
30
- | `@invisible-labs/sdk` | Session lifecycle, attestation, and shared controls |
31
- | `@invisible-labs/sdk/user` | Private-transfer and refund flows |
32
- | `@invisible-labs/sdk/events` | Sync subscriptions |
33
- | `@invisible-labs/sdk/storage` | Client storage adapters |
49
+ | Import | Covers |
50
+ | ----------------------------- | ------------------------------------------------------ |
51
+ | `@invisible-labs/sdk` | `createSession`, attestation, and coordinator controls |
52
+ | `@invisible-labs/sdk/user` | normal-user commands: private transfer, sync, refund |
53
+ | `@invisible-labs/sdk/lp` | liquidity-provider lifecycle |
54
+ | `@invisible-labs/sdk/stats` | actor-safe read projections |
55
+ | `@invisible-labs/sdk/events` | sync subscriptions |
56
+ | `@invisible-labs/sdk/storage` | storage adapters |
57
+ | `@invisible-labs/sdk/presets` | optional coordinator endpoint presets |
58
+
59
+ Each actor entrypoint is independently importable; pulling one in must not drag the others into a
60
+ consumer bundle. See [ARCHITECTURE.md](./ARCHITECTURE.md) for the layered module map.
34
61
 
35
62
  ## Private transfer
36
63
 
37
- Configure the coordinator from the current approved release information, then
38
- create a user session:
64
+ The canonical normal-user flow uses one attested session and the functional SDK commands:
39
65
 
40
66
  ```ts
41
- import { normalizeError } from "@invisible-labs/sdk";
42
- import { createCoordinatorSession } from "@invisible-labs/sdk/user";
43
-
44
- const transfer = createCoordinatorSession({
45
- coordinator,
46
- });
47
-
67
+ import { closeSession, createSession } from "@invisible-labs/sdk";
68
+ import {
69
+ contractRequest,
70
+ recoveryCodeFromHex,
71
+ requestRefund,
72
+ sync,
73
+ } from "@invisible-labs/sdk/user";
74
+
75
+ const coordinatorUrl = "wss://tee-azure.invisible.exchange/ws-noise";
76
+ const payoutPolicy = {
77
+ destinations: [{ address: receiverPublicKey, sharePercent: 100 }],
78
+ totalDeadlineMs: 0,
79
+ };
80
+
81
+ const session = await createSession({ coordinatorUrl });
48
82
  try {
49
- const result = await transfer.runSwap({
83
+ const contract = await contractRequest(session, {
50
84
  amountLamports: 3_000_000_000,
51
- payoutSpec: {
52
- mode: "instant",
53
- destination_address: destinationAddress,
54
- },
55
- onSyncSecretReady({ secretHex }) {
56
- saveSyncSecret(secretHex);
57
- },
58
- onRecoveryCodeReady({ codeHex }) {
59
- saveRecoveryCode(codeHex);
60
- },
61
- onDepositAddressReady(deposit) {
62
- showDepositInstructions(deposit);
63
- },
85
+ payoutPolicy,
64
86
  });
65
-
66
- console.log(result.swapId);
67
- } catch (error) {
68
- console.error(normalizeError(error));
87
+ const status = await sync(session, contract.swapId, contract.syncSecret);
88
+ console.log(status.state, status.coordinatorTimestampMs);
89
+
90
+ if (status.actor_sync?.snapshot.refundability === "available_now") {
91
+ const receipt = await requestRefund(session, {
92
+ swapId: contract.swapId,
93
+ syncSecret: contract.syncSecret,
94
+ recoveryCode: recoveryCodeFromHex(contract.recoveryCodeHex!),
95
+ });
96
+ console.log(receipt.requestId, receipt.amountLamports);
97
+ }
69
98
  } finally {
70
- transfer.close();
99
+ closeSession(session);
71
100
  }
72
101
  ```
73
102
 
74
- See the
75
- [private-transfer guide](https://docs.invisible.exchange/docs/sdk/private-transfer/)
76
- for funding, settlement events, scheduled receive, sync, and refunds.
103
+ `contractRequest` resolves after durable delegation and before the deposit is observed. Its result
104
+ contains `swapId`, `depositAddress`, `depositExpiresAtMs`, `syncSecret`, and the generated Recovery
105
+ Code. Persist the sync secret and Recovery Code before asking the user to deposit. Send exactly
106
+ `amountLamports` to the deposit address. The `sync` response contains actor-scoped lifecycle truth
107
+ and the coordinator response timestamp; it does not expose an internal payout due timestamp. A
108
+ refund receipt also carries the coordinator-authoritative accepted amount; use that value for
109
+ pending refund accounting and use `sync` for final landing, cancellation, and fee-loss outcomes.
77
110
 
78
- ## Security model
111
+ For crash recovery before delegation, persist `policySnapshot` from the contract result and call
112
+ `resumePreDelegation` with it, the `resumeSecret`, and the Recovery Code commitment. When resuming
113
+ DKG, `onDelegateShareReady` is invoked before `DkgRound2` so the generated Alice share can be
114
+ persisted. Resume fails closed if the coordinator acknowledges a different spending policy.
115
+
116
+ ## Private-transfer amount limits
117
+
118
+ Use the public user-entry constants for inclusive preflight validation. Values are expressed in
119
+ lamports, matching the `amountLamports` request field. The current V0 bounds are `1.5 SOL`
120
+ (`1_500_000_000` lamports) minimum and `100 SOL` (`100_000_000_000` lamports) maximum.
121
+ The SDK rejects non-safe integers and values outside these bounds before sending a coordinator
122
+ request.
123
+
124
+ ```ts
125
+ import { MAX_ENTRY_AMOUNT_LAMPORTS, MIN_ENTRY_AMOUNT_LAMPORTS } from "@invisible-labs/sdk/user";
126
+
127
+ const isValidEntryAmount = (amountLamports: number) =>
128
+ Number.isSafeInteger(amountLamports) &&
129
+ amountLamports >= MIN_ENTRY_AMOUNT_LAMPORTS &&
130
+ amountLamports <= MAX_ENTRY_AMOUNT_LAMPORTS;
131
+ ```
132
+
133
+ ## Live and deferred surfaces
79
134
 
80
- The SDK establishes an encrypted Noise XX channel and verifies TDX attestation
81
- before sensitive protocol material is sent. Verification failures stop the
82
- session.
135
+ Live today:
83
136
 
84
- Integrators remain responsible for:
137
+ - `createSession` opens a live WebSocket, runs Noise XX, verifies TDX attestation, and returns an
138
+ attested `Session`.
139
+ - `contractRequest`, `sync`, and `requestRefund` are the only normal-user command path over a
140
+ caller-owned attested session. `closeSession` ends the flow.
141
+ - LP lifecycle helpers drive position open/recover, DKG, funding, refill, withdrawal, confirmation,
142
+ and listing.
143
+ - Input validation throws typed `PolicyValidationError`; the closed `InvisibleError` taxonomy and
144
+ `normalizeError` are available to callers.
85
145
 
86
- - loading coordinator measurements from an approved release source;
87
- - protecting Recovery Codes and sync secrets;
88
- - persisting recovery material before asking a user to deposit;
89
- - using fresh payout destinations;
90
- - handling reconnects through sync instead of blindly repeating commands.
146
+ Other target surfaces throw `NotImplementedError` until each is finalized. No command fakes success.
91
147
 
92
- Invisible is trust-minimized, not trustless. Attestation verifies an approved
93
- coordinator build; it does not prove that the code is bug-free. Privacy is not
94
- absolute and can be weakened by low pool depth, timing, amount correlation,
95
- destination reuse, and off-chain metadata.
148
+ ## Recovery material and storage
96
149
 
97
- Read the full
98
- [trust model and security boundaries](https://docs.invisible.exchange/docs/security/).
150
+ The SDK does not persist recovery material automatically. Consumers that need restart or tab-close
151
+ recovery must store the relevant values themselves:
152
+
153
+ | Material | Needed for | Guidance |
154
+ | ----------------------- | ----------------------------------------------- | ------------------------------------------------------- |
155
+ | `swapId` + `syncSecret` | Re-sync a private-transfer status view | Persist before asking the user to deposit. |
156
+ | User Recovery Code | Request an origin-bound private-transfer refund | Treat it like a seed phrase and persist it immediately. |
157
+ | LP Position Code | Recover and operate an LP position | Keep it out of logs and treat it like a seed phrase. |
158
+
159
+ The web app persists private-transfer recovery material locally so users can resume flows. SDK
160
+ consumers can choose `browserStorage`, `extensionStorage`, or their own encrypted storage layer.
161
+
162
+ LP DKG requests are bounded. If a browser worker stops responding, the SDK terminates the local
163
+ workers and attempts the signed position-scoped DKG abort command within a bounded cleanup window
164
+ before returning the original failure. LP recovery sends the same cleanup command for an
165
+ incomplete position, so a reload does not wait for the coordinator's session expiry.
166
+
167
+ ## Security model
168
+
169
+ The SDK establishes an encrypted Noise XX channel and verifies TDX attestation before sensitive
170
+ protocol material is sent. Verification failures stop the session. Integrators remain responsible
171
+ for loading coordinator measurements from an approved release source, protecting Recovery Codes and
172
+ sync secrets, persisting recovery material before deposit, using fresh payout destinations, and
173
+ handling reconnects through `sync` instead of blindly repeating commands.
174
+
175
+ Invisible is trust-minimized, not trustless. Attestation verifies an approved coordinator build; it
176
+ does not prove that the code is bug-free. Privacy can be weakened by low pool depth, timing, amount
177
+ correlation, destination reuse, and off-chain metadata.
99
178
 
100
179
  ## Devnet limitations
101
180
 
@@ -105,15 +184,52 @@ Read the full
105
184
  - Availability and privacy strength depend on current pool conditions.
106
185
  - Some documented target APIs are not yet available in the devnet beta.
107
186
 
108
- Use only APIs marked as live in the
109
- [current reference](https://docs.invisible.exchange/docs/sdk/reference/).
187
+ Use only APIs marked as live in the [current reference](https://docs.invisible.exchange/docs/sdk/reference/).
188
+
189
+ ## Not in this SDK
190
+
191
+ Protocol-fee admin payout is out of scope for the SDK. It lives behind a separate admin surface.
192
+
193
+ ## Packaging
194
+
195
+ The package is bundled with tsup into a self-contained artifact. Workspace-internal packages and the
196
+ FROST WASM are inlined into the published bundle, while published third-party packages remain
197
+ external dependencies.
198
+
199
+ ```bash
200
+ npm run build:private
201
+ npm run verify:exports
202
+ npm run verify:private-artifact
203
+ ```
204
+
205
+ The public artifact is built separately with approved release inputs:
206
+
207
+ ```bash
208
+ SDK_PRODUCTION_BINARY_HASH=<64-hex-binary-sha256> \
209
+ AZURE_PROD_EXPECTED_BINARY_HASH=<same-64-hex-binary-sha256> \
210
+ SDK_PRODUCTION_COORDINATOR_MRTD=<96-hex-mrtd> \
211
+ SDK_PRODUCTION_RUNTIME_PROFILE=prod-devnet-simplified \
212
+ npm run build:public
213
+ npm run verify:exports
214
+ npm run verify:public-build-marker
215
+ npm run verify:public-artifact
216
+ ```
217
+
218
+ The public production smoke consumes that already verified artifact. It requires
219
+ `--prebuilt-sdk` plus an operator-approved release manifest whose exact file
220
+ SHA-256 is supplied separately:
221
+
222
+ ```bash
223
+ SDK_APPROVED_RELEASE_MANIFEST_PATH=<approved-release-manifest> \
224
+ SDK_APPROVED_RELEASE_MANIFEST_SHA256=<sha256-of-manifest-bytes> \
225
+ npm --workspace @invisible-labs/sdk run smoke:prod-attestation -- \
226
+ --host tee-azure.invisible.exchange --mrtd <96-hex-mrtd> \
227
+ --binary-hash <64-hex-binary-sha256> --target public \
228
+ --runtime-profile prod-devnet-simplified --prebuilt-sdk
229
+ ```
110
230
 
111
- ## Documentation
231
+ Do not pack the workspace directly. Use the private or public staged publish
232
+ commands so the selected build target and artifact marker are checked.
112
233
 
113
- - [SDK overview](https://docs.invisible.exchange/docs/sdk/)
114
- - [Quickstart](https://docs.invisible.exchange/docs/sdk/quickstart/)
115
- - [Examples](https://docs.invisible.exchange/docs/sdk/examples/)
116
- - [API reference](https://docs.invisible.exchange/docs/sdk/reference/)
117
- - [Compatibility](https://docs.invisible.exchange/docs/sdk/compatibility/)
118
- - [Versioning](https://docs.invisible.exchange/docs/sdk/versioning/)
119
- - [V0 launch scope](https://docs.invisible.exchange/docs/v0-launch/)
234
+ Private smoke runs may rebuild the private SDK. Public smoke must use
235
+ `--prebuilt-sdk` so it cannot rebuild after the public artifact gates.
@@ -0,0 +1,7 @@
1
+ {
2
+ "package": "@invisible-labs/sdk",
3
+ "target": "public",
4
+ "productionBinaryHash": "92237e1cc0d528a12288ff5a2d99eff38ab387080d31eb4146526daa6c973860",
5
+ "productionMrtd": "a2e61f1316e9e367e9c1f7a0adc98c48eb13875c399c85d286cee5ea2b05e57f2df9f61d903b0ae7ac5607d843dfffc1",
6
+ "productionRuntimeProfile": "prod-devnet-simplified"
7
+ }
@@ -6,12 +6,12 @@ var LP_DEFAULT_TARGET_SHARDS = 200;
6
6
  var LP_MAX_TARGET_SHARDS = 300;
7
7
  var LP_DEFAULT_REFILL_BATCH_SIZE = 50;
8
8
  var LP_MAX_REFILL_BATCH_SIZE = 50;
9
- var PRODUCT_MIN_ENTRY_LAMPORTS = 4e8;
9
+ var PRODUCT_MIN_ENTRY_LAMPORTS = 15e8;
10
10
  var PRODUCT_MAX_ENTRY_LAMPORTS = 1e11;
11
11
  function isValidLpPositionId(lpPositionId) {
12
12
  return lpPositionId.length >= LP_POSITION_ID_MIN_LENGTH && lpPositionId.length <= LP_POSITION_ID_MAX_LENGTH && LP_POSITION_ID_PATTERN.test(lpPositionId);
13
13
  }
14
14
 
15
15
  export { LP_DEFAULT_REFILL_BATCH_SIZE, LP_DEFAULT_TARGET_SHARDS, LP_MAX_REFILL_BATCH_SIZE, LP_MAX_TARGET_SHARDS, PRODUCT_MAX_ENTRY_LAMPORTS, PRODUCT_MIN_ENTRY_LAMPORTS, isValidLpPositionId };
16
- //# sourceMappingURL=chunk-TQNNTV5F.js.map
17
- //# sourceMappingURL=chunk-TQNNTV5F.js.map
16
+ //# sourceMappingURL=chunk-4X5OCCQW.js.map
17
+ //# sourceMappingURL=chunk-4X5OCCQW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../shared/src/index.ts"],"names":[],"mappings":";AAgBO,IAAM,yBAAA,GAA4B,CAAA;AAClC,IAAM,yBAAA,GAA4B,EAAA;AAClC,IAAM,sBAAA,GAAyB,kBAAA;AAC/B,IAAM,wBAAA,GAA2B;AACjC,IAAM,oBAAA,GAAuB;AAC7B,IAAM,4BAAA,GAA+B;AACrC,IAAM,wBAAA,GAA2B;AAKjC,IAAM,0BAAA,GAA6B;AACnC,IAAM,0BAAA,GAA6B;AAGnC,SAAS,oBAAoB,YAAA,EAA+B;AACjE,EAAA,OACE,YAAA,CAAa,UAAU,yBAAA,IACvB,YAAA,CAAa,UAAU,yBAAA,IACvB,sBAAA,CAAuB,KAAK,YAAY,CAAA;AAE5C","file":"chunk-TQNNTV5F.js","sourcesContent":["/**\n * Shared workspace entrypoint.\n *\n * Keep exports here pure and reusable across workspaces. Do not put React,\n * DOM-only, libp2p runtime state, or feature-specific glue in this package.\n */\nexport function sleep(ms: number): Promise<void> {\n if (ms <= 0) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport const LP_POSITION_ID_MIN_LENGTH = 3;\nexport const LP_POSITION_ID_MAX_LENGTH = 96;\nexport const LP_POSITION_ID_PATTERN = /^[A-Za-z0-9_-]+$/;\nexport const LP_DEFAULT_TARGET_SHARDS = 200;\nexport const LP_MAX_TARGET_SHARDS = 300;\nexport const LP_DEFAULT_REFILL_BATCH_SIZE = 50;\nexport const LP_MAX_REFILL_BATCH_SIZE = 50;\n\n// Temporary TypeScript mirrors of the Rust TEE entry limits, plus the distinct\n// mainnet UI default. Keep them guarded by `npm run product-limits:check` until\n// cross-language generated product constants exist.\nexport const PRODUCT_MIN_ENTRY_LAMPORTS = 400_000_000;\nexport const PRODUCT_MAX_ENTRY_LAMPORTS = 100_000_000_000;\nexport const PRODUCT_DEFAULT_MAINNET_ENTRY_LAMPORTS = 3_000_000_000;\n\nexport function isValidLpPositionId(lpPositionId: string): boolean {\n return (\n lpPositionId.length >= LP_POSITION_ID_MIN_LENGTH &&\n lpPositionId.length <= LP_POSITION_ID_MAX_LENGTH &&\n LP_POSITION_ID_PATTERN.test(lpPositionId)\n );\n}\n"]}
1
+ {"version":3,"sources":["../../shared/src/index.ts"],"names":[],"mappings":";AAgBO,IAAM,yBAAA,GAA4B,CAAA;AAClC,IAAM,yBAAA,GAA4B,EAAA;AAClC,IAAM,sBAAA,GAAyB,kBAAA;AAC/B,IAAM,wBAAA,GAA2B;AACjC,IAAM,oBAAA,GAAuB;AAC7B,IAAM,4BAAA,GAA+B;AACrC,IAAM,wBAAA,GAA2B;AAKjC,IAAM,0BAAA,GAA6B;AACnC,IAAM,0BAAA,GAA6B;AAGnC,SAAS,oBAAoB,YAAA,EAA+B;AACjE,EAAA,OACE,YAAA,CAAa,UAAU,yBAAA,IACvB,YAAA,CAAa,UAAU,yBAAA,IACvB,sBAAA,CAAuB,KAAK,YAAY,CAAA;AAE5C","file":"chunk-4X5OCCQW.js","sourcesContent":["/**\n * Shared workspace entrypoint.\n *\n * Keep exports here pure and reusable across workspaces. Do not put React,\n * DOM-only, libp2p runtime state, or feature-specific glue in this package.\n */\nexport function sleep(ms: number): Promise<void> {\n if (ms <= 0) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport const LP_POSITION_ID_MIN_LENGTH = 3;\nexport const LP_POSITION_ID_MAX_LENGTH = 96;\nexport const LP_POSITION_ID_PATTERN = /^[A-Za-z0-9_-]+$/;\nexport const LP_DEFAULT_TARGET_SHARDS = 200;\nexport const LP_MAX_TARGET_SHARDS = 300;\nexport const LP_DEFAULT_REFILL_BATCH_SIZE = 50;\nexport const LP_MAX_REFILL_BATCH_SIZE = 50;\n\n// Temporary TypeScript mirrors of the Rust TEE entry limits, plus the distinct\n// mainnet UI default. Keep them guarded by `npm run product-limits:check` until\n// cross-language generated product constants exist.\nexport const PRODUCT_MIN_ENTRY_LAMPORTS = 1_500_000_000;\nexport const PRODUCT_MAX_ENTRY_LAMPORTS = 100_000_000_000;\nexport const PRODUCT_DEFAULT_MAINNET_ENTRY_LAMPORTS = 1_500_000_000;\n\nexport function isValidLpPositionId(lpPositionId: string): boolean {\n return (\n lpPositionId.length >= LP_POSITION_ID_MIN_LENGTH &&\n lpPositionId.length <= LP_POSITION_ID_MAX_LENGTH &&\n LP_POSITION_ID_PATTERN.test(lpPositionId)\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { failSessionClosed, createSessionHandle, getSessionState, closeSessionState } from './chunk-JRMKCE3S.js';
2
- import { verifyAttestation, assertAttestResponse } from './chunk-NCY4FCYU.js';
3
- import { TransportError, AttestationError } from './chunk-OHIM2YWU.js';
1
+ import { failSessionClosed, createSessionHandle, getSessionState, closeSessionState } from './chunk-V5HXJRBW.js';
2
+ import { verifyAttestation, assertAttestResponse } from './chunk-DIA6U2CV.js';
3
+ import { TransportError, AttestationError } from './chunk-GHBQF3A7.js';
4
4
  import { generateKeyPair, sharedKey } from '@stablelib/x25519';
5
5
  import { ChaCha20Poly1305 } from '@stablelib/chacha20poly1305';
6
6
  import { hash, SHA256 } from '@stablelib/sha256';
@@ -398,6 +398,7 @@ function toAttestationPolicy(endpoint) {
398
398
  // ignore the MRTD pin inside the verifier.
399
399
  expectedMrtd: pin.mrtd,
400
400
  ...pin.binaryHash ? { expectedBinaryHash: pin.binaryHash } : {},
401
+ ...pin.runtimeProfile ? { expectedRuntimeProfile: pin.runtimeProfile } : {},
401
402
  allowMissingDcapCollateral: pin.allowMissingDcapCollateral === true,
402
403
  allowLocalAttestation
403
404
  };
@@ -694,6 +695,7 @@ async function establishAttestedChannel(params) {
694
695
  mrtd: channel.attestation.mrtd,
695
696
  mode: channel.attestation.mode,
696
697
  binaryHash: channel.attestation.binaryHash,
698
+ runtimeProfile: channel.attestation.runtimeProfile,
697
699
  pubkeyHex: channel.attestation.pubkeyHex,
698
700
  localAttestation: channel.attestation.localAttestation,
699
701
  rtmr0: channel.attestation.rtmr0,
@@ -705,33 +707,6 @@ async function establishAttestedChannel(params) {
705
707
  void toAttestationPolicy(endpoint);
706
708
  return { channel, handshake, attestation };
707
709
  }
708
- async function performNoiseHandshake(transport, endpoint, nonce = crypto.getRandomValues(new Uint8Array(32))) {
709
- const established = await establishAttestedChannel({ transport, endpoint, nonce });
710
- return established.handshake;
711
- }
712
- function performAttestation(_transport, handshake) {
713
- const channel = handshake.channel;
714
- if (!channel) {
715
- return Promise.reject(
716
- new TransportError(
717
- "NOISE_HANDSHAKE_FAILED",
718
- "performAttestation requires a handshake result produced by performNoiseHandshake"
719
- )
720
- );
721
- }
722
- return Promise.resolve({
723
- mrtd: channel.attestation.mrtd,
724
- mode: channel.attestation.mode,
725
- binaryHash: channel.attestation.binaryHash,
726
- pubkeyHex: channel.attestation.pubkeyHex,
727
- localAttestation: channel.attestation.localAttestation,
728
- rtmr0: channel.attestation.rtmr0,
729
- rtmr1: channel.attestation.rtmr1,
730
- rtmr2: channel.attestation.rtmr2,
731
- rtmr3: channel.attestation.rtmr3,
732
- verifiedAtMs: Date.now()
733
- });
734
- }
735
710
 
736
711
  // src/schemas/payoutPolicy.schema.json
737
712
  var payoutPolicy_schema_default = {
@@ -872,6 +847,10 @@ var coordinatorPoolConfig_schema_default = {
872
847
  pattern: "^[0-9a-fA-F]{64}$",
873
848
  description: "Optional SHA-256 hash of the approved coordinator binary; required for production Azure attestation."
874
849
  },
850
+ runtimeProfile: {
851
+ enum: ["prod-hardened", "prod-devnet-simplified"],
852
+ description: "Optional compile-time coordinator runtime profile; production simplified deployments must pin it."
853
+ },
875
854
  intelRootFingerprint: {
876
855
  type: "string",
877
856
  description: "Hex SHA-256 of the Intel root cert."
@@ -1023,6 +1002,7 @@ async function reattest(state, endpoint, timeoutMs = DEFAULT_REATTEST_TIMEOUT_MS
1023
1002
  mrtd: metadata.mrtd,
1024
1003
  mode: metadata.mode,
1025
1004
  binaryHash: metadata.binaryHash,
1005
+ runtimeProfile: metadata.runtimeProfile,
1026
1006
  pubkeyHex: metadata.pubkeyHex,
1027
1007
  localAttestation: metadata.localAttestation,
1028
1008
  rtmr0: metadata.rtmr0,
@@ -1052,7 +1032,7 @@ function toHex(b) {
1052
1032
 
1053
1033
  // src/session/createSession.ts
1054
1034
  var REATTEST_EVERY_MS = 9e5;
1055
- async function createSession(options) {
1035
+ async function createSessionInternal(options) {
1056
1036
  const { coordinator } = options;
1057
1037
  if (!validateCoordinatorPoolConfigShape(coordinator)) {
1058
1038
  throw new Error(
@@ -1063,11 +1043,15 @@ async function createSession(options) {
1063
1043
  assertExpectedHostname(endpoint);
1064
1044
  const timeoutMs = coordinator.noiseTransportTimeoutMs;
1065
1045
  const transport = options.transport ?? noiseWebSocketTransport({ wsUrl: endpoint.wsUrl, connectTimeoutMs: timeoutMs });
1066
- await transport.connect();
1046
+ await transport.connect(options.signal);
1067
1047
  const nonce = crypto.getRandomValues(new Uint8Array(32));
1068
1048
  let established;
1069
1049
  try {
1070
- established = await establishAttestedChannel({ transport, endpoint, nonce, timeoutMs });
1050
+ established = await abortableSessionEstablishment(
1051
+ establishAttestedChannel({ transport, endpoint, nonce, timeoutMs }),
1052
+ transport,
1053
+ options.signal
1054
+ );
1071
1055
  } catch (err) {
1072
1056
  transport.close();
1073
1057
  throw err;
@@ -1092,6 +1076,27 @@ async function createSession(options) {
1092
1076
  scheduleReattest(state, endpoint);
1093
1077
  return createSessionHandle(state);
1094
1078
  }
1079
+ function abortableSessionEstablishment(establishment, transport, signal) {
1080
+ if (signal === void 0) return establishment;
1081
+ if (signal.aborted) {
1082
+ transport.close();
1083
+ return Promise.reject(createSessionAbortError());
1084
+ }
1085
+ return new Promise((resolve, reject) => {
1086
+ const onAbort = () => {
1087
+ transport.close();
1088
+ reject(createSessionAbortError());
1089
+ };
1090
+ signal.addEventListener("abort", onAbort, { once: true });
1091
+ void establishment.then(resolve, reject).finally(() => {
1092
+ signal.removeEventListener("abort", onAbort);
1093
+ });
1094
+ });
1095
+ }
1096
+ function createSessionAbortError() {
1097
+ return new TransportError("CONNECTION_LOST", "session establishment aborted");
1098
+ }
1099
+ var createSession = createSessionInternal;
1095
1100
  function assertExpectedHostname(endpoint) {
1096
1101
  let hostname;
1097
1102
  try {
@@ -1140,6 +1145,6 @@ async function runReattest(state, endpoint) {
1140
1145
  }
1141
1146
  }
1142
1147
 
1143
- export { closeSession, createExponentialBackoff, createSession, createStateController, formatAjvErrors, noiseWebSocketTransport, performAttestation, performNoiseHandshake, reattestSerialized, validatePayoutPolicyShape };
1144
- //# sourceMappingURL=chunk-7DSVN3MV.js.map
1145
- //# sourceMappingURL=chunk-7DSVN3MV.js.map
1148
+ export { closeSession, createExponentialBackoff, createSession, createSessionInternal, createStateController, formatAjvErrors, isLoopbackUrl, noiseWebSocketTransport, reattestSerialized, validatePayoutPolicyShape };
1149
+ //# sourceMappingURL=chunk-5NNEO7IK.js.map
1150
+ //# sourceMappingURL=chunk-5NNEO7IK.js.map