@unicitylabs/sphere-sdk 0.14.1-dev.2 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/connect/index.cjs +1 -1
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.js +1 -1
  4. package/dist/connect/index.js.map +1 -1
  5. package/dist/core/index.cjs +69 -27
  6. package/dist/core/index.cjs.map +1 -1
  7. package/dist/core/index.d.cts +21 -1
  8. package/dist/core/index.d.ts +21 -1
  9. package/dist/core/index.js +69 -27
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/impl/browser/connect/index.cjs +1 -1
  12. package/dist/impl/browser/connect/index.cjs.map +1 -1
  13. package/dist/impl/browser/connect/index.js +1 -1
  14. package/dist/impl/browser/connect/index.js.map +1 -1
  15. package/dist/impl/browser/index.cjs +33 -0
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js +33 -0
  18. package/dist/impl/browser/index.js.map +1 -1
  19. package/dist/impl/nodejs/index.cjs +33 -0
  20. package/dist/impl/nodejs/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/index.d.cts +41 -1
  22. package/dist/impl/nodejs/index.d.ts +41 -1
  23. package/dist/impl/nodejs/index.js +33 -0
  24. package/dist/impl/nodejs/index.js.map +1 -1
  25. package/dist/impl/shared/wallet-api/index.d.cts +21 -1
  26. package/dist/impl/shared/wallet-api/index.d.ts +21 -1
  27. package/dist/index.cjs +69 -27
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +21 -1
  30. package/dist/index.d.ts +21 -1
  31. package/dist/index.js +69 -27
  32. package/dist/index.js.map +1 -1
  33. package/dist/modules/payments-v2/index.cjs +36 -26
  34. package/dist/modules/payments-v2/index.cjs.map +1 -1
  35. package/dist/modules/payments-v2/index.d.cts +16 -6
  36. package/dist/modules/payments-v2/index.d.ts +16 -6
  37. package/dist/modules/payments-v2/index.js +35 -26
  38. package/dist/modules/payments-v2/index.js.map +1 -1
  39. package/package.json +1 -1
@@ -13,6 +13,8 @@ interface GroupChatModuleConfig {
13
13
  maxReconnectAttempts?: number;
14
14
  }
15
15
 
16
+ type ConnectionStatus$1 = 'connected' | 'degraded' | 'offline';
17
+
16
18
  /**
17
19
  * SDK2 Core Types
18
20
  * Platform-independent type definitions
@@ -416,6 +418,19 @@ interface PeerInfo {
416
418
  chainPubkey: string;
417
419
  /** L3 DIRECT address (DIRECT://...) */
418
420
  directAddress: string;
421
+ /**
422
+ * Network the peer's identity binding DECLARES ('testnet2', …) — absent when
423
+ * the binding carries none, which is every binding published so far. Parsed
424
+ * only, never invented: money refuses a PROVEN foreign network (§5.6).
425
+ *
426
+ * Absent is also the STRUCTURAL answer on the `@nametag` and `DIRECT://`
427
+ * routes of the Nostr transport, whichever binding is out there: those two
428
+ * resolve through nostr-js-sdk's `queryBindingBy*`, whose parser drops every
429
+ * content field outside its whitelist and never hands back the signed event
430
+ * (#734 tracks the upstream fix). Only routes that parse the raw event —
431
+ * `resolveTransportPubkeyInfo`, `discoverAddresses` — can populate it today.
432
+ */
433
+ network?: string;
419
434
  /** Event timestamp */
420
435
  timestamp: number;
421
436
  }
@@ -631,6 +646,26 @@ declare class NostrTransportProvider implements TransportProvider {
631
646
  resolveAddressInfo(address: string): Promise<PeerInfo | null>;
632
647
  /**
633
648
  * Convert a BindingInfo (from nostr-js-sdk) to PeerInfo (sphere-sdk type).
649
+ *
650
+ * `network` IS DELIBERATELY ABSENT HERE — a live limitation, not an oversight
651
+ * (#734). `queryBindingByNametag`/`queryBindingByAddress` are the whole public
652
+ * resolution API for `@nametag` and `DIRECT://`, and both hardcode
653
+ * `parseBindingInfo` inside the SDK's PRIVATE `queryWithFirstSeenWins`: the
654
+ * caller never sees the signed event that resolution selected, and the parse
655
+ * has already dropped every content field outside its whitelist. Re-querying
656
+ * raw would mean re-deriving UNIP-01 ownership ourselves (marker preference,
657
+ * cross-author first-seen-wins, ambiguity→null, multi-relay settle — all
658
+ * private), and a second resolver that can disagree with the SDK's is worse
659
+ * than a missing field on a MONEY guard. Nothing can declare a network today
660
+ * regardless: the publish builders whitelist the same fields.
661
+ *
662
+ * CONSEQUENCE, stated plainly: for `@nametag` and `DIRECT://` recipients the
663
+ * §5.6 cross-network guard can only SIGNAL (`recipient:network-unverified`),
664
+ * never refuse. Upstream #734 must add `network` to the binding builders AND
665
+ * to `BindingInfo`; the tripwire in
666
+ * tests/unit/payments-v2/recipient-network.transport.test.ts fails the day it
667
+ * lands, so this wiring cannot be forgotten. Do not "fix" this by inventing a
668
+ * value — a stamped network is what made the guard unfalsifiable (#733).
634
669
  */
635
670
  private bindingInfoToPeerInfo;
636
671
  /**
@@ -1066,12 +1101,17 @@ interface FacadeSession {
1066
1101
  * stream nudge resumes. The facade registers handleEpochChange here.
1067
1102
  */
1068
1103
  subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
1104
+ /**
1105
+ * The session's CURRENT status — REQUIRED, and the ONE source `connectionStatus()`
1106
+ * and `connection:status` both come from ('offline' before first contact).
1107
+ */
1108
+ status(): ConnectionStatus$1;
1069
1109
  /**
1070
1110
  * Optional connection-status feed (same wiring pattern as the streams; the
1071
1111
  * emission point is the session's existing `connection:status` transition).
1072
1112
  * The facade's heartbeat resets its backoff on a 'connected' recovery.
1073
1113
  */
1074
- subscribeStatus?(handler: (status: 'connected' | 'degraded' | 'offline') => void): () => void;
1114
+ subscribeStatus?(handler: (status: ConnectionStatus$1) => void): () => void;
1075
1115
  }
1076
1116
  interface IntentWireLike {
1077
1117
  transferId: string;
@@ -13,6 +13,8 @@ interface GroupChatModuleConfig {
13
13
  maxReconnectAttempts?: number;
14
14
  }
15
15
 
16
+ type ConnectionStatus$1 = 'connected' | 'degraded' | 'offline';
17
+
16
18
  /**
17
19
  * SDK2 Core Types
18
20
  * Platform-independent type definitions
@@ -416,6 +418,19 @@ interface PeerInfo {
416
418
  chainPubkey: string;
417
419
  /** L3 DIRECT address (DIRECT://...) */
418
420
  directAddress: string;
421
+ /**
422
+ * Network the peer's identity binding DECLARES ('testnet2', …) — absent when
423
+ * the binding carries none, which is every binding published so far. Parsed
424
+ * only, never invented: money refuses a PROVEN foreign network (§5.6).
425
+ *
426
+ * Absent is also the STRUCTURAL answer on the `@nametag` and `DIRECT://`
427
+ * routes of the Nostr transport, whichever binding is out there: those two
428
+ * resolve through nostr-js-sdk's `queryBindingBy*`, whose parser drops every
429
+ * content field outside its whitelist and never hands back the signed event
430
+ * (#734 tracks the upstream fix). Only routes that parse the raw event —
431
+ * `resolveTransportPubkeyInfo`, `discoverAddresses` — can populate it today.
432
+ */
433
+ network?: string;
419
434
  /** Event timestamp */
420
435
  timestamp: number;
421
436
  }
@@ -631,6 +646,26 @@ declare class NostrTransportProvider implements TransportProvider {
631
646
  resolveAddressInfo(address: string): Promise<PeerInfo | null>;
632
647
  /**
633
648
  * Convert a BindingInfo (from nostr-js-sdk) to PeerInfo (sphere-sdk type).
649
+ *
650
+ * `network` IS DELIBERATELY ABSENT HERE — a live limitation, not an oversight
651
+ * (#734). `queryBindingByNametag`/`queryBindingByAddress` are the whole public
652
+ * resolution API for `@nametag` and `DIRECT://`, and both hardcode
653
+ * `parseBindingInfo` inside the SDK's PRIVATE `queryWithFirstSeenWins`: the
654
+ * caller never sees the signed event that resolution selected, and the parse
655
+ * has already dropped every content field outside its whitelist. Re-querying
656
+ * raw would mean re-deriving UNIP-01 ownership ourselves (marker preference,
657
+ * cross-author first-seen-wins, ambiguity→null, multi-relay settle — all
658
+ * private), and a second resolver that can disagree with the SDK's is worse
659
+ * than a missing field on a MONEY guard. Nothing can declare a network today
660
+ * regardless: the publish builders whitelist the same fields.
661
+ *
662
+ * CONSEQUENCE, stated plainly: for `@nametag` and `DIRECT://` recipients the
663
+ * §5.6 cross-network guard can only SIGNAL (`recipient:network-unverified`),
664
+ * never refuse. Upstream #734 must add `network` to the binding builders AND
665
+ * to `BindingInfo`; the tripwire in
666
+ * tests/unit/payments-v2/recipient-network.transport.test.ts fails the day it
667
+ * lands, so this wiring cannot be forgotten. Do not "fix" this by inventing a
668
+ * value — a stamped network is what made the guard unfalsifiable (#733).
634
669
  */
635
670
  private bindingInfoToPeerInfo;
636
671
  /**
@@ -1066,12 +1101,17 @@ interface FacadeSession {
1066
1101
  * stream nudge resumes. The facade registers handleEpochChange here.
1067
1102
  */
1068
1103
  subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
1104
+ /**
1105
+ * The session's CURRENT status — REQUIRED, and the ONE source `connectionStatus()`
1106
+ * and `connection:status` both come from ('offline' before first contact).
1107
+ */
1108
+ status(): ConnectionStatus$1;
1069
1109
  /**
1070
1110
  * Optional connection-status feed (same wiring pattern as the streams; the
1071
1111
  * emission point is the session's existing `connection:status` transition).
1072
1112
  * The facade's heartbeat resets its backoff on a 'connected' recovery.
1073
1113
  */
1074
- subscribeStatus?(handler: (status: 'connected' | 'degraded' | 'offline') => void): () => void;
1114
+ subscribeStatus?(handler: (status: ConnectionStatus$1) => void): () => void;
1075
1115
  }
1076
1116
  interface IntentWireLike {
1077
1117
  transferId: string;
@@ -24428,6 +24428,15 @@ function defaultUUIDGenerator() {
24428
24428
  var COMPOSING_INDICATOR_KIND = 25050;
24429
24429
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
24430
24430
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
24431
+ function declaredNetwork(event) {
24432
+ let value;
24433
+ try {
24434
+ value = JSON.parse(event.content)?.network;
24435
+ } catch {
24436
+ return void 0;
24437
+ }
24438
+ return typeof value === "string" && value !== "" ? value : void 0;
24439
+ }
24431
24440
  var NostrTransportProvider = class _NostrTransportProvider {
24432
24441
  id = "nostr";
24433
24442
  name = "Nostr Transport";
@@ -24924,6 +24933,26 @@ var NostrTransportProvider = class _NostrTransportProvider {
24924
24933
  }
24925
24934
  /**
24926
24935
  * Convert a BindingInfo (from nostr-js-sdk) to PeerInfo (sphere-sdk type).
24936
+ *
24937
+ * `network` IS DELIBERATELY ABSENT HERE — a live limitation, not an oversight
24938
+ * (#734). `queryBindingByNametag`/`queryBindingByAddress` are the whole public
24939
+ * resolution API for `@nametag` and `DIRECT://`, and both hardcode
24940
+ * `parseBindingInfo` inside the SDK's PRIVATE `queryWithFirstSeenWins`: the
24941
+ * caller never sees the signed event that resolution selected, and the parse
24942
+ * has already dropped every content field outside its whitelist. Re-querying
24943
+ * raw would mean re-deriving UNIP-01 ownership ourselves (marker preference,
24944
+ * cross-author first-seen-wins, ambiguity→null, multi-relay settle — all
24945
+ * private), and a second resolver that can disagree with the SDK's is worse
24946
+ * than a missing field on a MONEY guard. Nothing can declare a network today
24947
+ * regardless: the publish builders whitelist the same fields.
24948
+ *
24949
+ * CONSEQUENCE, stated plainly: for `@nametag` and `DIRECT://` recipients the
24950
+ * §5.6 cross-network guard can only SIGNAL (`recipient:network-unverified`),
24951
+ * never refuse. Upstream #734 must add `network` to the binding builders AND
24952
+ * to `BindingInfo`; the tripwire in
24953
+ * tests/unit/payments-v2/recipient-network.transport.test.ts fails the day it
24954
+ * lands, so this wiring cannot be forgotten. Do not "fix" this by inventing a
24955
+ * value — a stamped network is what made the guard unfalsifiable (#733).
24927
24956
  */
24928
24957
  async bindingInfoToPeerInfo(binding, nametag) {
24929
24958
  return {
@@ -24950,11 +24979,13 @@ var NostrTransportProvider = class _NostrTransportProvider {
24950
24979
  const bindingEvent = events[0];
24951
24980
  try {
24952
24981
  const content = JSON.parse(bindingEvent.content);
24982
+ const network = declaredNetwork(bindingEvent);
24953
24983
  return {
24954
24984
  nametag: content.nametag || void 0,
24955
24985
  transportPubkey: bindingEvent.pubkey,
24956
24986
  chainPubkey: content.public_key || "",
24957
24987
  directAddress: content.direct_address || "",
24988
+ ...network !== void 0 ? { network } : {},
24958
24989
  timestamp: bindingEvent.created_at * 1e3
24959
24990
  };
24960
24991
  } catch {
@@ -24990,11 +25021,13 @@ var NostrTransportProvider = class _NostrTransportProvider {
24990
25021
  for (const [pubkey, event] of byAuthor) {
24991
25022
  try {
24992
25023
  const content = JSON.parse(event.content);
25024
+ const network = declaredNetwork(event);
24993
25025
  results.push({
24994
25026
  nametag: content.nametag || void 0,
24995
25027
  transportPubkey: pubkey,
24996
25028
  chainPubkey: content.public_key || "",
24997
25029
  directAddress: content.direct_address || "",
25030
+ ...network !== void 0 ? { network } : {},
24998
25031
  timestamp: event.created_at * 1e3
24999
25032
  });
25000
25033
  } catch {