@sogni-ai/sogni-client 5.80.1 → 5.82.0
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/AGENTS.md +2 -1
- package/CHANGELOG.md +25 -0
- package/README.md +192 -2
- package/dist/Account/TwoFactorRequiredError.d.ts +8 -0
- package/dist/Account/TwoFactorRequiredError.js +14 -0
- package/dist/Account/TwoFactorRequiredError.js.map +1 -0
- package/dist/Account/index.d.ts +43 -0
- package/dist/Account/index.js +97 -13
- package/dist/Account/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js +6 -5
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +11 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +43 -5
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/events.d.ts +27 -0
- package/dist/ApiClient/WebSocketClient/index.d.ts +13 -0
- package/dist/ApiClient/WebSocketClient/index.js +33 -1
- package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/messages.d.ts +8 -0
- package/dist/ApiClient/WebSocketClient/types.d.ts +4 -0
- package/dist/ApiClient/index.d.ts +19 -1
- package/dist/ApiClient/index.js +23 -1
- package/dist/ApiClient/index.js.map +1 -1
- package/dist/Chat/modelRouting.d.ts +1 -0
- package/dist/Chat/modelRouting.js +7 -1
- package/dist/Chat/modelRouting.js.map +1 -1
- package/dist/MediaEncryption/index.d.ts +153 -0
- package/dist/MediaEncryption/index.js +434 -0
- package/dist/MediaEncryption/index.js.map +1 -0
- package/dist/Projects/Job.d.ts +27 -1
- package/dist/Projects/Job.js +51 -4
- package/dist/Projects/Job.js.map +1 -1
- package/dist/Projects/Project.d.ts +29 -0
- package/dist/Projects/Project.js +43 -2
- package/dist/Projects/Project.js.map +1 -1
- package/dist/Projects/createJobRequestMessage.js +16 -0
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +63 -2
- package/dist/Projects/index.js +391 -71
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/recovery.js +4 -0
- package/dist/Projects/recovery.js.map +1 -1
- package/dist/Projects/types/JobProvenance.d.ts +2 -0
- package/dist/Projects/types/PayAsYouGo.d.ts +88 -0
- package/dist/Projects/types/PayAsYouGo.js +60 -0
- package/dist/Projects/types/PayAsYouGo.js.map +1 -0
- package/dist/Projects/types/RawProject.d.ts +2 -0
- package/dist/Projects/types/events.d.ts +9 -1
- package/dist/Projects/types/index.d.ts +143 -1
- package/dist/Projects/types/index.js.map +1 -1
- package/dist/Projects/utils/imageLayers.d.ts +7 -0
- package/dist/Projects/utils/imageLayers.js +123 -0
- package/dist/Projects/utils/imageLayers.js.map +1 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaResponse.d.ts +11 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaResponse.js +97 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaResponse.js.map +1 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaWorker.d.ts +5 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaWorker.js +109 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedMediaWorker.js.map +1 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedPlayback.d.ts +12 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedPlayback.js +169 -0
- package/dist/browser/mediaEncryptionPlayback/encryptedPlayback.js.map +1 -0
- package/dist/browser/mediaEncryptionPlayback/index.d.ts +3 -0
- package/dist/browser/mediaEncryptionPlayback/index.js +20 -0
- package/dist/browser/mediaEncryptionPlayback/index.js.map +1 -0
- package/dist/index.d.ts +47 -6
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/RestClient.d.ts +6 -0
- package/dist/lib/RestClient.js +12 -0
- package/dist/lib/RestClient.js.map +1 -1
- package/dist/lib/mediaEncryption/capability.d.ts +16 -0
- package/dist/lib/mediaEncryption/capability.js +12 -0
- package/dist/lib/mediaEncryption/capability.js.map +1 -0
- package/dist/lib/mediaEncryption/crypto.d.ts +36 -0
- package/dist/lib/mediaEncryption/crypto.js +169 -0
- package/dist/lib/mediaEncryption/crypto.js.map +1 -0
- package/dist/lib/mediaEncryption/format.d.ts +62 -0
- package/dist/lib/mediaEncryption/format.js +167 -0
- package/dist/lib/mediaEncryption/format.js.map +1 -0
- package/dist/lib/mediaEncryption/index.d.ts +12 -0
- package/dist/lib/mediaEncryption/index.js +46 -0
- package/dist/lib/mediaEncryption/index.js.map +1 -0
- package/dist/lib/mediaEncryption/inputKeys.d.ts +24 -0
- package/dist/lib/mediaEncryption/inputKeys.js +102 -0
- package/dist/lib/mediaEncryption/inputKeys.js.map +1 -0
- package/dist/lib/mediaEncryption/networks.d.ts +14 -0
- package/dist/lib/mediaEncryption/networks.js +22 -0
- package/dist/lib/mediaEncryption/networks.js.map +1 -0
- package/dist/lib/mediaEncryption/recipient.d.ts +17 -0
- package/dist/lib/mediaEncryption/recipient.js +106 -0
- package/dist/lib/mediaEncryption/recipient.js.map +1 -0
- package/dist/lib/mediaEncryption/redact.d.ts +5 -0
- package/dist/lib/mediaEncryption/redact.js +34 -0
- package/dist/lib/mediaEncryption/redact.js.map +1 -0
- package/dist/lib/mediaEncryption/remote.d.ts +18 -0
- package/dist/lib/mediaEncryption/remote.js +243 -0
- package/dist/lib/mediaEncryption/remote.js.map +1 -0
- package/dist/lib/validation.d.ts +12 -2
- package/dist/lib/validation.js +100 -10
- package/dist/lib/validation.js.map +1 -1
- package/dist/types/ErrorData.d.ts +15 -0
- package/dist/types/ErrorData.js +15 -1
- package/dist/types/ErrorData.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist-esm/Account/TwoFactorRequiredError.js +11 -0
- package/dist-esm/Account/TwoFactorRequiredError.js.map +1 -0
- package/dist-esm/Account/index.js +97 -13
- package/dist-esm/Account/index.js.map +1 -1
- package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js +6 -5
- package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js.map +1 -1
- package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +43 -5
- package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
- package/dist-esm/ApiClient/WebSocketClient/index.js +33 -1
- package/dist-esm/ApiClient/WebSocketClient/index.js.map +1 -1
- package/dist-esm/ApiClient/index.js +23 -1
- package/dist-esm/ApiClient/index.js.map +1 -1
- package/dist-esm/Chat/modelRouting.js +8 -2
- package/dist-esm/Chat/modelRouting.js.map +1 -1
- package/dist-esm/MediaEncryption/index.js +429 -0
- package/dist-esm/MediaEncryption/index.js.map +1 -0
- package/dist-esm/Projects/Job.js +51 -4
- package/dist-esm/Projects/Job.js.map +1 -1
- package/dist-esm/Projects/Project.js +43 -2
- package/dist-esm/Projects/Project.js.map +1 -1
- package/dist-esm/Projects/createJobRequestMessage.js +16 -0
- package/dist-esm/Projects/createJobRequestMessage.js.map +1 -1
- package/dist-esm/Projects/index.js +351 -31
- package/dist-esm/Projects/index.js.map +1 -1
- package/dist-esm/Projects/recovery.js +4 -0
- package/dist-esm/Projects/recovery.js.map +1 -1
- package/dist-esm/Projects/types/PayAsYouGo.js +55 -0
- package/dist-esm/Projects/types/PayAsYouGo.js.map +1 -0
- package/dist-esm/Projects/types/index.js.map +1 -1
- package/dist-esm/Projects/utils/imageLayers.js +120 -0
- package/dist-esm/Projects/utils/imageLayers.js.map +1 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedMediaResponse.js +93 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedMediaResponse.js.map +1 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedMediaWorker.js +106 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedMediaWorker.js.map +1 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedPlayback.js +166 -0
- package/dist-esm/browser/mediaEncryptionPlayback/encryptedPlayback.js.map +1 -0
- package/dist-esm/browser/mediaEncryptionPlayback/index.js +4 -0
- package/dist-esm/browser/mediaEncryptionPlayback/index.js.map +1 -0
- package/dist-esm/index.js +16 -5
- package/dist-esm/index.js.map +1 -1
- package/dist-esm/lib/RestClient.js +12 -0
- package/dist-esm/lib/RestClient.js.map +1 -1
- package/dist-esm/lib/mediaEncryption/capability.js +9 -0
- package/dist-esm/lib/mediaEncryption/capability.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/crypto.js +157 -0
- package/dist-esm/lib/mediaEncryption/crypto.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/format.js +157 -0
- package/dist-esm/lib/mediaEncryption/format.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/index.js +17 -0
- package/dist-esm/lib/mediaEncryption/index.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/inputKeys.js +94 -0
- package/dist-esm/lib/mediaEncryption/inputKeys.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/networks.js +17 -0
- package/dist-esm/lib/mediaEncryption/networks.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/recipient.js +100 -0
- package/dist-esm/lib/mediaEncryption/recipient.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/redact.js +31 -0
- package/dist-esm/lib/mediaEncryption/redact.js.map +1 -0
- package/dist-esm/lib/mediaEncryption/remote.js +240 -0
- package/dist-esm/lib/mediaEncryption/remote.js.map +1 -0
- package/dist-esm/lib/validation.js +99 -9
- package/dist-esm/lib/validation.js.map +1 -1
- package/dist-esm/types/ErrorData.js +14 -0
- package/dist-esm/types/ErrorData.js.map +1 -1
- package/dist-esm/version.js +1 -1
- package/llms-full.txt +73 -0
- package/llms.txt +7 -2
- package/package.json +15 -3
- package/src/Account/TwoFactorRequiredError.ts +12 -0
- package/src/Account/index.ts +183 -3
- package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.ts +9 -5
- package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +42 -4
- package/src/ApiClient/WebSocketClient/events.ts +27 -0
- package/src/ApiClient/WebSocketClient/index.ts +32 -1
- package/src/ApiClient/WebSocketClient/messages.ts +4 -0
- package/src/ApiClient/WebSocketClient/types.ts +4 -0
- package/src/ApiClient/index.ts +31 -1
- package/src/Chat/modelRouting.ts +9 -2
- package/src/MediaEncryption/index.ts +500 -0
- package/src/Projects/Job.ts +57 -4
- package/src/Projects/Project.ts +56 -2
- package/src/Projects/createJobRequestMessage.ts +16 -0
- package/src/Projects/index.ts +383 -31
- package/src/Projects/recovery.ts +4 -0
- package/src/Projects/types/JobProvenance.ts +2 -0
- package/src/Projects/types/PayAsYouGo.ts +162 -0
- package/src/Projects/types/RawProject.ts +2 -0
- package/src/Projects/types/events.ts +9 -1
- package/src/Projects/types/index.ts +143 -1
- package/src/Projects/utils/imageLayers.ts +131 -0
- package/src/browser/mediaEncryptionPlayback/encryptedMediaResponse.ts +88 -0
- package/src/browser/mediaEncryptionPlayback/encryptedMediaWorker.ts +103 -0
- package/src/browser/mediaEncryptionPlayback/encryptedPlayback.ts +166 -0
- package/src/browser/mediaEncryptionPlayback/index.ts +3 -0
- package/src/index.ts +91 -4
- package/src/lib/RestClient.ts +13 -0
- package/src/lib/mediaEncryption/capability.ts +17 -0
- package/src/lib/mediaEncryption/crypto.ts +217 -0
- package/src/lib/mediaEncryption/format.ts +209 -0
- package/src/lib/mediaEncryption/index.ts +43 -0
- package/src/lib/mediaEncryption/inputKeys.ts +130 -0
- package/src/lib/mediaEncryption/networks.ts +31 -0
- package/src/lib/mediaEncryption/recipient.ts +118 -0
- package/src/lib/mediaEncryption/redact.ts +30 -0
- package/src/lib/mediaEncryption/remote.ts +259 -0
- package/src/lib/validation.ts +106 -9
- package/src/types/ErrorData.ts +18 -0
- package/src/version.ts +1 -1
package/AGENTS.md
CHANGED
|
@@ -29,6 +29,7 @@ Current public API anchors:
|
|
|
29
29
|
- Project cost helpers are `sogni.projects.estimateCost()`, `estimateVideoCost()`, and `estimateAudioCost()`.
|
|
30
30
|
- `sogni.projects.assets` manages private subscriber uploads (`upload`, `list`, `remove`, `bind`). Supported servers automatically reuse matching files passed to `projects.create()`; saved IDs do not replace file parameters.
|
|
31
31
|
- `checkAuth()` is only for cookie-auth browser flows. API-key auth auto-authenticates during `createInstance()`, and token auth uses `login()` or `setTokens()`.
|
|
32
|
+
- Optional media encryption: `createInstance({ mediaEncryption: 'auto' })` encrypts eligible new projects once encryption is available for the account (`sogni.mediaEncryption.available`). Unset, nothing changes. Read results through `job.getResultData()` or `sogni.mediaEncryption.fetchDecrypted()`, which return the media either way. `declareMediaCapability: false` keeps encrypting but has result links serve the media itself.
|
|
32
33
|
- `ChatCompletionResult` is SDK-shaped (`content`, `role`, `finishReason`, `tool_calls`, `usage`, `cost`). Streaming chunks expose `chunk.content` and optional `chunk.tool_calls`.
|
|
33
34
|
|
|
34
35
|
## Public Release Security
|
|
@@ -72,7 +73,7 @@ Public chat and workflow media rules:
|
|
|
72
73
|
|
|
73
74
|
## Overview
|
|
74
75
|
|
|
75
|
-
This is the **Sogni SDK for JavaScript/Node.js** - a TypeScript client library for the Sogni Supernet, a DePIN protocol for creative AI inference. The SDK supports image generation (Stable Diffusion, Flux, Z-Image / Z-Image Turbo, Krea 2 Turbo, Krea 2 Identity Edit, Chroma v.46 Flash / v.48 Detail / Chroma1-HD, Qwen image-edit models, GPT Image 2 and 2.5, Seedream 5.0 Pro Uncensored, plus community fine-tunes such as Dark Beast Z-Image Turbo v9, Dark Beast KREA 2, Dark Beast Krea 2 Identity Edit, and One Obsession v22), video generation (WAN 2.2, Wan 3, LTX-2.3, Seedance 2.0 and 2.5, HappyHorse 1.1, MiniMax H3, and MiniMax H3 Turbo), promptless video upscaling (FlashVSR v1.1), audio generation (MiniMax Music 3 by default, ACE-Step 1.5), LLM chat with tool calling, hosted creative tools, durable creative workflows, replay records, and multimodal vision chat (Qwen3.6 35B VLM, default `qwen3.6-35b-a3b-gguf-iq4xs`). The model catalog is discovered dynamically at runtime (`sogni.projects.getAvailableModels()`); model ids listed here are illustrative.
|
|
76
|
+
This is the **Sogni SDK for JavaScript/Node.js** - a TypeScript client library for the Sogni Supernet, a DePIN protocol for creative AI inference. The SDK supports image generation (Stable Diffusion, Flux, Z-Image / Z-Image Turbo, Krea 2 Turbo, Krea 2 Identity Edit, Chroma v.46 Flash / v.48 Detail / Chroma1-HD, Qwen image-edit models, GPT Image 2 and 2.5, Seedream 5.0 Pro Uncensored and Seedream 5.5 Uncensored, plus community fine-tunes such as Dark Beast Z-Image Turbo v9, Dark Beast KREA 2, Dark Beast Krea 2 Identity Edit, and One Obsession v22), video generation (WAN 2.2, Wan 3, LTX-2.3, Seedance 2.0 and 2.5, HappyHorse 1.1, MiniMax H3, and MiniMax H3 Turbo), promptless video upscaling (FlashVSR v1.1), audio generation (MiniMax Music 3 by default, ACE-Step 1.5), LLM chat with tool calling, hosted creative tools, durable creative workflows, replay records, and multimodal vision chat (Qwen3.6 35B VLM, default `qwen3.6-35b-a3b-gguf-iq4xs`). The model catalog is discovered dynamically at runtime (`sogni.projects.getAvailableModels()`); model ids listed here are illustrative.
|
|
76
77
|
|
|
77
78
|
Choosing an image-edit model: pick by what the edit has to preserve, not by step count or quality tier. When a person or character must stay recognisable through the edit — style transfer, makeover, clothing or person swap, face swap, new pose or expression, character sheet — use Krea 2 Identity Edit (`krea2_identity_edit_v1_2`, or `dark_beast_krea2_identity_edit_v1_2` uncensored) with 1-2 context images. For general-purpose editing — photo transforms, in-image text, multi-person changes, combining up to 3 references — use a Qwen image-edit model. A higher-step general-purpose editor does not beat the identity model at a likeness task; it reinterprets the subject instead of preserving it. See `llms.txt` for parameters.
|
|
78
79
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# [5.82.0](https://github.com/Sogni-AI/sogni-client/compare/v5.81.0...v5.82.0) (2026-11-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **account:** add authenticator and passkey sign-in ([4420bb3](https://github.com/Sogni-AI/sogni-client/commit/4420bb3ef8c9f3669ade0480bb5cedbb2572d492))
|
|
7
|
+
* **media:** add optional media encryption ([ea7a618](https://github.com/Sogni-AI/sogni-client/commit/ea7a61882f2edc854a712b112ff30f91def701c0))
|
|
8
|
+
|
|
9
|
+
# [5.81.0](https://github.com/Sogni-AI/sogni-client/compare/v5.80.1...v5.81.0) (2026-11-13)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **projects:** name a switch request that never left the client ([6b85108](https://github.com/Sogni-AI/sogni-client/commit/6b8510839d6f6501db5fb6e8b2ead59cb7cfb21d))
|
|
15
|
+
* **projects:** report unknown switch outcomes instead of fake refusals ([736b0ad](https://github.com/Sogni-AI/sogni-client/commit/736b0ad56ddd46eb78d1941a67471ad255d662a8))
|
|
16
|
+
* **projects:** treat a not_found switch reply as an unknown outcome ([c1688f5](https://github.com/Sogni-AI/sogni-client/commit/c1688f5e89e2db9e5fd850825c81aacb2ce15f66))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **projects:** expose the pay-as-you-go offer and Premium Spark switch ([672376b](https://github.com/Sogni-AI/sogni-client/commit/672376b92070d15935d030e7360ca2ce4597d271))
|
|
22
|
+
* **projects:** support seedream layer extraction ([a575eb9](https://github.com/Sogni-AI/sogni-client/commit/a575eb9d028bbda2f46a2f04b01e790f75fc3bd7))
|
|
23
|
+
* **seedream:** add Seedream 5.5 transparency, layer options and larger sizes ([0977330](https://github.com/Sogni-AI/sogni-client/commit/0977330bcdf38985b604b971346286ddf8f428bd))
|
|
24
|
+
* **seedream:** recognise Seedream 5.5 Uncensored as a Seedream model ([5f6235f](https://github.com/Sogni-AI/sogni-client/commit/5f6235f932fb3af4569314fe718c8c1617db55a1))
|
|
25
|
+
|
|
1
26
|
## [5.80.1](https://github.com/Sogni-AI/sogni-client/compare/v5.80.0...v5.80.1) (2026-11-10)
|
|
2
27
|
|
|
3
28
|
|
package/README.md
CHANGED
|
@@ -135,6 +135,51 @@ await sogni.account.login('your-username', 'your-password');
|
|
|
135
135
|
const models = await sogni.projects.waitForModels();
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
+
#### Two-factor sign-in
|
|
139
|
+
|
|
140
|
+
When an account has enabled two-factor authentication, `login()` throws
|
|
141
|
+
`TwoFactorRequiredError` without starting a session. Ask the person for an
|
|
142
|
+
authenticator or backup code, then complete that challenge:
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
import { TwoFactorRequiredError } from '@sogni-ai/sogni-client';
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
await sogni.account.login(username, password, rememberMe);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (!(error instanceof TwoFactorRequiredError)) throw error;
|
|
151
|
+
const code = await askForAuthenticatorOrBackupCode(); // Your application's input UI
|
|
152
|
+
await sogni.account.verifyTwoFactorLogin(error, code);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Keep the challenge in memory and discard it when the person cancels. Do not log
|
|
157
|
+
or persist challenge tokens, authenticator setup keys, or backup codes.
|
|
158
|
+
The account API also provides `getTwoFactorStatus()`, `setupTwoFactor()`,
|
|
159
|
+
`confirmTwoFactorSetup()`, `disableTwoFactor()`, and
|
|
160
|
+
`regenerateTwoFactorBackupCodes()`. Setup and management require a password
|
|
161
|
+
session; API keys cannot manage two-factor settings.
|
|
162
|
+
|
|
163
|
+
Passkeys can complete the same pending sign-in from a browser. Trigger the device
|
|
164
|
+
prompt from a user gesture, such as a button click:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { startAuthentication } from '@simplewebauthn/browser';
|
|
168
|
+
|
|
169
|
+
const pending = await sogni.account.getTwoFactorPasskeyOptions(challenge);
|
|
170
|
+
const assertion = await startAuthentication({ optionsJSON: pending.options });
|
|
171
|
+
await sogni.account.verifyTwoFactorLogin(challenge, {
|
|
172
|
+
challengeId: pending.challengeId,
|
|
173
|
+
assertion
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Account security screens use `beginPasskeySetup` / `finishPasskeySetup`
|
|
178
|
+
and `removePasskey`. Save the first registration's backup codes before finishing.
|
|
179
|
+
Management accepts an authenticator/backup code or a passkey proof from
|
|
180
|
+
`getTwoFactorPasskeyOptions()` without a login challenge. Keep pending proofs
|
|
181
|
+
in memory. A second step adds to the Sogni password; it does not replace it.
|
|
182
|
+
|
|
138
183
|
#### Restoring a deleted account at sign-in
|
|
139
184
|
|
|
140
185
|
When someone signs in to an account they deleted and the account can be restored, `login()` throws
|
|
@@ -236,6 +281,35 @@ The same current fields are available on `Project.waitingReason`, `Project.jobWa
|
|
|
236
281
|
|
|
237
282
|
Set `socketEventSubscriptions: { projectQueue: false }` to opt out. A runtime subscription reset disables this optional stream; subscribe again with `{ projectQueue: true }` if needed.
|
|
238
283
|
|
|
284
|
+
#### Running a waiting plan project on Premium Spark
|
|
285
|
+
|
|
286
|
+
When an Unlimited plan project has waited a while on Fast and a card outside the plan's worker pool could start it now, supported servers add an optional offer to the same queue stream. `Project.payAsYouGo` and the `payAsYouGo` field of `queueChanged` hold `{ available: true, costInSpark, coveredByPremiumSpark }`, or `null` when nothing is offered. `costInSpark` is the project's normal Premium Spark price as a decimal string. `coveredByPremiumSpark` is advisory; the server decides when you ask. The offer clears when a result starts, the project ends, the connection drops, or the server stops sending it.
|
|
287
|
+
|
|
288
|
+
Nothing is charged until the owner asks:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const result = await sogni.projects.switchToPremiumSpark(projectId); // or project.switchToPremiumSpark()
|
|
292
|
+
if (result.status === 'switched') {
|
|
293
|
+
// The project now runs on Premium Spark; its price was charged once.
|
|
294
|
+
} else if (result.status === 'refused') {
|
|
295
|
+
// This request costs nothing. If the server had already started its debit
|
|
296
|
+
// (for example 'payment_failed', 'no_idle_worker' or 'started'), that debit
|
|
297
|
+
// is cancelled, and the balance can take a moment to show it, so tell the
|
|
298
|
+
// member they won't be charged rather than that they weren't.
|
|
299
|
+
// result.reason says why. 'started' and 'not_eligible' clear the offer; after other refusals, such as
|
|
300
|
+
// 'insufficient_premium_spark' (offer a Spark purchase, then ask again), the
|
|
301
|
+
// server's next queue update decides whether the offer stays.
|
|
302
|
+
} else {
|
|
303
|
+
// 'unknown' (result.reason: 'timeout', 'not_found', 'session_changed' or
|
|
304
|
+
// 'unrecognized_reply'): the project may have been switched and charged.
|
|
305
|
+
// Treat the payment as possibly made.
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Asking again is safe and never charges twice. It answers `switched` if the earlier request switched, a refusal from the server if it costs nothing, or `unknown` again, including `not_found` once the creation has finished. While the outcome stays unknown, check the member's Spark history or the creation's result rather than assuming either way. A `not_sent` refusal comes from the SDK itself: that request never left the client, so it says nothing about the earlier one; ask again once connected.
|
|
310
|
+
|
|
311
|
+
The server reads project ids of at most 128 characters, and API-key sessions are never offered the switch and are refused with `not_eligible`. Concurrent calls for one project share a single request. If the connection drops while a request is pending, the SDK sends it once more after reconnecting. `timeoutMs` (default 45 seconds) counts from when the request is sent. Servers without the feature never send an offer.
|
|
312
|
+
|
|
239
313
|
User-facing subscription limit notices are opt-in. Enable the event when a client needs live queue, concurrency, or fair-use messaging:
|
|
240
314
|
|
|
241
315
|
```typescript
|
|
@@ -610,7 +684,7 @@ Here is a full list of project parameters that you can use:
|
|
|
610
684
|
- `negativePrompt` - text prompt that describes what you don't want to see in the image. Can be an empty string.
|
|
611
685
|
- `stylePrompt` - text prompt that describes the style of the image. Can be an empty string.
|
|
612
686
|
- `numberOfImages` - number of images to generate.
|
|
613
|
-
- `tokenType` - select token type to pay for render. Can be either `sogni` or `spark`. External API-backed models such as GPT Image 2, Seedream 5.0 Pro Uncensored, and Seedance are Spark-only.
|
|
687
|
+
- `tokenType` - select token type to pay for render. Can be either `sogni` or `spark`. External API-backed models such as GPT Image 2, Seedream 5.0 Pro Uncensored, Seedream 5.5 Uncensored, and Seedance are Spark-only.
|
|
614
688
|
- `sizePreset` - optionally pass the ID of a size preset to use. If not passed, the default output is a square at
|
|
615
689
|
either 512x512, 768x768 or 1024x1024 (SDXL and Flux) based on the default resolution of the selected model.
|
|
616
690
|
See **Detecting available output presets** section below for available presets for your model. The token cost and
|
|
@@ -714,7 +788,61 @@ const project = await sogni.projects.create({
|
|
|
714
788
|
});
|
|
715
789
|
```
|
|
716
790
|
|
|
717
|
-
It shares the one-time likeness and consent agreement of Seedance 2.5 Uncensored: an account that has accepted it for Seedance can use Seedream, and until it is accepted in a Sogni app every Seedream job fails with `MODEL_CONSENT_REQUIRED_ERROR_CODE` (4103), whose error carries `consentRequired: { key: 'seedance-2-5-uncensored', version, modelId: 'seedream-5-0-pro-uncensored' }` and is detected by `isModelConsentRequiredError()`. `isSeedreamModel()` and `
|
|
791
|
+
It shares the one-time likeness and consent agreement of Seedance 2.5 Uncensored: an account that has accepted it for Seedance can use Seedream, and until it is accepted in a Sogni app every Seedream job fails with `MODEL_CONSENT_REQUIRED_ERROR_CODE` (4103), whose error carries `consentRequired: { key: 'seedance-2-5-uncensored', version, modelId: 'seedream-5-0-pro-uncensored' }` and is detected by `isModelConsentRequiredError()`. `isSeedreamModel()`, `SEEDREAM_5_PRO_UNCENSORED_MODEL_ID` and `SEEDREAM_5_5_UNCENSORED_MODEL_ID` are exported from the package root. Hosted chat tools (`generate_image`, `edit_image`) use it only when the call names it.
|
|
792
|
+
|
|
793
|
+
### Seedream 5.5 Uncensored
|
|
794
|
+
|
|
795
|
+
Seedream 5.5 Uncensored (`seedream-5-5-uncensored`) takes the same requests as 5.0 Pro: text-to-image or edits from 1-10 `contextImages`, Spark-only, no negative prompt, seed or steps, and the same one-time agreement. It is chosen only by name; `seedream-uncensored` and the other unversioned names still select 5.0 Pro. Custom sizes run from 921,600 to 4,624,220 pixels at an aspect ratio from 1:16 to 16:1. Its native sizes are:
|
|
796
|
+
|
|
797
|
+
- 1K: 1024x1024, 1152x864, 864x1152, 1424x800, 800x1424, 1248x832, 832x1248, 1568x672
|
|
798
|
+
- 1.5K: 1536x1536, 1792x1344, 1344x1792, 2048x1152, 1152x2048, 1872x1248, 1248x1872, 2352x1008
|
|
799
|
+
- 2K: 2048x2048, 2368x1776, 1776x2368, 2816x1584, 1584x2816, 2496x1664, 1664x2496, 3136x1344
|
|
800
|
+
|
|
801
|
+
`seedreamBackground` sets transparency on 5.5 only: `'opaque'` (the default) returns an RGB image, `'transparent'` an RGBA image, and `'auto'` lets the model decide from the prompt. Transparency works for text-to-image and for edits from up to 10 references, which need no alpha channel of their own. It needs PNG (the default) or WebP output, so `'transparent'` and `'auto'` refuse `outputFormat: 'jpg'`, and it cannot combine with layer extraction.
|
|
802
|
+
|
|
803
|
+
```javascript
|
|
804
|
+
const sticker = await sogni.projects.create({
|
|
805
|
+
type: 'image', network: 'fast', tokenType: 'spark',
|
|
806
|
+
modelId: 'seedream-5-5-uncensored',
|
|
807
|
+
positivePrompt: 'A glossy cherry sticker with a white die-cut border',
|
|
808
|
+
numberOfMedia: 1, width: 1536, height: 1536,
|
|
809
|
+
seedreamBackground: 'transparent'
|
|
810
|
+
});
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Seedream layer extraction
|
|
814
|
+
|
|
815
|
+
Both Seedream models can split one image into a base image and transparent PNG layers. Layer extraction is opt-in with `seedreamLayerDecomposition: true`, exactly one `contextImages` entry and `numberOfMedia: 1`. Choose `seedreamLayerSize: '1K' | '1.5K' | '2K'` (default `'1.5K'`); the source determines the aspect ratio. The prompt can be empty, which splits every major element, or name the parts to extract.
|
|
816
|
+
|
|
817
|
+
- Seedream 5.0 Pro Uncensored returns up to 16 layers. Its estimate reserves the maximum 17 returned images.
|
|
818
|
+
- Seedream 5.5 Uncensored returns up to 99 layers. `seedreamLayerMaxImages` caps the images returned, base included, at an integer from 2 to 100 (default 17), and its estimate reserves that many. `seedreamLayerTextRecognition: true` also reads the text of regular text layers.
|
|
819
|
+
|
|
820
|
+
The final charge uses the base image and layers actually returned. Pass the same layer options to `sogni.projects.estimateCost()` to quote a request. Both 5.5 options require `seedreamLayerDecomposition`, and 5.0 Pro refuses them.
|
|
821
|
+
|
|
822
|
+
```javascript
|
|
823
|
+
const split = await sogni.projects.create({
|
|
824
|
+
type: 'image', network: 'fast', tokenType: 'spark',
|
|
825
|
+
modelId: 'seedream-5-5-uncensored',
|
|
826
|
+
contextImages: [sourceImage], numberOfMedia: 1,
|
|
827
|
+
positivePrompt: '',
|
|
828
|
+
seedreamLayerDecomposition: true, seedreamLayerSize: '1.5K',
|
|
829
|
+
seedreamLayerMaxImages: 8, seedreamLayerTextRecognition: true
|
|
830
|
+
});
|
|
831
|
+
await split.waitForCompletion();
|
|
832
|
+
const job = split.jobs[0];
|
|
833
|
+
// job.resultUrl is the base. job.layers holds the transparent PNG layers,
|
|
834
|
+
// ordered by zIndex, with names, dimensions and absolute/normalized bounds.
|
|
835
|
+
for (const layer of job.layers ?? []) {
|
|
836
|
+
const freshLayerUrl = await job.getLayerUrl(layer.zIndex);
|
|
837
|
+
if (layer.textRecognition) console.log(layer.textRecognition.text);
|
|
838
|
+
}
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
Each `ImageLayer` has `url`, `width`, `height`, `zIndex` (1-99; the base is 0), `boundingBox: { absolute, normalized }` (`[left, top, right, bottom]` in base-image pixels and on a 0-1000 grid), and optional `name` and `description`. A layer image is rendered near the size tier, so it can be larger than its box: scale it to `right - left` by `bottom - top` before placing it at `left, top` on the base, stacking layers in `zIndex` order.
|
|
842
|
+
|
|
843
|
+
`layer.textRecognition` is present only on Seedream 5.5 layers the model classes as regular text, and only when text recognition was requested; artistic text, handwriting and other layers have none. Its shape is `{ text, lines: [{ boundingBox: { absolute, normalized }, runs: [{ text, style: { similarFontFamily, foregroundColor, bold, italic, underline, strikethrough, shadow, translucent } }] }] }`, where `text` is the layer's full text with lines separated by `\n`, `foregroundColor` is `#RRGGBB`, and `similarFontFamily` is the closest matching font or `'unknown'`.
|
|
844
|
+
|
|
845
|
+
Layer metadata also appears on completed job events and recovered projects. Layer URLs expire; `job.getLayerUrl(zIndex)` refreshes a layer URL after checking ownership. Omitting the extraction options preserves ordinary generation and editing.
|
|
718
846
|
|
|
719
847
|
### Detecting available output presets
|
|
720
848
|
|
|
@@ -980,6 +1108,67 @@ clients that manage project IDs and input slots directly.
|
|
|
980
1108
|
Project history may include `byolUsed`, `personalLoras` public-source snapshots,
|
|
981
1109
|
and `reusedAssetCount`. Missing fields on older projects mean unknown, not zero.
|
|
982
1110
|
|
|
1111
|
+
### Media encryption
|
|
1112
|
+
|
|
1113
|
+
The SDK offers optional encryption of project media for the signed-in account.
|
|
1114
|
+
Turn it on when creating the client:
|
|
1115
|
+
|
|
1116
|
+
```javascript
|
|
1117
|
+
const sogni = await SogniClient.createInstance({ appId, mediaEncryption: 'auto' });
|
|
1118
|
+
await sogni.account.login('username', 'password');
|
|
1119
|
+
|
|
1120
|
+
const project = await sogni.projects.create(params);
|
|
1121
|
+
await project.waitForCompletion();
|
|
1122
|
+
const blob = await project.jobs[0].getResultData(); // the media, with its real MIME type
|
|
1123
|
+
```
|
|
1124
|
+
|
|
1125
|
+
- Once media encryption is available for the account
|
|
1126
|
+
(`sogni.mediaEncryption.available`), every eligible new project is encrypted.
|
|
1127
|
+
Until then, and without the option, the client works exactly as before.
|
|
1128
|
+
- Read results with `job.getResultData()`, or
|
|
1129
|
+
`sogni.mediaEncryption.fetchDecrypted(url)` for result and preview URLs, rather
|
|
1130
|
+
than loading the URL in an `<img>` or `<video>` directly. Both return the
|
|
1131
|
+
media whether or not it was encrypted.
|
|
1132
|
+
- A project is sent unencrypted when encryption is not available for it: for the
|
|
1133
|
+
account at that moment, for its model (`projects.supportsMediaEncryption(modelId)`),
|
|
1134
|
+
or for its network (Fast only, for now), or when an input is `true` ("already
|
|
1135
|
+
uploaded"). `job.encrypted` and `project.encrypted` say which projects were
|
|
1136
|
+
sent encrypted.
|
|
1137
|
+
- Set `mediaEncryption` on a project to override the client: `false` sends it
|
|
1138
|
+
unencrypted, and `true` encrypts it or throws `MediaEncryptionError` before
|
|
1139
|
+
anything is uploaded. Saved uploads work for encrypted projects too.
|
|
1140
|
+
- Services that pass result links on to others can add
|
|
1141
|
+
`declareMediaCapability: false`: projects are still encrypted, and result,
|
|
1142
|
+
preview and download URLs serve the media itself.
|
|
1143
|
+
- `availabilityChanged` fires when `sogni.mediaEncryption.available` changes.
|
|
1144
|
+
Client-side failures throw `MediaEncryptionError` with a `code` such as
|
|
1145
|
+
`locked`, `unsupported`, `wrong_account_key` or `authentication_failed`.
|
|
1146
|
+
|
|
1147
|
+
For encrypted video and audio, `openDecrypted()` reads byte ranges without
|
|
1148
|
+
downloading the entire file. Offsets refer to the media itself and the end offset
|
|
1149
|
+
is exclusive. Use `stream()` for large reads and close the reader when finished;
|
|
1150
|
+
locking or changing accounts also aborts its outstanding requests.
|
|
1151
|
+
|
|
1152
|
+
```javascript
|
|
1153
|
+
const media = await sogni.mediaEncryption.openDecrypted(resultUrl);
|
|
1154
|
+
try {
|
|
1155
|
+
const header = await media.read(0, Math.min(1024, media.size));
|
|
1156
|
+
// media.contentType is the media's MIME type; media.stream() reads with backpressure.
|
|
1157
|
+
} finally {
|
|
1158
|
+
media.close();
|
|
1159
|
+
}
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
Browser apps can import `createEncryptedPlayback` and `serveEncryptedMedia` from
|
|
1163
|
+
`@sogni-ai/sogni-client/media-encryption-playback` to play encrypted video and
|
|
1164
|
+
audio through their own service worker. The worker must route
|
|
1165
|
+
`ENCRYPTED_MEDIA_PATH` requests with the requesting client's ID, and answer
|
|
1166
|
+
`SOGNI_ENCRYPTED_MEDIA_CLIENT` messages through their transferred port with
|
|
1167
|
+
`{ clientId: event.source.id }`. Pass the opened reader to
|
|
1168
|
+
`createEncryptedPlayback()`, use its returned `url` as the media element's
|
|
1169
|
+
source, and call `dispose()` when removing the element. The URL belongs to that
|
|
1170
|
+
tab. This requires an active service worker controlling the page.
|
|
1171
|
+
|
|
983
1172
|
### ControlNets
|
|
984
1173
|
|
|
985
1174
|
**EXPERIMENTAL FEATURE:** This feature is still in development and may not work as expected. Use at your own risk.
|
|
@@ -2006,6 +2195,7 @@ scheduler and dimension bounds. Both presets accept compatible Personal LoRAs.
|
|
|
2006
2195
|
| `qwen_image_edit_2511_fp8_lightning` | **Qwen Image Edit Lightning** - Fast 4-step editing | Rapid reference-based image generation |
|
|
2007
2196
|
| `qwen_image_edit_2511_fp8` | **Qwen Image Edit** - High quality 20-step editing | Professional image editing with context awareness |
|
|
2008
2197
|
| `seedream-5-0-pro-uncensored` | **Seedream 5.0 Pro Uncensored** - ByteDance, external API | Text-to-image and edits from 1-10 reference images; accept the Seedance 2.5 Uncensored agreement first (error 4103 until then) |
|
|
2198
|
+
| `seedream-5-5-uncensored` | **Seedream 5.5 Uncensored** - ByteDance, external API | Text-to-image and edits from 1-10 reference images up to 4,624,220 pixels, transparent backgrounds, up to 99 layers; same agreement |
|
|
2009
2199
|
| `wan_v2.2-14b-fp8_t2v_lightx2v` | **Wan 2.2 T2V** - Text-to-video | Generate videos from text prompts |
|
|
2010
2200
|
| `seedance-2-0` | **Seedance 2.0** - 4K external API multimodal video | Full Seedance 2.0 24fps video generation with optional image, video, and audio context |
|
|
2011
2201
|
| `seedance-2-0-mini` | **Seedance 2.0 Mini** - 720p external API video | Fastest, lower-cost 24fps Seedance video generation |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Sign-in needs an authenticator or backup code before a session can begin. */
|
|
2
|
+
export default class TwoFactorRequiredError extends Error {
|
|
3
|
+
readonly tempToken: string;
|
|
4
|
+
readonly walletAddress: string;
|
|
5
|
+
readonly username: string;
|
|
6
|
+
readonly name = "TwoFactorRequiredError";
|
|
7
|
+
constructor(tempToken: string, walletAddress: string, username: string);
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** Sign-in needs an authenticator or backup code before a session can begin. */
|
|
4
|
+
class TwoFactorRequiredError extends Error {
|
|
5
|
+
constructor(tempToken, walletAddress, username) {
|
|
6
|
+
super('Enter your authenticator code or a backup code to finish signing in.');
|
|
7
|
+
this.tempToken = tempToken;
|
|
8
|
+
this.walletAddress = walletAddress;
|
|
9
|
+
this.username = username;
|
|
10
|
+
this.name = 'TwoFactorRequiredError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = TwoFactorRequiredError;
|
|
14
|
+
//# sourceMappingURL=TwoFactorRequiredError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TwoFactorRequiredError.js","sourceRoot":"","sources":["../../src/Account/TwoFactorRequiredError.ts"],"names":[],"mappings":";;AAAA,gFAAgF;AAChF,MAAqB,sBAAuB,SAAQ,KAAK;IAGvD,YACkB,SAAiB,EACjB,aAAqB,EACrB,QAAgB;QAEhC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAJ9D,cAAS,GAAT,SAAS,CAAQ;QACjB,kBAAa,GAAb,aAAa,CAAQ;QACrB,aAAQ,GAAR,QAAQ,CAAQ;QALzB,SAAI,GAAG,wBAAwB,CAAC;IAQzC,CAAC;CACF;AAVD,yCAUC"}
|
package/dist/Account/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AuthenticationResponseJSON, RegistrationResponseJSON, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';
|
|
2
|
+
import TwoFactorRequiredError from './TwoFactorRequiredError.js';
|
|
1
3
|
import { AccountCreateData, AccountCreateParams, Balances, ClaimOptions, FullBalances, LoginData, LoginOptions, MeData, Reward, RewardsQuery, TxHistoryEntry, TxHistoryParams } from './types.js';
|
|
2
4
|
import { CreateSubscriptionCheckoutOptions, SubscriptionCheckoutResult, SubscriptionEntitlementSnapshot, SubscriptionPlanId, SubscriptionPlan, SubscriptionPortalSession, SubscriptionTerm, SubscriptionUsage, TrialEligibility } from './subscription.types.js';
|
|
3
5
|
import ApiGroup, { ApiConfig } from '../ApiGroup.js';
|
|
@@ -16,6 +18,22 @@ import { SupernetType } from '../ApiClient/WebSocketClient/types.js';
|
|
|
16
18
|
* ```
|
|
17
19
|
*
|
|
18
20
|
*/
|
|
21
|
+
export type TwoFactorProof = {
|
|
22
|
+
code: string;
|
|
23
|
+
} | {
|
|
24
|
+
assertion: AuthenticationResponseJSON;
|
|
25
|
+
challengeId: string;
|
|
26
|
+
};
|
|
27
|
+
export interface TwoFactorStatus {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
backupCodesRemaining: number;
|
|
30
|
+
canManage: boolean;
|
|
31
|
+
authenticatorEnabled: boolean;
|
|
32
|
+
passkeys: {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}[];
|
|
36
|
+
}
|
|
19
37
|
declare class AccountApi extends ApiGroup {
|
|
20
38
|
readonly currentAccount: CurrentAccount;
|
|
21
39
|
/**
|
|
@@ -139,6 +157,31 @@ declare class AccountApi extends ApiGroup {
|
|
|
139
157
|
* seconds).
|
|
140
158
|
*/
|
|
141
159
|
login(username: string, password: string, rememberMe?: boolean, appSource?: string, options?: LoginOptions): Promise<LoginData>;
|
|
160
|
+
private acceptLogin;
|
|
161
|
+
/** Complete the sign-in requested by a TwoFactorRequiredError. Keep the challenge in memory. */
|
|
162
|
+
verifyTwoFactorLogin(challenge: TwoFactorRequiredError, proof: string | TwoFactorProof): Promise<LoginData>;
|
|
163
|
+
getTwoFactorStatus(): Promise<TwoFactorStatus>;
|
|
164
|
+
getTwoFactorPasskeyOptions(challenge?: TwoFactorRequiredError): Promise<{
|
|
165
|
+
challengeId: string;
|
|
166
|
+
options: PublicKeyCredentialRequestOptionsJSON;
|
|
167
|
+
}>;
|
|
168
|
+
beginPasskeySetup(username: string, password: string, name: string, proof?: TwoFactorProof): Promise<{
|
|
169
|
+
setupId: string;
|
|
170
|
+
options: PublicKeyCredentialCreationOptionsJSON;
|
|
171
|
+
backupCodes?: string[];
|
|
172
|
+
}>;
|
|
173
|
+
finishPasskeySetup(setupId: string, response: RegistrationResponseJSON): Promise<void>;
|
|
174
|
+
removePasskey(username: string, password: string, credentialId: string, proof: string | TwoFactorProof): Promise<void>;
|
|
175
|
+
private twoFactorSignature;
|
|
176
|
+
setupTwoFactor(username: string, password: string, proof?: TwoFactorProof): Promise<{
|
|
177
|
+
setupId: string;
|
|
178
|
+
secret: string;
|
|
179
|
+
qrData: string;
|
|
180
|
+
backupCodes: string[];
|
|
181
|
+
}>;
|
|
182
|
+
confirmTwoFactorSetup(setupId: string, code: string): Promise<void>;
|
|
183
|
+
disableTwoFactor(username: string, password: string, proof: string | TwoFactorProof): Promise<void>;
|
|
184
|
+
regenerateTwoFactorBackupCodes(username: string, password: string, proof: string | TwoFactorProof): Promise<string[]>;
|
|
142
185
|
/**
|
|
143
186
|
* Logout the user and close the WebSocket connection.
|
|
144
187
|
*
|
package/dist/Account/index.js
CHANGED
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const TwoFactorRequiredError_js_1 = __importDefault(require("./TwoFactorRequiredError.js"));
|
|
15
16
|
const ApiGroup_js_1 = __importDefault(require("../ApiGroup.js"));
|
|
16
17
|
const requestSession_js_1 = require("../lib/requestSession.js");
|
|
17
18
|
const ethers_1 = require("ethers");
|
|
@@ -43,17 +44,9 @@ function parseSubscriptionVersion(version) {
|
|
|
43
44
|
}
|
|
44
45
|
return null;
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
*
|
|
50
|
-
* @example Retrieve the current account balance
|
|
51
|
-
* ```typescript
|
|
52
|
-
* const balance = await sogni.account.refreshBalance();
|
|
53
|
-
* console.log(balance);
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
*/
|
|
47
|
+
function factorProof(value) {
|
|
48
|
+
return typeof value === 'string' ? { code: value.trim().toUpperCase() } : value;
|
|
49
|
+
}
|
|
57
50
|
class AccountApi extends ApiGroup_js_1.default {
|
|
58
51
|
constructor(config) {
|
|
59
52
|
super(config);
|
|
@@ -445,17 +438,108 @@ class AccountApi extends ApiGroup_js_1.default {
|
|
|
445
438
|
});
|
|
446
439
|
const resolvedAppSource = (appSource === null || appSource === void 0 ? void 0 : appSource.trim()) || this.client.appSource;
|
|
447
440
|
const res = yield this.client.rest.post('/v1/account/login', Object.assign(Object.assign(Object.assign({ walletAddress: wallet.address, signature }, (resolvedAppSource ? { appSource: resolvedAppSource } : {})), { rememberMe }), ((options === null || options === void 0 ? void 0 : options.restoreDeletedAccount) ? { restoreDeletedAccount: true } : {})));
|
|
441
|
+
if (res.data.requires2FA) {
|
|
442
|
+
if (!res.data.tempToken)
|
|
443
|
+
throw new Error('Unable to start verification. Please sign in again.');
|
|
444
|
+
throw new TwoFactorRequiredError_js_1.default(res.data.tempToken, wallet.address, res.data.username);
|
|
445
|
+
}
|
|
446
|
+
yield this.acceptLogin(res.data, wallet.address);
|
|
447
|
+
return res.data;
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
acceptLogin(data, walletAddress) {
|
|
451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
448
452
|
const auth = this.client.auth;
|
|
449
453
|
if (auth instanceof index_js_3.TokenAuthManager) {
|
|
450
|
-
yield auth.authenticate({ refreshToken:
|
|
454
|
+
yield auth.authenticate({ refreshToken: data.refreshToken, token: data.token });
|
|
451
455
|
}
|
|
452
456
|
else if (auth instanceof index_js_3.CookieAuthManager) {
|
|
453
|
-
auth._setSessionIdentity(
|
|
457
|
+
auth._setSessionIdentity(walletAddress.toLowerCase());
|
|
454
458
|
yield auth.authenticate();
|
|
455
459
|
}
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/** Complete the sign-in requested by a TwoFactorRequiredError. Keep the challenge in memory. */
|
|
463
|
+
verifyTwoFactorLogin(challenge, proof) {
|
|
464
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
465
|
+
const res = yield this.client.rest.post('/v1/account/2fa/verify-login', Object.assign({ tempToken: challenge.tempToken }, factorProof(proof)));
|
|
466
|
+
yield this.acceptLogin(res.data, challenge.walletAddress);
|
|
467
|
+
return Object.assign(Object.assign({}, res.data), { username: challenge.username });
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
getTwoFactorStatus() {
|
|
471
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
472
|
+
const res = yield this.client.rest.get('/v1/account/2fa/status');
|
|
456
473
|
return res.data;
|
|
457
474
|
});
|
|
458
475
|
}
|
|
476
|
+
getTwoFactorPasskeyOptions(challenge) {
|
|
477
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
478
|
+
const res = yield this.client.rest.post(challenge
|
|
479
|
+
? '/v1/account/2fa/passkeys/login-options'
|
|
480
|
+
: '/v1/account/2fa/passkeys/authentication-options', challenge ? { tempToken: challenge.tempToken } : {});
|
|
481
|
+
return res.data;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
beginPasskeySetup(username, password, name, proof) {
|
|
485
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
486
|
+
const signature = yield this.twoFactorSignature(username, password);
|
|
487
|
+
const res = yield this.client.rest.post('/v1/account/2fa/passkeys/registration-options', Object.assign({ signature,
|
|
488
|
+
name }, (proof ? { proof } : {})));
|
|
489
|
+
return res.data;
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
finishPasskeySetup(setupId, response) {
|
|
493
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
494
|
+
yield this.client.rest.post('/v1/account/2fa/passkeys/register', { setupId, response });
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
removePasskey(username, password, credentialId, proof) {
|
|
498
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
499
|
+
const signature = yield this.twoFactorSignature(username, password);
|
|
500
|
+
yield this.client.rest.post('/v1/account/2fa/passkeys/remove', Object.assign({ signature,
|
|
501
|
+
credentialId }, factorProof(proof)));
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
twoFactorSignature(username, password) {
|
|
505
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
506
|
+
var _a;
|
|
507
|
+
const wallet = this.getWallet(username, password);
|
|
508
|
+
if (wallet.address.toLowerCase() !== ((_a = this.currentAccount.walletAddress) === null || _a === void 0 ? void 0 : _a.toLowerCase())) {
|
|
509
|
+
throw new Error('Incorrect password. Please try again.');
|
|
510
|
+
}
|
|
511
|
+
const nonce = yield this.getNonce(wallet.address);
|
|
512
|
+
return this.eip712.signTypedData(wallet, 'authentication', {
|
|
513
|
+
walletAddress: wallet.address,
|
|
514
|
+
nonce
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
setupTwoFactor(username, password, proof) {
|
|
519
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
520
|
+
const signature = yield this.twoFactorSignature(username, password);
|
|
521
|
+
const res = yield this.client.rest.post('/v1/account/2fa/setup', Object.assign({ signature }, (proof ? { proof } : {})));
|
|
522
|
+
return res.data;
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
confirmTwoFactorSetup(setupId, code) {
|
|
526
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
527
|
+
yield this.client.rest.post('/v1/account/2fa/verify-setup', { setupId, code: code.trim() });
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
disableTwoFactor(username, password, proof) {
|
|
531
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
532
|
+
const signature = yield this.twoFactorSignature(username, password);
|
|
533
|
+
yield this.client.rest.post('/v1/account/2fa/disable', Object.assign({ signature }, factorProof(proof)));
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
regenerateTwoFactorBackupCodes(username, password, proof) {
|
|
537
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
538
|
+
const signature = yield this.twoFactorSignature(username, password);
|
|
539
|
+
const res = yield this.client.rest.post('/v1/account/2fa/backup-codes', Object.assign({ signature }, factorProof(proof)));
|
|
540
|
+
return res.data.backupCodes;
|
|
541
|
+
});
|
|
542
|
+
}
|
|
459
543
|
/**
|
|
460
544
|
* Logout the user and close the WebSocket connection.
|
|
461
545
|
*
|