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

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 (2) hide show
  1. package/README.md +97 -188
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,210 +1,119 @@
1
1
  # @invisible-labs/sdk
2
2
 
3
- Frontend-integration TypeScript SDK for the Invisible protocol.
3
+ TypeScript SDK for building private SOL transfer integrations with Invisible.
4
4
 
5
- This package is the single programmatic entrypoint for every user and LP
6
- interaction with an attested Invisible coordinator. It is the contract defined
7
- in [docs/sdk-specification.md](../../docs/sdk-specification.md). The current
8
- build exposes both the functional normal-user pre-deposit request and the
9
- frontend coordinator facade.
5
+ [Documentation](https://docs.invisible.exchange/docs/sdk/) ·
6
+ [Quickstart](https://docs.invisible.exchange/docs/sdk/quickstart/) ·
7
+ [API reference](https://docs.invisible.exchange/docs/sdk/reference/) ·
8
+ [Trust model](https://docs.invisible.exchange/docs/security/)
10
9
 
11
- > Status: **frontend integration SDK**. The attested `/ws-noise` session,
12
- > normal-user contract request and coordinator session, and LP lifecycle helpers
13
- > are functional. Target surfaces that are not wired to the live coordinator
14
- > still throw `NotImplementedError`; no command fakes success.
10
+ > Devnet beta. This release targets Solana devnet. APIs may change before a
11
+ > stable release.
15
12
 
16
- ## Entrypoints
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @invisible-labs/sdk@devnet
17
+ ```
17
18
 
18
- | Import | Covers |
19
- | ----------------------------- | ----------------------------------------------------- |
20
- | `@invisible-labs/sdk` | `createSession`, attestation and coordinator controls |
21
- | `@invisible-labs/sdk/user` | normal-user commands (private transfer) |
22
- | `@invisible-labs/sdk/lp` | liquidity-provider lifecycle |
23
- | `@invisible-labs/sdk/stats` | actor-safe read projections |
24
- | `@invisible-labs/sdk/events` | sync subscriptions |
25
- | `@invisible-labs/sdk/storage` | storage adapters |
26
- | `@invisible-labs/sdk/presets` | optional Invisible coordinator endpoint presets |
19
+ ## What the SDK provides
27
20
 
28
- Each actor entrypoint is independently importable; pulling one in must not drag
29
- the others into a consumer bundle.
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.
30
25
 
31
- See [ARCHITECTURE.md](./ARCHITECTURE.md) for the layered module map (mermaid).
26
+ ## Entrypoints
27
+
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 |
32
34
 
33
- ## Private-transfer amount limits
35
+ ## Private transfer
34
36
 
35
- Use the public user-entry constants for inclusive preflight validation. Values
36
- are expressed in lamports, matching the `amountLamports` request field.
37
+ Configure the coordinator from the current approved release information, then
38
+ create a user session:
37
39
 
38
40
  ```ts
39
- import { MAX_ENTRY_AMOUNT_LAMPORTS, MIN_ENTRY_AMOUNT_LAMPORTS } from "@invisible-labs/sdk/user";
41
+ import { normalizeError } from "@invisible-labs/sdk";
42
+ import { createCoordinatorSession } from "@invisible-labs/sdk/user";
40
43
 
41
- const isValidEntryAmount = (amountLamports: number) =>
42
- amountLamports >= MIN_ENTRY_AMOUNT_LAMPORTS && amountLamports <= MAX_ENTRY_AMOUNT_LAMPORTS;
44
+ const transfer = createCoordinatorSession({
45
+ coordinator,
46
+ });
47
+
48
+ try {
49
+ const result = await transfer.runSwap({
50
+ 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
+ },
64
+ });
65
+
66
+ console.log(result.swapId);
67
+ } catch (error) {
68
+ console.error(normalizeError(error));
69
+ } finally {
70
+ transfer.close();
71
+ }
43
72
  ```
44
73
 
45
- ## Quickstart
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.
46
77
 
47
- ```ts
48
- import { createCoordinatorSession } from "@invisible-labs/sdk/user";
78
+ ## Security model
49
79
 
50
- const coordinator = {
51
- endpoints: [
52
- /* CoordinatorEndpoint[] - supply your own, or use @invisible-labs/sdk/presets */
53
- ],
54
- };
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.
55
83
 
56
- const user = createCoordinatorSession({ coordinator });
84
+ Integrators remain responsible for:
57
85
 
58
- await user.runSwap({ amountLamports: 3_000_000_000, payoutSpec });
59
- ```
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.
60
91
 
61
- The quickstart above is the full normal-user transfer path. For a bot or server
62
- integration that owns the deposit step, use `contractRequest` from
63
- `@invisible-labs/sdk/user`. It resolves after durable delegation and returns
64
- `swapId`, `depositAddress`, `depositExpiresAtMs`, `syncSecret`, and the generated
65
- Recovery Code before waiting for a deposit. Set `payoutPolicy.totalDeadlineMs`
66
- to `0` for instant payout, or to `3_600_000`, `86_400_000`, or `604_800_000`
67
- milliseconds for the supported 1-hour, 24-hour, or 7-day scheduled windows.
68
-
69
- ## What is real vs NO-OP today
70
-
71
- Real and usable now:
72
-
73
- - `createSession` opens a live WebSocket, runs Noise XX, verifies TDX
74
- attestation, and returns an attested `Session`.
75
- - `createCoordinatorSession` in `@invisible-labs/sdk/user` drives the normal-user
76
- contract, sync, refund-withdrawal, and event flow used by the web app.
77
- - The functional `contractRequest`, `requestRefund`, and `sync` exports in
78
- `@invisible-labs/sdk/user` send the same normal-user protocol commands on a
79
- caller-owned attested session.
80
- - `createLpLifecycleClient` and the LP free functions in `@invisible-labs/sdk/lp`
81
- drive position open/recover, DKG, funding, refill, withdrawal, confirmation,
82
- and listing. Lower-level LP coordinator and DKG helpers remain available.
83
- - Input validation: `PayoutPolicy` and LP plan checks throw `PolicyValidationError`;
84
- LP client-side lifecycle states throw `LpLifecycleError`.
85
- - The closed `InvisibleError` taxonomy and `normalizeError`.
86
- - `coordinator.endpoints`, `attestation.current` / `policy` (read-only).
87
- - `stats.derivedRefundableLamports` (pure local computation).
88
- - `inMemoryStorage`, `browserStorage`, `extensionStorage`; the `presets`
89
- endpoint helpers.
90
- - `presets.invisibleDevnet(approvedBinaryHash)` targets the public devnet through
91
- the hardened Azure coordinator in prod mode with the release MRTD, Intel root,
92
- MAA, and exact coordinator binary hash pins. The approved 64-hex binary hash
93
- is required at preset construction; no unapproved default is embedded.
94
-
95
- Deferred (throws `NotImplementedError` until each target surface is finalized):
96
-
97
- - Spec-level user free functions other than the live `contractRequest`,
98
- `requestRefund`, and `sync` functions, actor-safe stats, and `events`
99
- subscriptions when they are not the frontend-facing coordinator helpers
100
- listed above.
101
- - Server-HKDF storage. The current web app keeps its local recovery material in
102
- its persisted app store; SDK consumers can choose their own storage controls.
103
-
104
- Before public npm distribution, the remaining deferred functions will either be
105
- wired to the coordinator helpers or removed from the published surface.
106
-
107
- ## Recovery material and storage
108
-
109
- The SDK does not yet persist recovery material automatically from
110
- `createSession`. Consumers that need restart or tab-close recovery must keep the
111
- relevant values themselves, using SDK storage helpers or their own storage layer:
112
-
113
- | Material | Needed for | Current guidance |
114
- | ----------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
- | `swapId` + `syncSecret` | Re-sync a private-transfer status view. | `contractRequest` returns both values and supports `onSyncSecretReady({ secretHex })`; store them before asking the user to deposit. |
116
- | User Recovery Code | Request an origin-bound private-transfer refund. | Persist `onRecoveryCodeReady({ codeHex })` immediately, or pass caller-managed recovery material. Products with stricter local-storage requirements can encrypt it. |
117
- | LP Position Code | Recover and operate an LP position. | Treat like a seed phrase. The SDK keeps derived LP auth only in memory. |
118
-
119
- The Invisible web app currently persists private-transfer `refundCode` and
120
- `syncSecret` locally so users can resume flows. That is the current product
121
- tradeoff. Integrators can use `browserStorage` or `extensionStorage` as local
122
- byte stores, or they can pre-encrypt/wrap values before storing them if their
123
- product requires that.
124
-
125
- Server integrations can keep raw recovery material in their own database/vault,
126
- or derive material from a master secret with domain-separated HKDF. For
127
- pre-acceptance material such as `syncSecret`, use a stable context available
128
- before the coordinator receives `sync_commitment`; `swapId` is only available
129
- after acceptance.
130
-
131
- ## Not in this SDK
132
-
133
- Protocol-fee (admin) payout is deliberately **out of scope** for the SDK. It
134
- lives in a separate, fully isolated, non-public admin frontend. See
135
- [ADR-0120](../../docs/adr/0120-protocol-fee-payout-lives-in-isolated-admin-frontend.md).
136
-
137
- ## Packaging and publishing
138
-
139
- The package is bundled with [tsup](./tsup.config.ts) into a **self-contained
140
- artifact** so it can be installed by an external consumer that has none of this
141
- monorepo's workspace links:
142
-
143
- - The three workspace-internal packages (`@invisible/shared`, `protocol`,
144
- `frost`) are `file:` deps that npm does not rewrite on publish. They are
145
- **inlined** into `dist` (`noExternal`) and live in `devDependencies`, so the
146
- published runtime `dependencies` contain zero `file:` specifiers.
147
- - The **FROST wasm** is inlined into the bundle. The SDK uses a swappable wasm
148
- loader: from source the web app and vitest use
149
- [`frostWasm.dev.ts`](./src/frost/frostWasm.dev.ts) (Vite-friendly asset URL /
150
- Node `file:` read), while tsup swaps in
151
- [`frostWasm.bundled.ts`](./src/frost/frostWasm.bundled.ts) (esbuild `binary`
152
- loader -> inlined bytes) for the published artifact, so there is no runtime
153
- asset path or `import.meta.url` resolution to break in a consumer's bundler.
154
- - Only published third-party packages (`ajv`, `@peculiar/x509`, `@stablelib/*`)
155
- stay external and are declared in `dependencies`.
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.
156
96
 
157
- ```bash
158
- npm run prepare:frost # build or restore frost/pkg for SDK source/bundling
159
- npm run build # tsup: bundled dist + .d.ts
160
- npm run verify:exports # assert exports, bundled dist, and FROST wasm init
161
- npm run smoke:prod-attestation -- --host tee-azure.invisible.exchange --mrtd <96-hex> --binary-hash <64-hex-approved> --azure-maa-issuer <https-url> --azure-maa-jwks-url <https-url> --azure-maa-policy-hash <base64url>
162
- npm run smoke:publish # publish -> install -> typecheck -> import on Verdaccio
163
- npm run publish:public:noop # credential-free public manifest validation
164
- VERSION=<version> NPM_DIST_TAG=devnet npm run publish:public -- --confirm @invisible-labs/sdk@<version>
165
- ```
97
+ Read the full
98
+ [trust model and security boundaries](https://docs.invisible.exchange/docs/security/).
99
+
100
+ ## Devnet limitations
101
+
102
+ - Solana devnet and SOL only.
103
+ - No settlement SLA.
104
+ - Current normal-user transfers support one payout destination.
105
+ - Availability and privacy strength depend on current pool conditions.
106
+ - Some documented target APIs are not yet available in the devnet beta.
107
+
108
+ Use only APIs marked as live in the
109
+ [current reference](https://docs.invisible.exchange/docs/sdk/reference/).
110
+
111
+ ## Documentation
166
112
 
167
- The SDK `build` and `prepack` scripts run `prepare:frost` first, so direct
168
- package builds, `smoke:publish`, and `publish:private` are hermetic from a clean
169
- checkout. In GitHub CI, the first SDK preparation uses the clean FROST WASM
170
- build path, then later SDK build/pack guards in the same job reuse that prepared
171
- artifact. From the repository root, `npm run test:sdk` uses the same SDK
172
- preparer before typecheck, tests, conformance, bundle, export check, and pack
173
- dry-run. The export check also rejects unresolved workspace imports, rejects the
174
- source-only FROST wasm loader path in built `dist`, and instantiates the bundled
175
- FROST wasm once through `dkgRound1`.
176
- `smoke:prod-attestation` also builds first, then verifies a live production
177
- coordinator with `createSession`, `requiredMode=prod`, the supplied MRTD and
178
- approved binary hash pins, Azure MAA pins, and mandatory DCAP collateral.
179
-
180
- ### Publish flow (Verdaccio -> GitHub Packages -> npmjs)
181
-
182
- The package manifest is public-publishable, but public npmjs publication remains
183
- manual. Private GitHub Packages publishing still stages a versioned copy under
184
- `@invisible-labs/sdk`. The progression, each step gated on the previous one
185
- passing:
186
-
187
- 1. **Local (Verdaccio).** `npm run smoke:publish` boots a throwaway local
188
- registry, stages a publishable copy (private flag flipped, unique test
189
- version), publishes it, then installs, typechecks, and imports it from a
190
- clean consumer project. Zero external footprint. Use this to confirm the
191
- tarball works.
192
- 2. **Private remote (GitHub Packages).** Intermediate validation against a real
193
- remote without going public. The executable path is `publish:private`, which
194
- stages the workspace package as `@invisible-labs/sdk` because GitHub Packages
195
- requires the package scope to match the `Invisible-Labs` org. Authenticate
196
- with a PAT or `GITHUB_TOKEN` with `write:packages`, then run:
197
- ```bash
198
- NODE_AUTH_TOKEN=<token> VERSION=0.0.1 npm run publish:private
199
- ```
200
- The release workflow runs this path automatically for SDK-relevant changes
201
- and publishes `<package version>-dev.<run_number>.<run_attempt>` with the
202
- private `dev` dist-tag.
203
- Consumers install the private `dev` dist-tag and import `@invisible-labs/sdk`
204
- directly, with no npm alias; see [`PUBLISHING.md`](./PUBLISHING.md).
205
- 3. **Public validation no-op.** Production promotion runs `publish:public:noop`
206
- with the exact `packages/sdk` version. This verifies the public-publishable
207
- manifest without npmjs credentials or publication.
208
- 4. **Public (npmjs).** After the release commit is on `main`, an authorized npm
209
- publisher runs the manual npmjs publish flow in [`PUBLISHING.md`](./PUBLISHING.md).
210
- CI does not publish to npmjs.
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/)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@invisible-labs/sdk",
3
- "version": "0.6.0-devnet.1",
4
- "description": "Functional, tree-shakeable TypeScript SDK for the Invisible protocol. Frontend-integration build: attested coordinator session plus live user and LP coordinator clients.",
3
+ "version": "0.6.0-devnet.2",
4
+ "description": "TypeScript SDK for building private SOL transfer integrations with Invisible.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",