@unicitylabs/sphere-sdk 0.3.9 → 0.4.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 (43) hide show
  1. package/dist/connect/index.cjs +79 -3
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.d.cts +16 -0
  4. package/dist/connect/index.d.ts +16 -0
  5. package/dist/connect/index.js +79 -3
  6. package/dist/connect/index.js.map +1 -1
  7. package/dist/core/index.cjs +2686 -56
  8. package/dist/core/index.cjs.map +1 -1
  9. package/dist/core/index.d.cts +228 -3
  10. package/dist/core/index.d.ts +228 -3
  11. package/dist/core/index.js +2682 -52
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/impl/browser/connect/index.cjs +11 -2
  14. package/dist/impl/browser/connect/index.cjs.map +1 -1
  15. package/dist/impl/browser/connect/index.js +11 -2
  16. package/dist/impl/browser/connect/index.js.map +1 -1
  17. package/dist/impl/browser/index.cjs +467 -47
  18. package/dist/impl/browser/index.cjs.map +1 -1
  19. package/dist/impl/browser/index.js +468 -47
  20. package/dist/impl/browser/index.js.map +1 -1
  21. package/dist/impl/nodejs/connect/index.cjs +11 -2
  22. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  23. package/dist/impl/nodejs/connect/index.js +11 -2
  24. package/dist/impl/nodejs/connect/index.js.map +1 -1
  25. package/dist/impl/nodejs/index.cjs +152 -8
  26. package/dist/impl/nodejs/index.cjs.map +1 -1
  27. package/dist/impl/nodejs/index.d.cts +47 -0
  28. package/dist/impl/nodejs/index.d.ts +47 -0
  29. package/dist/impl/nodejs/index.js +153 -8
  30. package/dist/impl/nodejs/index.js.map +1 -1
  31. package/dist/index.cjs +2703 -56
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +326 -5
  34. package/dist/index.d.ts +326 -5
  35. package/dist/index.js +2692 -52
  36. package/dist/index.js.map +1 -1
  37. package/dist/l1/index.cjs +5 -1
  38. package/dist/l1/index.cjs.map +1 -1
  39. package/dist/l1/index.d.cts +2 -1
  40. package/dist/l1/index.d.ts +2 -1
  41. package/dist/l1/index.js +5 -1
  42. package/dist/l1/index.js.map +1 -1
  43. package/package.json +1 -1
@@ -655,6 +655,11 @@ interface BroadcastMessage {
655
655
  readonly timestamp: number;
656
656
  readonly tags?: string[];
657
657
  }
658
+ interface ComposingIndicator {
659
+ readonly senderPubkey: string;
660
+ readonly senderNametag?: string;
661
+ readonly expiresIn: number;
662
+ }
658
663
  /**
659
664
  * Minimal data stored in persistent storage for a tracked address.
660
665
  * Only contains user state — derived fields are computed on load.
@@ -685,7 +690,7 @@ interface TrackedAddress extends TrackedAddressEntry {
685
690
  /** Primary nametag (from nametag cache, without @ prefix) */
686
691
  readonly nametag?: string;
687
692
  }
688
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection';
693
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection';
689
694
  interface SphereEventMap {
690
695
  'transfer:incoming': IncomingTransfer;
691
696
  'transfer:confirmed': TransferResult;
@@ -705,6 +710,7 @@ interface SphereEventMap {
705
710
  senderNametag?: string;
706
711
  timestamp: number;
707
712
  };
713
+ 'composing:started': ComposingIndicator;
708
714
  'message:broadcast': BroadcastMessage;
709
715
  'sync:started': {
710
716
  source: string;
@@ -1053,6 +1059,17 @@ interface TransportProvider extends BaseProvider {
1053
1059
  * @returns Unsubscribe function
1054
1060
  */
1055
1061
  onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
1062
+ /**
1063
+ * Send composing indicator to a recipient using NIP-44 encrypted gift wrap
1064
+ * @param recipientTransportPubkey - Transport pubkey of the conversation partner
1065
+ * @param content - JSON payload with senderNametag and expiresIn
1066
+ */
1067
+ sendComposingIndicator?(recipientTransportPubkey: string, content: string): Promise<void>;
1068
+ /**
1069
+ * Subscribe to incoming composing indicators
1070
+ * @returns Unsubscribe function
1071
+ */
1072
+ onComposing?(handler: ComposingHandler): () => void;
1056
1073
  /**
1057
1074
  * Get list of configured relay URLs
1058
1075
  */
@@ -1277,6 +1294,7 @@ interface IncomingTypingIndicator {
1277
1294
  timestamp: number;
1278
1295
  }
1279
1296
  type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
1297
+ type ComposingHandler = (indicator: ComposingIndicator) => void;
1280
1298
 
1281
1299
  /**
1282
1300
  * L1 Payments Sub-Module
@@ -2401,6 +2419,13 @@ declare class PaymentsModule {
2401
2419
  * Remove all nametag data from memory and storage.
2402
2420
  */
2403
2421
  clearNametag(): Promise<void>;
2422
+ /**
2423
+ * Reload nametag data from storage providers into memory.
2424
+ *
2425
+ * Used as a recovery mechanism when `this.nametags` is unexpectedly empty
2426
+ * (e.g., wiped by sync or race condition) but nametag data exists in storage.
2427
+ */
2428
+ private reloadNametagsFromStorage;
2404
2429
  /**
2405
2430
  * Mint a nametag token on-chain (like Sphere wallet and lottery)
2406
2431
  * This creates the nametag token required for receiving tokens via PROXY addresses
@@ -2492,6 +2517,11 @@ declare class PaymentsModule {
2492
2517
  * Create SigningService from identity private key
2493
2518
  */
2494
2519
  private createSigningService;
2520
+ /**
2521
+ * Get the wallet's signing public key (used for token ownership predicates).
2522
+ * This is the key that token state predicates are checked against.
2523
+ */
2524
+ getSigningPublicKey(): Promise<Uint8Array>;
2495
2525
  /**
2496
2526
  * Create DirectAddress from a public key using UnmaskedPredicateReference
2497
2527
  */
@@ -2556,11 +2586,24 @@ declare class PaymentsModule {
2556
2586
  interface CommunicationsModuleConfig {
2557
2587
  /** Auto-save messages */
2558
2588
  autoSave?: boolean;
2559
- /** Max messages in memory */
2589
+ /** Max messages in memory (global cap) */
2560
2590
  maxMessages?: number;
2591
+ /** Max messages per conversation (default: 200) */
2592
+ maxPerConversation?: number;
2561
2593
  /** Enable read receipts */
2562
2594
  readReceipts?: boolean;
2563
2595
  }
2596
+ interface ConversationPage {
2597
+ messages: DirectMessage[];
2598
+ hasMore: boolean;
2599
+ oldestTimestamp: number | null;
2600
+ }
2601
+ interface GetConversationPageOptions {
2602
+ /** Max messages to return (default: 20) */
2603
+ limit?: number;
2604
+ /** Return messages older than this timestamp */
2605
+ before?: number;
2606
+ }
2564
2607
  interface CommunicationsModuleDependencies {
2565
2608
  identity: FullIdentity;
2566
2609
  storage: StorageProvider;
@@ -2573,8 +2616,10 @@ declare class CommunicationsModule {
2573
2616
  private messages;
2574
2617
  private broadcasts;
2575
2618
  private unsubscribeMessages;
2619
+ private unsubscribeComposing;
2576
2620
  private broadcastSubscriptions;
2577
2621
  private dmHandlers;
2622
+ private composingHandlers;
2578
2623
  private broadcastHandlers;
2579
2624
  constructor(config?: CommunicationsModuleConfig);
2580
2625
  /**
@@ -2582,7 +2627,10 @@ declare class CommunicationsModule {
2582
2627
  */
2583
2628
  initialize(deps: CommunicationsModuleDependencies): void;
2584
2629
  /**
2585
- * Load messages from storage
2630
+ * Load messages from storage.
2631
+ * Uses per-address key (STORAGE_KEYS_ADDRESS.MESSAGES) which is automatically
2632
+ * scoped by LocalStorageProvider to sphere_DIRECT_xxx_yyy_messages.
2633
+ * Falls back to legacy global 'direct_messages' key for migration.
2586
2634
  */
2587
2635
  load(): Promise<void>;
2588
2636
  /**
@@ -2609,10 +2657,28 @@ declare class CommunicationsModule {
2609
2657
  * Get unread count
2610
2658
  */
2611
2659
  getUnreadCount(peerPubkey?: string): number;
2660
+ /**
2661
+ * Get a page of messages from a conversation (for lazy loading).
2662
+ * Returns messages in chronological order with a cursor for loading older messages.
2663
+ */
2664
+ getConversationPage(peerPubkey: string, options?: GetConversationPageOptions): ConversationPage;
2665
+ /**
2666
+ * Delete all messages in a conversation with a peer
2667
+ */
2668
+ deleteConversation(peerPubkey: string): Promise<void>;
2612
2669
  /**
2613
2670
  * Send typing indicator to a peer
2614
2671
  */
2615
2672
  sendTypingIndicator(peerPubkey: string): Promise<void>;
2673
+ /**
2674
+ * Send a composing indicator to a peer.
2675
+ * Fire-and-forget — does not save to message history.
2676
+ */
2677
+ sendComposingIndicator(recipientPubkeyOrNametag: string): Promise<void>;
2678
+ /**
2679
+ * Subscribe to incoming composing indicators
2680
+ */
2681
+ onComposingIndicator(handler: (indicator: ComposingIndicator) => void): () => void;
2616
2682
  /**
2617
2683
  * Subscribe to incoming DMs
2618
2684
  */
@@ -2634,6 +2700,7 @@ declare class CommunicationsModule {
2634
2700
  */
2635
2701
  onBroadcast(handler: (message: BroadcastMessage) => void): () => void;
2636
2702
  private handleIncomingMessage;
2703
+ private handleComposingIndicator;
2637
2704
  private handleIncomingBroadcast;
2638
2705
  private save;
2639
2706
  private pruneIfNeeded;
@@ -2761,6 +2828,146 @@ declare class GroupChatModule {
2761
2828
  private randomId;
2762
2829
  }
2763
2830
 
2831
+ /**
2832
+ * Market Module Types
2833
+ * Intent bulletin board for posting and discovering intents,
2834
+ * plus real-time feed subscription.
2835
+ */
2836
+ type IntentType = 'buy' | 'sell' | 'service' | 'announcement' | 'other' | (string & {});
2837
+ type IntentStatus = 'active' | 'closed' | 'expired';
2838
+ interface MarketModuleConfig {
2839
+ /** Market API base URL (default: https://market-api.unicity.network) */
2840
+ apiUrl?: string;
2841
+ /** Request timeout in ms (default: 30000) */
2842
+ timeout?: number;
2843
+ }
2844
+ interface MarketModuleDependencies {
2845
+ identity: FullIdentity;
2846
+ emitEvent: <T extends SphereEventType>(type: T, data: SphereEventMap[T]) => void;
2847
+ }
2848
+ interface PostIntentRequest {
2849
+ description: string;
2850
+ intentType: IntentType;
2851
+ category?: string;
2852
+ price?: number;
2853
+ currency?: string;
2854
+ location?: string;
2855
+ contactHandle?: string;
2856
+ expiresInDays?: number;
2857
+ }
2858
+ interface PostIntentResult {
2859
+ intentId: string;
2860
+ message: string;
2861
+ expiresAt: string;
2862
+ }
2863
+ interface MarketIntent {
2864
+ id: string;
2865
+ intentType: IntentType;
2866
+ category?: string;
2867
+ price?: string;
2868
+ currency: string;
2869
+ location?: string;
2870
+ status: IntentStatus;
2871
+ createdAt: string;
2872
+ expiresAt: string;
2873
+ }
2874
+ interface SearchIntentResult {
2875
+ id: string;
2876
+ score: number;
2877
+ agentNametag?: string;
2878
+ agentPublicKey: string;
2879
+ description: string;
2880
+ intentType: IntentType;
2881
+ category?: string;
2882
+ price?: number;
2883
+ currency: string;
2884
+ location?: string;
2885
+ contactMethod: string;
2886
+ contactHandle?: string;
2887
+ createdAt: string;
2888
+ expiresAt: string;
2889
+ }
2890
+ interface SearchFilters {
2891
+ intentType?: IntentType;
2892
+ category?: string;
2893
+ minPrice?: number;
2894
+ maxPrice?: number;
2895
+ location?: string;
2896
+ /** Minimum similarity score (0–1). Results below this threshold are excluded (client-side). */
2897
+ minScore?: number;
2898
+ }
2899
+ interface SearchOptions {
2900
+ filters?: SearchFilters;
2901
+ limit?: number;
2902
+ }
2903
+ interface SearchResult {
2904
+ intents: SearchIntentResult[];
2905
+ count: number;
2906
+ }
2907
+ /** A listing broadcast on the live feed */
2908
+ interface FeedListing {
2909
+ id: string;
2910
+ title: string;
2911
+ descriptionPreview: string;
2912
+ agentName: string;
2913
+ agentId: number;
2914
+ type: IntentType;
2915
+ createdAt: string;
2916
+ }
2917
+ /** WebSocket message: initial batch of recent listings */
2918
+ interface FeedInitialMessage {
2919
+ type: 'initial';
2920
+ listings: FeedListing[];
2921
+ }
2922
+ /** WebSocket message: single new listing */
2923
+ interface FeedNewMessage {
2924
+ type: 'new';
2925
+ listing: FeedListing;
2926
+ }
2927
+ type FeedMessage = FeedInitialMessage | FeedNewMessage;
2928
+ /** Callback for live feed events */
2929
+ type FeedListener = (message: FeedMessage) => void;
2930
+
2931
+ declare class MarketModule {
2932
+ private readonly apiUrl;
2933
+ private readonly timeout;
2934
+ private identity;
2935
+ private registered;
2936
+ constructor(config?: MarketModuleConfig);
2937
+ /** Called by Sphere after construction */
2938
+ initialize(deps: MarketModuleDependencies): void;
2939
+ /** No-op — stateless module */
2940
+ load(): Promise<void>;
2941
+ /** No-op — stateless module */
2942
+ destroy(): void;
2943
+ /** Post a new intent (agent is auto-registered on first post) */
2944
+ postIntent(intent: PostIntentRequest): Promise<PostIntentResult>;
2945
+ /** Semantic search for intents (public — no auth required) */
2946
+ search(query: string, opts?: SearchOptions): Promise<SearchResult>;
2947
+ /** List own intents (authenticated) */
2948
+ getMyIntents(): Promise<MarketIntent[]>;
2949
+ /** Close (delete) an intent */
2950
+ closeIntent(intentId: string): Promise<void>;
2951
+ /** Fetch the most recent listings via REST (public — no auth required) */
2952
+ getRecentListings(): Promise<FeedListing[]>;
2953
+ /**
2954
+ * Subscribe to the live listing feed via WebSocket.
2955
+ * Returns an unsubscribe function that closes the connection.
2956
+ *
2957
+ * Requires a WebSocket implementation — works natively in browsers
2958
+ * and in Node.js 21+ (or with the `ws` package).
2959
+ */
2960
+ subscribeFeed(listener: FeedListener): () => void;
2961
+ private ensureIdentity;
2962
+ /** Register the agent's public key with the server (idempotent) */
2963
+ private ensureRegistered;
2964
+ private parseResponse;
2965
+ private apiPost;
2966
+ private apiGet;
2967
+ private apiDelete;
2968
+ private apiPublicPost;
2969
+ }
2970
+
2764
2971
  /** Network configurations */
2765
2972
  declare const NETWORKS: {
2766
2973
  readonly mainnet: {
@@ -2904,6 +3111,8 @@ interface SphereCreateOptions {
2904
3111
  network?: NetworkType;
2905
3112
  /** Group chat configuration (NIP-29). Omit to disable groupchat. */
2906
3113
  groupChat?: GroupChatModuleConfig | boolean;
3114
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3115
+ market?: MarketModuleConfig | boolean;
2907
3116
  /** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
2908
3117
  password?: string;
2909
3118
  }
@@ -2929,6 +3138,8 @@ interface SphereLoadOptions {
2929
3138
  network?: NetworkType;
2930
3139
  /** Group chat configuration (NIP-29). Omit to disable groupchat. */
2931
3140
  groupChat?: GroupChatModuleConfig | boolean;
3141
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3142
+ market?: MarketModuleConfig | boolean;
2932
3143
  /** Optional password to decrypt the wallet. Must match the password used during creation. */
2933
3144
  password?: string;
2934
3145
  }
@@ -2962,6 +3173,8 @@ interface SphereImportOptions {
2962
3173
  price?: PriceProvider;
2963
3174
  /** Group chat configuration (NIP-29). Omit to disable groupchat. */
2964
3175
  groupChat?: GroupChatModuleConfig | boolean;
3176
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3177
+ market?: MarketModuleConfig | boolean;
2965
3178
  /** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
2966
3179
  password?: string;
2967
3180
  }
@@ -3009,6 +3222,8 @@ interface SphereInitOptions {
3009
3222
  * - Omit/undefined: No groupchat module
3010
3223
  */
3011
3224
  groupChat?: GroupChatModuleConfig | boolean;
3225
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3226
+ market?: MarketModuleConfig | boolean;
3012
3227
  /** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
3013
3228
  password?: string;
3014
3229
  }
@@ -3048,6 +3263,7 @@ declare class Sphere {
3048
3263
  private _payments;
3049
3264
  private _communications;
3050
3265
  private _groupChat;
3266
+ private _market;
3051
3267
  private eventHandlers;
3052
3268
  private _disabledProviders;
3053
3269
  private _providerEventCleanups;
@@ -3095,6 +3311,13 @@ declare class Sphere {
3095
3311
  * (different input shape: { enabled?, relays? }). Both fill relay URLs from network defaults.
3096
3312
  */
3097
3313
  private static resolveGroupChatConfig;
3314
+ /**
3315
+ * Resolve market module config from Sphere.init() options.
3316
+ * - `true` → enable with default API URL
3317
+ * - `MarketModuleConfig` → pass through
3318
+ * - `undefined` → no market module
3319
+ */
3320
+ private static resolveMarketConfig;
3098
3321
  /**
3099
3322
  * Configure TokenRegistry in the main bundle context.
3100
3323
  *
@@ -3163,6 +3386,8 @@ declare class Sphere {
3163
3386
  get communications(): CommunicationsModule;
3164
3387
  /** Group chat module (NIP-29). Null if not configured. */
3165
3388
  get groupChat(): GroupChatModule | null;
3389
+ /** Market module (intent bulletin board). Null if not configured. */
3390
+ get market(): MarketModule | null;
3166
3391
  /** Current identity (public info only) */
3167
3392
  get identity(): Identity | null;
3168
3393
  /** Is ready */