@unicitylabs/sphere-sdk 0.14.11 → 0.15.0-dev.1

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 (46) hide show
  1. package/README.md +55 -17
  2. package/dist/connect/index.cjs +10 -17
  3. package/dist/connect/index.cjs.map +1 -1
  4. package/dist/connect/index.js +10 -17
  5. package/dist/connect/index.js.map +1 -1
  6. package/dist/core/index.cjs +69 -84
  7. package/dist/core/index.cjs.map +1 -1
  8. package/dist/core/index.d.cts +5 -14
  9. package/dist/core/index.d.ts +5 -14
  10. package/dist/core/index.js +69 -84
  11. package/dist/core/index.js.map +1 -1
  12. package/dist/impl/browser/connect/index.cjs +3 -3
  13. package/dist/impl/browser/connect/index.cjs.map +1 -1
  14. package/dist/impl/browser/connect/index.js +3 -3
  15. package/dist/impl/browser/connect/index.js.map +1 -1
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js.map +1 -1
  18. package/dist/impl/nodejs/connect/index.cjs +2 -2
  19. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  20. package/dist/impl/nodejs/connect/index.js +2 -2
  21. package/dist/impl/nodejs/connect/index.js.map +1 -1
  22. package/dist/impl/nodejs/index.cjs.map +1 -1
  23. package/dist/impl/nodejs/index.js.map +1 -1
  24. package/dist/impl/wallet-api-v2/index.cjs +92 -92
  25. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  26. package/dist/impl/wallet-api-v2/index.js +92 -92
  27. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  28. package/dist/index.cjs +69 -84
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +6 -11
  31. package/dist/index.d.ts +6 -11
  32. package/dist/index.js +69 -84
  33. package/dist/index.js.map +1 -1
  34. package/dist/modules/payments-v2/index.cjs +116 -174
  35. package/dist/modules/payments-v2/index.cjs.map +1 -1
  36. package/dist/modules/payments-v2/index.d.cts +3 -5
  37. package/dist/modules/payments-v2/index.d.ts +3 -5
  38. package/dist/modules/payments-v2/index.js +114 -173
  39. package/dist/modules/payments-v2/index.js.map +1 -1
  40. package/dist/token-engine/index.cjs +43 -57
  41. package/dist/token-engine/index.cjs.map +1 -1
  42. package/dist/token-engine/index.d.cts +0 -4
  43. package/dist/token-engine/index.d.ts +0 -4
  44. package/dist/token-engine/index.js +43 -57
  45. package/dist/token-engine/index.js.map +1 -1
  46. package/package.json +2 -2
package/README.md CHANGED
@@ -110,7 +110,7 @@ A wallet is composed from **swappable ports**, layered in two steps:
110
110
  - **The rail is wallet-api, not Nostr.** Transfers are certified on-chain by the token engine and the finished token is deposited into the recipient's **wallet-api mailbox**. Nostr carries messaging/nametags — **it does not move payments.**
111
111
  - **Custody is server-side.** The wallet-api backend holds your token inventory; your keys never leave the client. (Own-storage custody was rescinded — there is no local token store.)
112
112
  - **The money ports are contract-enforced.** `StoragePort`/`DeliveryPort` (`modules/payments-v2/ports.ts`) have wallet-api implementations; the `paymentsV2Transport` seam in the `walletApi` config lets tests/custom hosts inject a whole replacement bundle.
113
- - **`network` placement.** Required on `createBrowserProviders`/`createNodeProviders` AND in the `walletApi` config (init throws `INVALID_CONFIG` without either); optional/informational on `Sphere.init`.
113
+ - **`network` placement.** Required on `createBrowserProviders`/`createNodeProviders`, in the `walletApi` config, AND on `Sphere.init` — the three must agree. `Sphere.init` resolves the payments composition and the token registry from its own `network`, so omitting it or letting it disagree with `walletApi.network` throws `INVALID_CONFIG` before any storage write.
114
114
 
115
115
  For manual/advanced provider wiring, see [Custom Providers Configuration](#custom-providers-configuration). For the deeper integration guide, see [docs/INTEGRATION.md](docs/INTEGRATION.md).
116
116
 
@@ -148,6 +148,22 @@ try {
148
148
  }
149
149
  ```
150
150
 
151
+ ## Migrating off `sphere.paymentsV2`
152
+
153
+ The deprecated `sphere.paymentsV2` alias and the `paymentsV2: true` init flag are **removed** in
154
+ 0.15.0. `sphere.payments` is the only accessor, and it is the same facade the alias returned.
155
+
156
+ One behavioural difference matters: while no vertical is running (init in flight, mid
157
+ address-switch, destroyed) the alias returned `null` and `sphere.payments` **throws**
158
+ `SphereError` with `code: 'NOT_INITIALIZED'`. Call sites that leaned on the nullish alias —
159
+ `sphere.paymentsV2?.tokens()`, `?? fallback`, `if (sphere.paymentsV2)` as a readiness probe —
160
+ silently degraded to "no payments" before and now throw, so catch `NOT_INITIALIZED` where you
161
+ used to check for null. Code that runs after `await Sphere.init(…)` and before `destroy()` —
162
+ everything else in this README — reads `sphere.payments` directly.
163
+
164
+ The `accounting:` / `swap:` options are **not** part of this cleanup: they still throw a typed
165
+ `INVALID_CONFIG`, deliberately, because 0.15.0 is the release where consumers re-integrate.
166
+
151
167
  ## Network Configuration
152
168
 
153
169
  The SDK ships network presets that configure all services automatically. `network` is **required** — there is no default:
@@ -159,7 +175,9 @@ The SDK ships network presets that configure all services automatically. `networ
159
175
  | `mainnet` | aggregator.unicity.network (v1-era) | relay.unicity.network (+ public relays) |
160
176
  | `dev` | dev-aggregator.dyndns.org (v1-era) | nostr-relay.testnet.unicity.network |
161
177
 
162
- > **v1 → v2 cutover:** `testnet` now points at **testnet2**, the v2 state-transition gateway network (network id 4, taken from the trust base; own testnet2 token registry). The old `goggregator-test` testnet spoke the removed v1 protocol and is gone. `mainnet` and `dev` still point at v1-era aggregators — wallet operations that move money (`send`, `mint`) **fail loudly** (`AGGREGATOR_ERROR`) on those networks until their gateways are cut over to the v2 protocol. The transfer wire payload is the finished v2 token blob (raw `Token.toCBOR()`), deposited into the recipient's wallet-api mailbox.
178
+ > **v1 → v2 cutover:** `testnet` now points at **testnet2**, the v2 state-transition gateway network (network id 4, taken from the trust base; own testnet2 token registry). The old `goggregator-test` testnet spoke the removed v1 protocol and is gone. `mainnet` and `dev` still point at v1-era aggregators — wallet operations that move money (`send`, `mint`) **fail loudly** (`AGGREGATOR_ERROR`) on those networks until their gateways are cut over. The transfer wire payload is the finished token blob — the base SDK's own `Token.toCBOR()` bytes, with no sphere envelope around them — deposited into the recipient's wallet-api mailbox.
179
+ >
180
+ > The **network** name (testnet2) and the **base-SDK major** (3.x since 0.15.0) are separate axes: testnet2 is still testnet2 after the 3.0.1 bump. What the bump changes is the bytes on that network — a gateway serving the v3 protocol accepts nothing a 2.x client writes, and vice versa.
163
181
 
164
182
  ```typescript
165
183
  // Use testnet for all services
@@ -168,7 +186,7 @@ const providers = createBrowserProviders({ network: 'testnet' });
168
186
  // Override specific services while using network preset
169
187
  const providers = createBrowserProviders({
170
188
  network: 'testnet',
171
- oracle: { url: 'https://custom-gateway.example.com' }, // custom v2 gateway
189
+ oracle: { url: 'https://custom-gateway.example.com' }, // custom testnet2 gateway
172
190
  });
173
191
  ```
174
192
 
@@ -199,7 +217,7 @@ The `testnet` preset wires most of these automatically — you only pass `networ
199
217
  | **Group-chat relay** (NIP-29) | `wss://sphere-relay.unicity.network` |
200
218
  | **Token registry** | `https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json` |
201
219
 
202
- The aggregator key above is the **testnet2** key only and is safe in client code; a **mainnet** key is a real secret. `mainnet`/`dev` still point at v1-era aggregators and cannot serve the v2 engine yet (`AGGREGATOR_ERROR`).
220
+ The aggregator key above is the **testnet2** key only and is safe in client code; a **mainnet** key is a real secret. `mainnet`/`dev` still point at v1-era aggregators and cannot serve the engine (`AGGREGATOR_ERROR`).
203
221
 
204
222
  ## Price Provider (Optional)
205
223
 
@@ -243,7 +261,7 @@ sphere.setPriceProvider(createPriceProvider({
243
261
 
244
262
  ## Test Tokens on Testnet (Self-Mint)
245
263
 
246
- There is no faucet. On testnet you top up your wallet by **self-minting** fungible tokens via the v2 token engine — `mint(coinIdHex, amount)` mints a finished token directly to this wallet (journal-first: crash-safe, a replay converges idempotently):
264
+ There is no faucet. On testnet you top up your wallet by **self-minting** fungible tokens via the token engine — `mint(coinIdHex, amount)` mints a finished token directly to this wallet (journal-first: crash-safe, a replay converges idempotently):
247
265
 
248
266
  ```typescript
249
267
  import { getCoinIdBySymbol } from '@unicitylabs/sphere-sdk';
@@ -259,7 +277,7 @@ if (result.success) {
259
277
  }
260
278
  ```
261
279
 
262
- > **Note:** Minting requires a working v2 oracle config (trust base + gateway URL + API key) — it fails with an error result otherwise. See [API Key](#api-key) above.
280
+ > **Note:** Minting requires a working oracle config (trust base + gateway URL + API key) — it fails with an error result otherwise. See [API Key](#api-key) above.
263
281
 
264
282
  ## Multi-Address Support
265
283
 
@@ -596,7 +614,7 @@ const transport = createNostrTransportProvider({
596
614
  relays: ['wss://nostr-relay.testnet.unicity.network'],
597
615
  });
598
616
  // `network` (or `trustBaseUrl`) is required — it selects the trust base the
599
- // v2 token engine is built from. The apiKey authenticates gateway requests.
617
+ // token engine is built from. The apiKey authenticates gateway requests.
600
618
  const oracle = createUnicityAggregatorProvider({
601
619
  url: 'https://gateway.testnet2.unicity.network',
602
620
  apiKey: 'sk_...',
@@ -722,7 +740,16 @@ import {
722
740
 
723
741
  ## Token format & verification
724
742
 
725
- Tokens are opaque **v2 CBOR blobs** (`Token.sdkData` carries the hex when a blob is loaded). Inventory lives in the wallet-api backend; the SDK downloads blobs on demand (lazy tokens carry value metadata only until selected for a spend). Every incoming token is engine-verified (full trust-base proof check) and ownership-checked **before it enters the balance** — there is no separate validate step to run.
743
+ Tokens are opaque CBOR blobs — the base SDK's own `Token.toCBOR()` bytes, with no sphere-private
744
+ envelope wrapped around them (`Token.sdkData` carries the hex when a blob is loaded). That is the
745
+ same form on the wire, in the wallet-api mailbox and in server storage. Since 0.15.0 those bytes
746
+ are **state-transition-sdk 3.x** CBOR; a 2.x blob does not decode and is rejected on receipt (the
747
+ drain warns and acks it as invalid rather than silently dropping it).
748
+
749
+ Inventory lives in the wallet-api backend; the SDK downloads blobs on demand (lazy tokens carry
750
+ value metadata only until selected for a spend). Every incoming token is engine-verified (full
751
+ trust-base proof check) and ownership-checked **before it enters the balance** — there is no
752
+ separate validate step to run.
726
753
 
727
754
  ## Architecture
728
755
 
@@ -742,7 +769,7 @@ mnemonic → master key → BIP32 derivation → identity
742
769
  ↓ ↓ ↓
743
770
  L3 (Unicity) Group Chat Nostr
744
771
  sphere.payments sphere.groupChat sphere.communications
745
- Tokens, v2 engine NIP-29 messaging P2P messaging
772
+ Tokens, engine NIP-29 messaging P2P messaging
746
773
  ```
747
774
 
748
775
  ```
@@ -761,14 +788,14 @@ Payments vertical (modules/payments-v2/ — docs/PAYMENTS-V2-DESIGN.md)
761
788
  `walletApi` transport config (core/payments-v2-wiring.ts).
762
789
 
763
790
  Token Engine (token-engine/)
764
- └── The wallet's boundary to the v2 state-transition SDK: all mint /
765
- transfer / split / verify / spent-check operations go through the
766
- ITokenEngine port. Sphere builds the engine from the oracle's config
791
+ └── The wallet's boundary to the base state-transition SDK (pinned 3.0.1):
792
+ all mint / transfer / split / verify / spent-check operations go through
793
+ the ITokenEngine port. Sphere builds the engine from the oracle's config
767
794
  (trust base JSON + gateway URL + API key); no state-transition SDK
768
795
  objects cross this boundary.
769
796
 
770
797
  Providers (injectable)
771
- ├── StorageProvider - Key-value persistence: keys/identity + the pv2:* scoped KV
798
+ ├── StorageProvider - Key-value persistence: keys/identity + the pv2g2:* scoped KV
772
799
  ├── TransportProvider - Messaging (Nostr) — NOT the payment rail
773
800
  ├── OracleProvider - Token-engine config (trust base JSON + gateway URL + API key)
774
801
  └── walletApi (config) - WalletApiTransportConfig — the wallet-api wire the
@@ -841,8 +868,19 @@ type NodeOracleConfig = BaseOracleConfig & NodeOracleExtensions;
841
868
 
842
869
  ## Documentation
843
870
 
844
- - [Integration Guide](./docs/INTEGRATION.md)
845
- - [API Reference](./docs/API.md)
871
+ Consumer-facing:
872
+
873
+ - [API Reference](./docs/API.md) — the full surface of `Sphere` and the payments facade
874
+ - [Integration Guide](./docs/INTEGRATION.md) — composition, custody, custom providers, events
875
+ - [Browser Quick Start](./docs/QUICKSTART-BROWSER.md) / [Node.js Quick Start](./docs/QUICKSTART-NODEJS.md)
876
+ - [Connect Protocol](./docs/CONNECT.md) — dApp ↔ wallet RPC (protocol version `2.1`)
877
+ - [Parallel token verification](./docs/VERIFICATION-WORKERS.md) — the opt-in worker pool
878
+ - [CHANGELOG](./CHANGELOG.md) — per-release notes (versioned sections start at `0.14.11`)
879
+
880
+ Design and migration references:
881
+
882
+ - [Payments vertical design](./docs/PAYMENTS-V2-DESIGN.md) — the authoritative money design
883
+ - [Payments migration guide](./docs/MIGRATION-PAYMENTS-V2.md) — what the P11 flip moved
846
884
 
847
885
  ## Browser Providers
848
886
 
@@ -852,7 +890,7 @@ The SDK includes browser-ready provider implementations:
852
890
  |----------|-------------|
853
891
  | `LocalStorageProvider` | Browser localStorage with SSR fallback |
854
892
  | `NostrTransportProvider` | Nostr relay messaging with NIP-04 |
855
- | `UnicityAggregatorProvider` | Network config for the v2 token engine (trust base + gateway URL + API key) |
893
+ | `UnicityAggregatorProvider` | Network config for the token engine (trust base + gateway URL + API key) |
856
894
 
857
895
  ## Node.js Providers
858
896
 
@@ -1070,7 +1108,7 @@ Nametags provide human-readable addresses (e.g., `@alice`) for receiving payment
1070
1108
 
1071
1109
  **How registration works:** registering a nametag publishes a **Nostr identity binding** (name ↔ chain pubkey). Uniqueness is first-seen-wins — a name is available iff no binding already resolves for it (`sphere.isNametagAvailable(name)`). Runtime name resolution is binding-only; payments always go to the recipient's key-based `DIRECT://` address (there are no PROXY addresses).
1072
1110
 
1073
- In addition, a self-issued v2 `UnicityIdToken` (the on-chain claim) is minted and stored **best-effort** at registration — a gateway outage or missing v2 oracle config never fails registration; the mint is retried on the next load, and the token is not consumed anywhere at runtime yet.
1111
+ Registration is **Nostr-binding-only**. The self-issued `UnicityIdToken` on-chain claim was removed with the 2.0.0 state-transition-sdk bump (upstream deleted the unicity-id primitive) — nothing is minted at registration, and nothing on chain is consulted to resolve a name.
1074
1112
 
1075
1113
  ### Registering a Nametag
1076
1114
 
@@ -455,7 +455,7 @@ function checkCompatibility(input) {
455
455
  }
456
456
 
457
457
  // connect/version.ts
458
- var SDK_VERSION = "0.14.11";
458
+ var SDK_VERSION = "0.15.0-dev.1";
459
459
 
460
460
  // connect/permissions.ts
461
461
  var PERMISSION_SCOPES = {
@@ -541,7 +541,7 @@ function toLegacyRequest(view, status) {
541
541
  return { ...view, symbol: view.symbol ?? "", status };
542
542
  }
543
543
  function legacyRequestPayload(sphere, update) {
544
- const view = sphere.paymentsV2?.requests.list().find((request) => request.id === update.id);
544
+ const view = sphere.payments.requests.list().find((request) => request.id === update.id);
545
545
  if (!view) {
546
546
  return {
547
547
  id: update.id,
@@ -620,7 +620,7 @@ var COMPAT_ATTACHERS = /* @__PURE__ */ new Map([
620
620
  forward({ providerId: "wallet-api", error: "wallet-api connection degraded" });
621
621
  })],
622
622
  ["sync:completed", (sphere, forward) => sphere.on("inventory:updated", () => {
623
- forward({ source: "payments", count: sphere.paymentsV2?.tokens().length ?? 0 });
623
+ forward({ source: "payments", count: sphere.payments.tokens().length });
624
624
  })],
625
625
  ["sync:remote-update", remoteUpdateAttacher]
626
626
  ]);
@@ -1372,32 +1372,25 @@ var ConnectHost = class {
1372
1372
  return this.handleUnsubscribe(params.event);
1373
1373
  }
1374
1374
  const sphere = this.requireSphere();
1375
- const v2 = sphere.paymentsV2 ?? null;
1376
1375
  switch (method) {
1377
1376
  case RPC_METHODS.GET_IDENTITY:
1378
1377
  return this.getPublicIdentity();
1379
1378
  case RPC_METHODS.GET_BALANCE:
1380
- return v2 ? v2.assets(params.coinId) : sphere.payments.getBalance(params.coinId);
1381
1379
  case RPC_METHODS.GET_ASSETS:
1382
- return v2 ? v2.assets(params.coinId) : sphere.payments.getAssets(params.coinId);
1380
+ return sphere.payments.assets(params.coinId);
1383
1381
  case RPC_METHODS.GET_FIAT_BALANCE:
1384
- return {
1385
- fiatBalance: v2 ? sumFiatUsd(await v2.assets()) : await sphere.payments.getFiatBalance()
1386
- };
1382
+ return { fiatBalance: sumFiatUsd(await sphere.payments.assets()) };
1387
1383
  case RPC_METHODS.GET_TOKENS:
1388
1384
  return this.stripTokenSdkData(
1389
- v2 ? v2.tokens(params.coinId ? { coinId: params.coinId } : void 0) : sphere.payments.getTokens(
1390
- params.coinId ? { coinId: params.coinId } : void 0
1391
- )
1385
+ sphere.payments.tokens(params.coinId ? { coinId: params.coinId } : void 0)
1392
1386
  );
1393
1387
  case RPC_METHODS.GET_HISTORY: {
1394
- if (!v2) return sphere.payments.getHistory();
1395
1388
  const limit = typeof params.limit === "number" && Number.isFinite(params.limit) ? params.limit : void 0;
1396
- if (limit !== void 0) return (await v2.history({ limit })).entries;
1397
- let page = await v2.history(void 0);
1389
+ if (limit !== void 0) return (await sphere.payments.history({ limit })).entries;
1390
+ let page = await sphere.payments.history(void 0);
1398
1391
  const entries = [...page.entries];
1399
1392
  while (page.more && page.cursor !== null) {
1400
- page = await v2.history({ before: page.cursor });
1393
+ page = await sphere.payments.history({ before: page.cursor });
1401
1394
  entries.push(...page.entries);
1402
1395
  }
1403
1396
  return entries;
@@ -1508,7 +1501,7 @@ var ConnectHost = class {
1508
1501
  return { subscribed: true, event: eventName };
1509
1502
  }
1510
1503
  const sphere = this.requireSphere();
1511
- if (sphere.paymentsV2) {
1504
+ {
1512
1505
  const compatUnsub = attachCompatEvent(
1513
1506
  sphere,
1514
1507
  eventName,