@sogni-ai/sogni-client 5.0.0 → 5.1.0-alpha.10

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 (130) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +42 -0
  3. package/dist/Account/CurrentAccount.d.ts +30 -0
  4. package/dist/Account/CurrentAccount.js +27 -1
  5. package/dist/Account/CurrentAccount.js.map +1 -1
  6. package/dist/Account/index.d.ts +171 -0
  7. package/dist/Account/index.js +362 -1
  8. package/dist/Account/index.js.map +1 -1
  9. package/dist/Account/subscription.types.d.ts +249 -0
  10. package/dist/Account/subscription.types.js +9 -0
  11. package/dist/Account/subscription.types.js.map +1 -0
  12. package/dist/Account/types.d.ts +12 -0
  13. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +1 -0
  14. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +19 -0
  15. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
  16. package/dist/ApiClient/WebSocketClient/events.d.ts +74 -0
  17. package/dist/Chat/ChatJobError.d.ts +111 -0
  18. package/dist/Chat/ChatJobError.js +116 -0
  19. package/dist/Chat/ChatJobError.js.map +1 -0
  20. package/dist/Chat/ChatTools.js +1 -4
  21. package/dist/Chat/ChatTools.js.map +1 -1
  22. package/dist/Chat/_hostedToolsManifest.generated.js +5 -3
  23. package/dist/Chat/_hostedToolsManifest.generated.js.map +1 -1
  24. package/dist/Chat/hostedToolValidator.js +4 -3
  25. package/dist/Chat/hostedToolValidator.js.map +1 -1
  26. package/dist/Chat/index.d.ts +5 -0
  27. package/dist/Chat/index.js +99 -13
  28. package/dist/Chat/index.js.map +1 -1
  29. package/dist/Chat/modelRouting.d.ts +2 -0
  30. package/dist/Chat/modelRouting.js +2 -7
  31. package/dist/Chat/modelRouting.js.map +1 -1
  32. package/dist/Chat/tools.d.ts +14 -11
  33. package/dist/Chat/tools.js +15 -13
  34. package/dist/Chat/tools.js.map +1 -1
  35. package/dist/Chat/types.d.ts +18 -0
  36. package/dist/CreativeWorkflows/Templates/index.js +4 -2
  37. package/dist/CreativeWorkflows/Templates/index.js.map +1 -1
  38. package/dist/Projects/createJobRequestMessage.js +8 -1
  39. package/dist/Projects/createJobRequestMessage.js.map +1 -1
  40. package/dist/Projects/index.d.ts +5 -0
  41. package/dist/Projects/index.js +47 -0
  42. package/dist/Projects/index.js.map +1 -1
  43. package/dist/Projects/types/ControlNetParams.d.ts +3 -1
  44. package/dist/Projects/types/index.d.ts +22 -2
  45. package/dist/Projects/types/index.js.map +1 -1
  46. package/dist/Projects/utils/index.js +16 -8
  47. package/dist/Projects/utils/index.js.map +1 -1
  48. package/dist/Replay/index.js +5 -4
  49. package/dist/Replay/index.js.map +1 -1
  50. package/dist/index.d.ts +9 -5
  51. package/dist/index.js +8 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/lib/isSubscriptionLimitError.d.ts +16 -0
  54. package/dist/lib/isSubscriptionLimitError.js +36 -0
  55. package/dist/lib/isSubscriptionLimitError.js.map +1 -0
  56. package/dist/types/ErrorData.d.ts +53 -0
  57. package/dist/types/ErrorData.js +25 -0
  58. package/dist/types/ErrorData.js.map +1 -1
  59. package/dist/version.d.ts +1 -1
  60. package/dist/version.js +1 -1
  61. package/dist/version.js.map +1 -1
  62. package/dist-esm/Account/CurrentAccount.js +27 -1
  63. package/dist-esm/Account/CurrentAccount.js.map +1 -1
  64. package/dist-esm/Account/index.js +362 -1
  65. package/dist-esm/Account/index.js.map +1 -1
  66. package/dist-esm/Account/subscription.types.js +8 -0
  67. package/dist-esm/Account/subscription.types.js.map +1 -0
  68. package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +19 -0
  69. package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
  70. package/dist-esm/Chat/ChatJobError.js +111 -0
  71. package/dist-esm/Chat/ChatJobError.js.map +1 -0
  72. package/dist-esm/Chat/ChatTools.js +1 -4
  73. package/dist-esm/Chat/ChatTools.js.map +1 -1
  74. package/dist-esm/Chat/_hostedToolsManifest.generated.js +5 -3
  75. package/dist-esm/Chat/_hostedToolsManifest.generated.js.map +1 -1
  76. package/dist-esm/Chat/hostedToolValidator.js +4 -3
  77. package/dist-esm/Chat/hostedToolValidator.js.map +1 -1
  78. package/dist-esm/Chat/index.js +66 -13
  79. package/dist-esm/Chat/index.js.map +1 -1
  80. package/dist-esm/Chat/modelRouting.js +2 -7
  81. package/dist-esm/Chat/modelRouting.js.map +1 -1
  82. package/dist-esm/Chat/tools.js +15 -13
  83. package/dist-esm/Chat/tools.js.map +1 -1
  84. package/dist-esm/CreativeWorkflows/Templates/index.js +4 -2
  85. package/dist-esm/CreativeWorkflows/Templates/index.js.map +1 -1
  86. package/dist-esm/Projects/createJobRequestMessage.js +8 -1
  87. package/dist-esm/Projects/createJobRequestMessage.js.map +1 -1
  88. package/dist-esm/Projects/index.js +47 -0
  89. package/dist-esm/Projects/index.js.map +1 -1
  90. package/dist-esm/Projects/types/index.js.map +1 -1
  91. package/dist-esm/Projects/utils/index.js +16 -8
  92. package/dist-esm/Projects/utils/index.js.map +1 -1
  93. package/dist-esm/Replay/index.js +5 -4
  94. package/dist-esm/Replay/index.js.map +1 -1
  95. package/dist-esm/index.js +5 -1
  96. package/dist-esm/index.js.map +1 -1
  97. package/dist-esm/lib/isSubscriptionLimitError.js +33 -0
  98. package/dist-esm/lib/isSubscriptionLimitError.js.map +1 -0
  99. package/dist-esm/types/ErrorData.js +24 -1
  100. package/dist-esm/types/ErrorData.js.map +1 -1
  101. package/dist-esm/version.js +1 -1
  102. package/dist-esm/version.js.map +1 -1
  103. package/llms-full.txt +87 -9
  104. package/llms.txt +42 -8
  105. package/package.json +2 -1
  106. package/src/Account/CurrentAccount.ts +40 -1
  107. package/src/Account/index.ts +442 -2
  108. package/src/Account/subscription.types.ts +281 -0
  109. package/src/Account/types.ts +18 -0
  110. package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +18 -0
  111. package/src/ApiClient/WebSocketClient/events.ts +75 -0
  112. package/src/Chat/ChatJobError.ts +188 -0
  113. package/src/Chat/ChatTools.ts +1 -4
  114. package/src/Chat/_hostedToolsManifest.generated.ts +5 -3
  115. package/src/Chat/hostedToolValidator.ts +7 -4
  116. package/src/Chat/index.ts +110 -35
  117. package/src/Chat/modelRouting.ts +2 -8
  118. package/src/Chat/tools.ts +22 -17
  119. package/src/Chat/types.ts +19 -0
  120. package/src/CreativeWorkflows/Templates/index.ts +6 -2
  121. package/src/Projects/createJobRequestMessage.ts +9 -0
  122. package/src/Projects/index.ts +42 -0
  123. package/src/Projects/types/ControlNetParams.ts +3 -1
  124. package/src/Projects/types/index.ts +24 -2
  125. package/src/Projects/utils/index.ts +16 -8
  126. package/src/Replay/index.ts +9 -21
  127. package/src/index.ts +44 -2
  128. package/src/lib/isSubscriptionLimitError.ts +36 -0
  129. package/src/types/ErrorData.ts +57 -0
  130. package/src/version.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,99 @@
1
+ # [5.1.0-alpha.10](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.9...v5.1.0-alpha.10) (2026-06-18)
2
+
3
+
4
+ ### Features
5
+
6
+ * **audio:** prefer ACE-Step XL music models ([ec5a715](https://github.com/Sogni-AI/sogni-client/commit/ec5a71579d04b42863ce9627c8ea4935b0190f70))
7
+ * **projects:** expose LTX-2.3 v2v outpaint and inpaint controls ([1a60576](https://github.com/Sogni-AI/sogni-client/commit/1a605766e42b6fa5cdedf0a64425deb51cbf81b1))
8
+
9
+ # [5.1.0-alpha.9](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.8...v5.1.0-alpha.9) (2026-06-16)
10
+
11
+
12
+ ### Features
13
+
14
+ * **subscription:** expose frontier vendor discount in types ([1e06f99](https://github.com/Sogni-AI/sogni-client/commit/1e06f99e54e39c2d09d65263c0ed6a5f52dbac18))
15
+
16
+ # [5.1.0-alpha.8](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.7...v5.1.0-alpha.8) (2026-06-16)
17
+
18
+
19
+ ### Features
20
+
21
+ * **chat:** carry subscription-limit fields on ChatJobError ([33c7ecd](https://github.com/Sogni-AI/sogni-client/commit/33c7ecdab22c571f6983fbb479bdbb5eb885a672))
22
+ * **chat:** forward 4081 limit fields at error call sites ([ef5b66a](https://github.com/Sogni-AI/sogni-client/commit/ef5b66a8b28dd52755f22cf76609258ecf2fe6dc))
23
+ * **projects:** surface 4081 limit fields on render errors ([13fa158](https://github.com/Sogni-AI/sogni-client/commit/13fa158f00c4e4415bb4d0f3c7eaf9979f1f7d40))
24
+ * **socket:** type 4081 limit fields on job error events ([0026438](https://github.com/Sogni-AI/sogni-client/commit/0026438ccbfb1cefe5be38861372d1430ade0eb2))
25
+ * **subscription:** add isSubscriptionLimitError helper ([139953b](https://github.com/Sogni-AI/sogni-client/commit/139953bc003aefc2f3ba09f8e4000982a071f7e8))
26
+ * **subscription:** recognize 4081 feature-gate denial code ([c513fe6](https://github.com/Sogni-AI/sogni-client/commit/c513fe67243c91e0ca8ccb5d301a3be20dcf1486))
27
+
28
+ # [5.1.0-alpha.7](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.6...v5.1.0-alpha.7) (2026-06-12)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **account:** map real socket entitlement status domain without dropping fields ([c2e7499](https://github.com/Sogni-AI/sogni-client/commit/c2e7499c5d254e8ce61da257b44307bca97ea56c))
34
+
35
+
36
+ ### Features
37
+
38
+ * **account:** accept chat checkout redirect target ([3900336](https://github.com/Sogni-AI/sogni-client/commit/390033692aaa46eff521030d80ba712f15bd3302))
39
+ * **account:** guard subscription writes against stale transports ([c60af1f](https://github.com/Sogni-AI/sogni-client/commit/c60af1ff4e4a9a8af1a8e2393899026f176a3f53))
40
+ * **chat:** preserve job error codes via typed ChatJobError ([dd5ad1d](https://github.com/Sogni-AI/sogni-client/commit/dd5ad1d585c709382547bfa4cff2aa98d734414c))
41
+ * **chat:** serialize billingMode on all three chat transports ([787dd43](https://github.com/Sogni-AI/sogni-client/commit/787dd4391dee1735a6d3d3a7953f25ec6c722a4d))
42
+ * **types:** export subscription billing socket error-code constants ([2fd5af4](https://github.com/Sogni-AI/sogni-client/commit/2fd5af49ffa76d6f1a304c6a06577468f5865c2e))
43
+
44
+ # [5.1.0-alpha.6](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.5...v5.1.0-alpha.6) (2026-06-12)
45
+
46
+
47
+ ### Features
48
+
49
+ * sync socket subscription entitlement ([fa5d24d](https://github.com/Sogni-AI/sogni-client/commit/fa5d24d307992993ac312c3b1e8ab94277529aa4))
50
+
51
+ # [5.1.0-alpha.5](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.4...v5.1.0-alpha.5) (2026-06-11)
52
+
53
+
54
+ ### Features
55
+
56
+ * **subscription:** pending plan-change snapshot fields and grace-period doc fix ([596e4a0](https://github.com/Sogni-AI/sogni-client/commit/596e4a030dc1114e5fdd90d3dce3dd799c5f1ede))
57
+
58
+ # [5.1.0-alpha.4](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.3...v5.1.0-alpha.4) (2026-06-11)
59
+
60
+
61
+ ### Bug Fixes
62
+
63
+ * **projects:** forward billing mode metadata ([975fdb0](https://github.com/Sogni-AI/sogni-client/commit/975fdb09adcbd74c11fa6786edb6f1d2392583eb))
64
+
65
+ # [5.1.0-alpha.3](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.2...v5.1.0-alpha.3) (2026-06-10)
66
+
67
+
68
+ ### Features
69
+
70
+ * **subscription:** mirror term, google productId, and manual provider ([78b3114](https://github.com/Sogni-AI/sogni-client/commit/78b311457c71448578b8f561cc7865e7bcaf9f20))
71
+
72
+ # [5.1.0-alpha.2](https://github.com/Sogni-AI/sogni-client/compare/v5.1.0-alpha.1...v5.1.0-alpha.2) (2026-06-10)
73
+
74
+
75
+ ### Bug Fixes
76
+
77
+ * **account:** correct trial usage SDK surface and eligibility reason docs ([222252d](https://github.com/Sogni-AI/sogni-client/commit/222252d87305f72b0be71f23b26a6607ad25bf46))
78
+
79
+
80
+ ### Features
81
+
82
+ * **account:** add trial eligibility, device-id, and startTrial checkout ([6564c82](https://github.com/Sogni-AI/sogni-client/commit/6564c8225aec37245a4c4a051119a48da6fc14a5))
83
+
84
+ # [5.1.0-alpha.1](https://github.com/Sogni-AI/sogni-client/compare/v5.0.0...v5.1.0-alpha.1) (2026-06-05)
85
+
86
+
87
+ ### Bug Fixes
88
+
89
+ * **subscription:** accept unlimited_pro tier in isUnlimited getter ([dd60513](https://github.com/Sogni-AI/sogni-client/commit/dd60513650071a46a2e43f7d81bae96026c4af93))
90
+ * **subscription:** align entitlement SDK surface ([df2b752](https://github.com/Sogni-AI/sogni-client/commit/df2b7527f479778f073ac8f05b39912e84874666))
91
+
92
+
93
+ ### Features
94
+
95
+ * **account:** add subscription entitlement accessors ([22682c4](https://github.com/Sogni-AI/sogni-client/commit/22682c4ac8a970b4189ec94ea9f7bc3fa215533e))
96
+
1
97
  # [5.0.0](https://github.com/Sogni-AI/sogni-client/compare/v4.1.1...v5.0.0) (2026-05-29)
2
98
 
3
99
 
package/README.md CHANGED
@@ -176,6 +176,48 @@ sogni.client.on('disconnected', ({ code, reason }) => {
176
176
  });
177
177
  ```
178
178
 
179
+ ### Subscription entitlements
180
+
181
+ The account API exposes the public subscription plan catalog and the current wallet's entitlement snapshot:
182
+
183
+ ```typescript
184
+ const plans = await sogni.account.getSubscriptionPlans();
185
+
186
+ const subscription = await sogni.account.refreshSubscription();
187
+ if (sogni.account.currentAccount.isUnlimited) {
188
+ console.log('Unlimited tier:', subscription.tier);
189
+ }
190
+ ```
191
+
192
+ `currentAccount.isUnlimited` is `true` when the latest entitlement snapshot has `active: true` and `tier` is either `unlimited` or `unlimited_pro`. The server keeps `active` true for entitled states until access actually ends: trials and cancel-at-period-end windows remain entitled, with `currentPeriodEnd` reflecting the paid-through date. Canceling during a free trial is the exception: it ends Unlimited access immediately by default, so the next snapshot reports `active: false`. A `grace_period` snapshot is never entitled and returns `active: false`: it means the provider (Apple billing grace / Google Play grace / Stripe retries) is retrying the renewal payment, and unlimited render access is paused while the retry is in progress — render submissions under the plan return a specific error from the platform explaining that the renewal payment is being retried and that unlimited access resumes once it succeeds. Renders can still be paid with Spark/SOGNI in the meantime, and unlimited access resumes automatically when the renewal succeeds. During grace the snapshot's effective period end indicates the payment-retry window, not access. Period dates are ISO timestamp strings.
193
+
194
+ A canceled-but-still-paid subscription carries `cancelAtPeriodEnd: true` and keeps access until `currentPeriodEnd`. When a downgrade or plan switch is scheduled for the next renewal, the snapshot may also carry `scheduledTier`, `scheduledTerm`, and `scheduledChangeAt` (ISO timestamp) — absent when no change is pending — so UIs can render "Your plan will change to X on date" messaging while the current tier keeps its benefits.
195
+
196
+ When a job is explicitly submitted with `billingMode: 'subscription'` and the subscription cannot cover it, the platform rejects the job with a subscription-specific error code, exported as `SUBSCRIPTION_ERROR_CODES` from the package root:
197
+
198
+ - `4078` (`NOT_ENTITLED`) — no active subscription entitlement covers the job.
199
+ - `4079` (`QUEUE_CAP`) — the subscription's concurrent job queue cap was reached.
200
+ - `4080` (`GRACE_RETRY`) — the subscription is in its billing-grace window: the renewal payment is being retried and unlimited access is paused until it succeeds. On `4080`, offer the user a "pay with Spark/SOGNI" fallback (token billing) instead of auto-retrying the subscription job in a loop — it will keep failing until the renewal succeeds.
201
+
202
+ `billingMode` (`'auto' | 'subscription' | 'tokens'`, exported as `BillingMode`) is accepted by project params and by all three chat transports: `sogni.chat.completions.create()` (socket), `sogni.chat.hosted.create()` (REST `/v1/chat/completions`), and `sogni.chat.runs.create()` (durable runs, where it serializes as `billing_mode`).
203
+
204
+ Chat job failures preserve this error contract. Streamed and non-streaming chat completions, hosted REST chat, and durable chat runs fail with a `ChatJobError` (exported from the package root): `.message` stays the human-readable server message, while `code`/`errorCode` carry the wire code string (e.g. `'4080'`), `errorType` carries the server's tag (e.g. `'subscription_unavailable'`), and the `subscriptionErrorCode` getter maps the code back to the numeric `SUBSCRIPTION_ERROR_CODES` value when applicable — so apps can branch without string-matching.
205
+
206
+ Unlimited fair-use accounting and enforcement are handled dynamically by the Sogni socket service. The SDK does not expose per-period usage counters or plan limit tables for clients to store or display as durable user-facing limits.
207
+
208
+ To start Stripe checkout, use a plan's `planId` (`unlimited` or `unlimited_pro`) and `term` (`monthly` or `annual`). Checkout and portal sessions require user authentication; API-key auth is rejected for those browser redirect operations.
209
+
210
+ ```typescript
211
+ const { url } = await sogni.account.createSubscriptionCheckout('unlimited_pro', 'annual', {
212
+ redirectType: 'web',
213
+ appSource: 'my-integration'
214
+ });
215
+ window.location.href = url;
216
+
217
+ const portal = await sogni.account.createSubscriptionPortalSession();
218
+ window.location.href = portal.url;
219
+ ```
220
+
179
221
  ## Image Generation
180
222
 
181
223
  Sogni supports a wide range of models for image generation. You can find a list of available models in
@@ -1,5 +1,6 @@
1
1
  import DataEntity from '../lib/DataEntity.js';
2
2
  import { Balances } from './types.js';
3
+ import { SubscriptionEntitlementSnapshot } from './subscription.types.js';
3
4
  import { SupernetType } from '../ApiClient/WebSocketClient/types.js';
4
5
  /**
5
6
  * @inline
@@ -20,6 +21,17 @@ export interface AccountData {
20
21
  walletAddress?: string;
21
22
  username?: string;
22
23
  email?: string;
24
+ /**
25
+ * The most recently fetched subscription entitlement snapshot.
26
+ * `undefined` until the account receives a socket entitlement snapshot or
27
+ * {@link AccountApi.getSubscriptionStatus} / {@link AccountApi.refreshSubscription}
28
+ * has been called.
29
+ *
30
+ * Subscribe to the `'updated'` event (inherited from `DataEntity`) to react
31
+ * to changes; the `changedKeys` array will include `'subscription'` when
32
+ * this field is refreshed.
33
+ */
34
+ subscription?: SubscriptionEntitlementSnapshot;
23
35
  }
24
36
  /**
25
37
  * Current account data.
@@ -35,5 +47,23 @@ declare class CurrentAccount extends DataEntity<AccountData> {
35
47
  get walletAddress(): string | undefined;
36
48
  get username(): string | undefined;
37
49
  get email(): string | undefined;
50
+ /**
51
+ * The most recently cached subscription entitlement snapshot.
52
+ * `undefined` until the account receives a socket entitlement snapshot or
53
+ * {@link AccountApi.getSubscriptionStatus} / {@link AccountApi.refreshSubscription}
54
+ * has been called.
55
+ */
56
+ get subscription(): SubscriptionEntitlementSnapshot | undefined;
57
+ /**
58
+ * Convenience getter - `true` when the account has an effective
59
+ * subscription entitlement on any Unlimited tier (`"unlimited"` or
60
+ * `"unlimited_pro"`).
61
+ *
62
+ * Returns `false` when no entitlement snapshot has been fetched yet, when
63
+ * the server reports no active entitlement, or when the tier is not an
64
+ * Unlimited tier. Call {@link AccountApi.refreshSubscription} to force a REST
65
+ * refresh when no socket entitlement snapshot has been received yet.
66
+ */
67
+ get isUnlimited(): boolean;
38
68
  }
39
69
  export default CurrentAccount;
@@ -24,7 +24,8 @@ function getDefaults() {
24
24
  }
25
25
  },
26
26
  walletAddress: undefined,
27
- username: undefined
27
+ username: undefined,
28
+ subscription: undefined
28
29
  };
29
30
  }
30
31
  /**
@@ -59,6 +60,31 @@ class CurrentAccount extends DataEntity_js_1.default {
59
60
  get email() {
60
61
  return this.data.email;
61
62
  }
63
+ /**
64
+ * The most recently cached subscription entitlement snapshot.
65
+ * `undefined` until the account receives a socket entitlement snapshot or
66
+ * {@link AccountApi.getSubscriptionStatus} / {@link AccountApi.refreshSubscription}
67
+ * has been called.
68
+ */
69
+ get subscription() {
70
+ return this.data.subscription;
71
+ }
72
+ /**
73
+ * Convenience getter - `true` when the account has an effective
74
+ * subscription entitlement on any Unlimited tier (`"unlimited"` or
75
+ * `"unlimited_pro"`).
76
+ *
77
+ * Returns `false` when no entitlement snapshot has been fetched yet, when
78
+ * the server reports no active entitlement, or when the tier is not an
79
+ * Unlimited tier. Call {@link AccountApi.refreshSubscription} to force a REST
80
+ * refresh when no socket entitlement snapshot has been received yet.
81
+ */
82
+ get isUnlimited() {
83
+ const sub = this.data.subscription;
84
+ if (!sub || !sub.active)
85
+ return false;
86
+ return sub.tier === 'unlimited' || sub.tier === 'unlimited_pro';
87
+ }
62
88
  }
63
89
  exports.default = CurrentAccount;
64
90
  //# sourceMappingURL=CurrentAccount.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CurrentAccount.js","sourceRoot":"","sources":["../../src/Account/CurrentAccount.ts"],"names":[],"mappings":";;;;;AAAA,yEAA8C;AAwB9C,SAAS,WAAW;IAClB,OAAO;QACL,aAAa,EAAE,cAAc;QAC7B,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,KAAK,EAAE;gBACL,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,GAAG;gBACV,GAAG,EAAE,GAAG;gBACR,OAAO,EAAE,GAAG;aACb;YACD,KAAK,EAAE;gBACL,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,GAAG;gBACV,GAAG,EAAE,GAAG;gBACR,OAAO,EAAE,GAAG;gBACZ,aAAa,EAAE,GAAG;aACnB;SACF;QACD,aAAa,EAAE,SAAS;QACxB,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,cAAe,SAAQ,uBAAuB;IAClD,YAAY,IAAkB;QAC5B,KAAK,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACnC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;CACF;AAED,kBAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"CurrentAccount.js","sourceRoot":"","sources":["../../src/Account/CurrentAccount.ts"],"names":[],"mappings":";;;;;AAAA,yEAA8C;AAoC9C,SAAS,WAAW;IAClB,OAAO;QACL,aAAa,EAAE,cAAc;QAC7B,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,KAAK,EAAE;gBACL,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,GAAG;gBACV,GAAG,EAAE,GAAG;gBACR,OAAO,EAAE,GAAG;aACb;YACD,KAAK,EAAE;gBACL,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,GAAG;gBACV,GAAG,EAAE,GAAG;gBACR,OAAO,EAAE,GAAG;gBACZ,aAAa,EAAE,GAAG;aACnB;SACF;QACD,aAAa,EAAE,SAAS;QACxB,QAAQ,EAAE,SAAS;QACnB,YAAY,EAAE,SAAS;KACxB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,cAAe,SAAQ,uBAAuB;IAClD,YAAY,IAAkB;QAC5B,KAAK,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACnC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACH,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;IAChC,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,WAAW;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QACnC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC;IAClE,CAAC;CACF;AAED,kBAAe,cAAc,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { AccountCreateData, AccountCreateParams, Balances, ClaimOptions, FullBalances, LoginData, MeData, Reward, RewardsQuery, TxHistoryEntry, TxHistoryParams } from './types.js';
2
+ import { CreateSubscriptionCheckoutOptions, SubscriptionCheckoutResult, SubscriptionEntitlementSnapshot, SubscriptionPlanId, SubscriptionPlan, SubscriptionPortalSession, SubscriptionTerm, SubscriptionUsage, TrialEligibility } from './subscription.types.js';
2
3
  import ApiGroup, { ApiConfig } from '../ApiGroup.js';
3
4
  import { Wallet } from 'ethers';
4
5
  import { ApiResponse } from '../ApiClient/index.js';
@@ -17,12 +18,44 @@ import { SupernetType } from '../ApiClient/WebSocketClient/types.js';
17
18
  */
18
19
  declare class AccountApi extends ApiGroup {
19
20
  readonly currentAccount: CurrentAccount;
21
+ /**
22
+ * Highest entitlement `version` applied to `currentAccount.subscription`.
23
+ * Socket payloads carry a monotonically increasing version; writes that
24
+ * carry an older version than the one already applied are discarded instead
25
+ * of overwriting fresher data.
26
+ */
27
+ private lastAppliedSubscriptionVersion;
28
+ /**
29
+ * Logical clock counting applied socket entitlement writes. A REST refresh
30
+ * captures this counter before its request goes on the wire; if it advanced
31
+ * by the time the response arrives, a fresher socket push landed mid-flight
32
+ * and the REST snapshot is discarded as stale.
33
+ */
34
+ private appliedSubscriptionSocketWrites;
20
35
  constructor(config: ApiConfig);
21
36
  private handleBalanceUpdate;
22
37
  private handleChangeNetwork;
23
38
  private handleServerConnected;
24
39
  private handleServerConnecting;
25
40
  private handleServerDisconnected;
41
+ private mapSocketSubscriptionEntitlement;
42
+ /**
43
+ * Single chokepoint through which every subscription entitlement writer
44
+ * (REST refresh, socket entitlement push, socket authenticated seeding)
45
+ * must route.
46
+ *
47
+ * Guards against last-writer-wins races between the two transports: writes
48
+ * carrying an older `version` than the one already applied are discarded,
49
+ * and an unversioned REST snapshot whose request started before a socket
50
+ * push was applied is discarded as stale. Snapshots deep-equal to the
51
+ * current one are accepted without re-applying, so reconnect re-seeds and
52
+ * tab replays do not emit redundant 'updated' events.
53
+ *
54
+ * @returns `true` when the snapshot was accepted (even if identical to the
55
+ * current one), `false` when it was discarded as stale.
56
+ */
57
+ private applySubscriptionSnapshot;
58
+ private handleSubscriptionEntitlementUpdated;
26
59
  private handleSocketAuthenticated;
27
60
  private handleAuthUpdated;
28
61
  /**
@@ -212,5 +245,143 @@ declare class AccountApi extends ApiGroup {
212
245
  * @param provider - Provider name, defaults to 'base', can be 'base', 'etherlink', etc.
213
246
  */
214
247
  approveTokenUsage(password: string, spender: 'account' | 'staker', provider?: string): Promise<void>;
248
+ /**
249
+ * Fetch the current user's subscription entitlement snapshot.
250
+ *
251
+ * Returns an object describing whether the account has an effective
252
+ * subscription entitlement, the tier, period boundaries, usage, limits, and
253
+ * enabled capabilities. When no subscription exists, `active` is `false` and
254
+ * `status` is `'none'`.
255
+ *
256
+ * Also updates `currentAccount.subscription` so callers can read the
257
+ * snapshot from the observable entity without re-fetching.
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const snap = await sogni.account.getSubscriptionStatus();
262
+ * if (snap.active) {
263
+ * console.log('Plan:', snap.tier, 'until', snap.currentPeriodEnd);
264
+ * }
265
+ * ```
266
+ */
267
+ getSubscriptionStatus(): Promise<SubscriptionEntitlementSnapshot>;
268
+ /**
269
+ * Fetch the current user's usage for the active billing cycle.
270
+ *
271
+ * Returns the render/job counters for the subscriber's current billing cycle
272
+ * (not a calendar month). While the entitlement is `'trialing'`, the response
273
+ * also carries `trialEndsAt`, `trialCreditsLimit`, and `trialCreditsUsed` so
274
+ * you can render "X of N trial credits used" messaging; those fields are
275
+ * omitted for non-trial subscriptions.
276
+ *
277
+ * Note: these trial usage fields come from this endpoint, NOT from
278
+ * {@link getSubscriptionStatus} — the entitlement snapshot never carries
279
+ * trial usage.
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const usage = await sogni.account.getSubscriptionUsage();
284
+ * if (usage.trialCreditsLimit !== undefined) {
285
+ * console.log(`${usage.trialCreditsUsed} of ${usage.trialCreditsLimit} trial credits used`);
286
+ * }
287
+ * ```
288
+ */
289
+ getSubscriptionUsage(): Promise<SubscriptionUsage>;
290
+ /**
291
+ * Check whether the current account is eligible to start a free trial.
292
+ *
293
+ * Returns `{ eligible, reasonCode }`. `reasonCode` is ALWAYS present: it is
294
+ * `'eligible'` when a trial may be started, or a deny reason otherwise (e.g.
295
+ * `'wallet_already_used'`, `'strong_signal_match'`, `'weak_combo'`). Use this
296
+ * before offering a "start free trial" flow.
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * const { eligible, reasonCode } = await sogni.account.getTrialEligibility();
301
+ * if (eligible) {
302
+ * const { url } = await sogni.account.createSubscriptionCheckout('unlimited', 'monthly', {
303
+ * startTrial: true
304
+ * });
305
+ * }
306
+ * ```
307
+ */
308
+ getTrialEligibility(): Promise<TrialEligibility>;
309
+ /**
310
+ * Persist a raw persistent device identifier for the current account.
311
+ *
312
+ * Used for free-trial anti-abuse attribution so the server can detect device
313
+ * reuse across accounts. Requires an authenticated session.
314
+ *
315
+ * @param deviceId - Raw persistent device identifier.
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * await sogni.account.setDeviceId(myPersistentDeviceId);
320
+ * ```
321
+ */
322
+ setDeviceId(deviceId: string): Promise<void>;
323
+ /**
324
+ * Fetch the list of available subscription plans.
325
+ *
326
+ * This is a public endpoint; no authentication is required.
327
+ *
328
+ * @example
329
+ * ```typescript
330
+ * const plans = await sogni.account.getSubscriptionPlans();
331
+ * plans.forEach(p => console.log(p.displayName, p.priceUsd));
332
+ * ```
333
+ */
334
+ getSubscriptionPlans(): Promise<SubscriptionPlan[]>;
335
+ /**
336
+ * Create a Stripe checkout session to subscribe to a plan.
337
+ *
338
+ * Returns a `url` to which the user should be redirected to complete payment.
339
+ * After a successful checkout Stripe will redirect back to your configured
340
+ * return URL and the subscription entitlement will become active.
341
+ *
342
+ * Pass `options.startTrial` to control free-trial behavior: `true` starts a
343
+ * trial when the account is eligible, while `false` is sent verbatim to
344
+ * subscribe immediately with no trial even if the account is eligible.
345
+ * Pass `options.deviceId` to forward a raw persistent device identifier for
346
+ * trial anti-abuse attribution.
347
+ *
348
+ * @param planId - The plan identifier from {@link getSubscriptionPlans}
349
+ * @param term - Billing cadence: `'monthly'` or `'annual'`
350
+ * @param options - Optional checkout metadata, redirect target, and trial controls.
351
+ *
352
+ * @example
353
+ * ```typescript
354
+ * const { url } = await sogni.account.createSubscriptionCheckout('unlimited', 'monthly');
355
+ * window.location.href = url;
356
+ * ```
357
+ */
358
+ createSubscriptionCheckout(planId: SubscriptionPlanId, term: SubscriptionTerm, options?: CreateSubscriptionCheckoutOptions): Promise<SubscriptionCheckoutResult>;
359
+ /**
360
+ * Create a Stripe customer portal session for managing an existing subscription.
361
+ *
362
+ * Returns a `url` to which the user should be redirected. The portal lets
363
+ * them update payment methods, cancel, or view invoices.
364
+ *
365
+ * @example
366
+ * ```typescript
367
+ * const { url } = await sogni.account.createSubscriptionPortalSession();
368
+ * window.location.href = url;
369
+ * ```
370
+ */
371
+ createSubscriptionPortalSession(): Promise<SubscriptionPortalSession>;
372
+ /**
373
+ * Refresh the cached subscription entitlement on `currentAccount`.
374
+ *
375
+ * Convenience wrapper around {@link getSubscriptionStatus} that makes the
376
+ * intent ("I want to pull fresh entitlement data into the observable
377
+ * account entity") explicit at the call site.
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * await sogni.account.refreshSubscription();
382
+ * console.log(sogni.account.currentAccount.isUnlimited);
383
+ * ```
384
+ */
385
+ refreshSubscription(): Promise<SubscriptionEntitlementSnapshot>;
215
386
  }
216
387
  export default AccountApi;