@unicitylabs/sphere-sdk 0.3.5 → 0.3.7

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.
@@ -685,7 +685,7 @@ interface TrackedAddress extends TrackedAddressEntry {
685
685
  /** Primary nametag (from nametag cache, without @ prefix) */
686
686
  readonly nametag?: string;
687
687
  }
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: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';
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';
689
689
  interface SphereEventMap {
690
690
  'transfer:incoming': IncomingTransfer;
691
691
  'transfer:confirmed': TransferResult;
@@ -696,6 +696,15 @@ interface SphereEventMap {
696
696
  'payment_request:paid': IncomingPaymentRequest$1;
697
697
  'payment_request:response': PaymentRequestResponse;
698
698
  'message:dm': DirectMessage;
699
+ 'message:read': {
700
+ messageIds: string[];
701
+ peerPubkey: string;
702
+ };
703
+ 'message:typing': {
704
+ senderPubkey: string;
705
+ senderNametag?: string;
706
+ timestamp: number;
707
+ };
699
708
  'message:broadcast': BroadcastMessage;
700
709
  'sync:started': {
701
710
  source: string;
@@ -1023,6 +1032,27 @@ interface TransportProvider extends BaseProvider {
1023
1032
  * @returns Unsubscribe function
1024
1033
  */
1025
1034
  onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
1035
+ /**
1036
+ * Send a read receipt for a message
1037
+ * @param recipientTransportPubkey - Transport pubkey of the message sender
1038
+ * @param messageEventId - Event ID of the message being acknowledged
1039
+ */
1040
+ sendReadReceipt?(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
1041
+ /**
1042
+ * Subscribe to incoming read receipts
1043
+ * @returns Unsubscribe function
1044
+ */
1045
+ onReadReceipt?(handler: ReadReceiptHandler): () => void;
1046
+ /**
1047
+ * Send typing indicator to a recipient
1048
+ * @param recipientTransportPubkey - Transport pubkey of the conversation partner
1049
+ */
1050
+ sendTypingIndicator?(recipientTransportPubkey: string): Promise<void>;
1051
+ /**
1052
+ * Subscribe to incoming typing indicators
1053
+ * @returns Unsubscribe function
1054
+ */
1055
+ onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
1026
1056
  /**
1027
1057
  * Get list of configured relay URLs
1028
1058
  */
@@ -1112,6 +1142,10 @@ interface IncomingMessage {
1112
1142
  content: string;
1113
1143
  timestamp: number;
1114
1144
  encrypted: boolean;
1145
+ /** Set when this is a self-wrap replay (sent message recovered from relay) */
1146
+ isSelfWrap?: boolean;
1147
+ /** Recipient pubkey — only present on self-wrap replays */
1148
+ recipientTransportPubkey?: string;
1115
1149
  }
1116
1150
  type MessageHandler = (message: IncomingMessage) => void;
1117
1151
  interface TokenTransferPayload {
@@ -1225,6 +1259,24 @@ interface PeerInfo {
1225
1259
  /** Event timestamp */
1226
1260
  timestamp: number;
1227
1261
  }
1262
+ interface IncomingReadReceipt {
1263
+ /** Transport-specific pubkey of the sender who read the message */
1264
+ senderTransportPubkey: string;
1265
+ /** Event ID of the message that was read */
1266
+ messageEventId: string;
1267
+ /** Timestamp */
1268
+ timestamp: number;
1269
+ }
1270
+ type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
1271
+ interface IncomingTypingIndicator {
1272
+ /** Transport-specific pubkey of the sender who is typing */
1273
+ senderTransportPubkey: string;
1274
+ /** Sender's nametag (if known) */
1275
+ senderNametag?: string;
1276
+ /** Timestamp */
1277
+ timestamp: number;
1278
+ }
1279
+ type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
1228
1280
 
1229
1281
  /**
1230
1282
  * L1 Payments Sub-Module
@@ -2556,6 +2608,10 @@ declare class CommunicationsModule {
2556
2608
  * Get unread count
2557
2609
  */
2558
2610
  getUnreadCount(peerPubkey?: string): number;
2611
+ /**
2612
+ * Send typing indicator to a peer
2613
+ */
2614
+ sendTypingIndicator(peerPubkey: string): Promise<void>;
2559
2615
  /**
2560
2616
  * Subscribe to incoming DMs
2561
2617
  */
@@ -2704,6 +2760,154 @@ declare class GroupChatModule {
2704
2760
  private randomId;
2705
2761
  }
2706
2762
 
2763
+ /**
2764
+ * Market Module Types
2765
+ * Intent bulletin board for posting and discovering intents,
2766
+ * plus real-time feed subscription.
2767
+ */
2768
+ type IntentType = 'buy' | 'sell' | 'service' | 'announcement' | 'other' | (string & {});
2769
+ type IntentStatus = 'active' | 'closed' | 'expired';
2770
+ interface MarketModuleConfig {
2771
+ /** Market API base URL (default: https://market-api.unicity.network) */
2772
+ apiUrl?: string;
2773
+ /** Request timeout in ms (default: 30000) */
2774
+ timeout?: number;
2775
+ }
2776
+ interface MarketModuleDependencies {
2777
+ identity: FullIdentity;
2778
+ emitEvent: <T extends SphereEventType>(type: T, data: SphereEventMap[T]) => void;
2779
+ }
2780
+ interface PostIntentRequest {
2781
+ description: string;
2782
+ intentType: IntentType;
2783
+ category?: string;
2784
+ price?: number;
2785
+ currency?: string;
2786
+ location?: string;
2787
+ contactHandle?: string;
2788
+ expiresInDays?: number;
2789
+ }
2790
+ interface PostIntentResult {
2791
+ intentId: string;
2792
+ message: string;
2793
+ expiresAt: string;
2794
+ }
2795
+ interface MarketIntent {
2796
+ id: string;
2797
+ intentType: IntentType;
2798
+ category?: string;
2799
+ price?: string;
2800
+ currency: string;
2801
+ location?: string;
2802
+ status: IntentStatus;
2803
+ createdAt: string;
2804
+ expiresAt: string;
2805
+ }
2806
+ interface SearchIntentResult {
2807
+ id: string;
2808
+ score: number;
2809
+ agentNametag?: string;
2810
+ agentPublicKey: string;
2811
+ description: string;
2812
+ intentType: IntentType;
2813
+ category?: string;
2814
+ price?: number;
2815
+ currency: string;
2816
+ location?: string;
2817
+ contactMethod: string;
2818
+ contactHandle?: string;
2819
+ createdAt: string;
2820
+ expiresAt: string;
2821
+ }
2822
+ interface SearchFilters {
2823
+ intentType?: IntentType;
2824
+ category?: string;
2825
+ minPrice?: number;
2826
+ maxPrice?: number;
2827
+ location?: string;
2828
+ /** Minimum similarity score (0–1). Results below this threshold are excluded (client-side). */
2829
+ minScore?: number;
2830
+ }
2831
+ interface SearchOptions {
2832
+ filters?: SearchFilters;
2833
+ limit?: number;
2834
+ }
2835
+ interface SearchResult {
2836
+ intents: SearchIntentResult[];
2837
+ count: number;
2838
+ }
2839
+ /** A listing broadcast on the live feed */
2840
+ interface FeedListing {
2841
+ id: string;
2842
+ title: string;
2843
+ descriptionPreview: string;
2844
+ agentName: string;
2845
+ agentId: number;
2846
+ type: IntentType;
2847
+ createdAt: string;
2848
+ }
2849
+ /** WebSocket message: initial batch of recent listings */
2850
+ interface FeedInitialMessage {
2851
+ type: 'initial';
2852
+ listings: FeedListing[];
2853
+ }
2854
+ /** WebSocket message: single new listing */
2855
+ interface FeedNewMessage {
2856
+ type: 'new';
2857
+ listing: FeedListing;
2858
+ }
2859
+ type FeedMessage = FeedInitialMessage | FeedNewMessage;
2860
+ /** Callback for live feed events */
2861
+ type FeedListener = (message: FeedMessage) => void;
2862
+
2863
+ /**
2864
+ * Market Module
2865
+ *
2866
+ * Intent bulletin board — post and discover intents (buy, sell,
2867
+ * service, announcement, other) with secp256k1-signed requests
2868
+ * tied to the wallet identity. Includes real-time feed via WebSocket.
2869
+ */
2870
+
2871
+ declare class MarketModule {
2872
+ private readonly apiUrl;
2873
+ private readonly timeout;
2874
+ private identity;
2875
+ private registered;
2876
+ constructor(config?: MarketModuleConfig);
2877
+ /** Called by Sphere after construction */
2878
+ initialize(deps: MarketModuleDependencies): void;
2879
+ /** No-op — stateless module */
2880
+ load(): Promise<void>;
2881
+ /** No-op — stateless module */
2882
+ destroy(): void;
2883
+ /** Post a new intent (agent is auto-registered on first post) */
2884
+ postIntent(intent: PostIntentRequest): Promise<PostIntentResult>;
2885
+ /** Semantic search for intents (public — no auth required) */
2886
+ search(query: string, opts?: SearchOptions): Promise<SearchResult>;
2887
+ /** List own intents (authenticated) */
2888
+ getMyIntents(): Promise<MarketIntent[]>;
2889
+ /** Close (delete) an intent */
2890
+ closeIntent(intentId: string): Promise<void>;
2891
+ /** Fetch the most recent listings via REST (public — no auth required) */
2892
+ getRecentListings(): Promise<FeedListing[]>;
2893
+ /**
2894
+ * Subscribe to the live listing feed via WebSocket.
2895
+ * Returns an unsubscribe function that closes the connection.
2896
+ *
2897
+ * Requires a WebSocket implementation — works natively in browsers
2898
+ * and in Node.js 21+ (or with the `ws` package).
2899
+ */
2900
+ subscribeFeed(listener: FeedListener): () => void;
2901
+ private ensureIdentity;
2902
+ /** Register the agent's public key with the server (idempotent) */
2903
+ private ensureRegistered;
2904
+ private parseResponse;
2905
+ private apiPost;
2906
+ private apiGet;
2907
+ private apiDelete;
2908
+ private apiPublicPost;
2909
+ }
2910
+
2707
2911
  /** Network configurations */
2708
2912
  declare const NETWORKS: {
2709
2913
  readonly mainnet: {
@@ -2713,6 +2917,7 @@ declare const NETWORKS: {
2713
2917
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2714
2918
  readonly electrumUrl: "wss://fulcrum.alpha.unicity.network:50004";
2715
2919
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2920
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2716
2921
  };
2717
2922
  readonly testnet: {
2718
2923
  readonly name: "Testnet";
@@ -2721,6 +2926,7 @@ declare const NETWORKS: {
2721
2926
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2722
2927
  readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
2723
2928
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2929
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2724
2930
  };
2725
2931
  readonly dev: {
2726
2932
  readonly name: "Development";
@@ -2729,6 +2935,7 @@ declare const NETWORKS: {
2729
2935
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2730
2936
  readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
2731
2937
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2938
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2732
2939
  };
2733
2940
  };
2734
2941
  type NetworkType = keyof typeof NETWORKS;
@@ -2846,6 +3053,8 @@ interface SphereCreateOptions {
2846
3053
  groupChat?: GroupChatModuleConfig | boolean;
2847
3054
  /** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
2848
3055
  password?: string;
3056
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3057
+ market?: MarketModuleConfig | boolean;
2849
3058
  }
2850
3059
  /** Options for loading existing wallet */
2851
3060
  interface SphereLoadOptions {
@@ -2871,6 +3080,8 @@ interface SphereLoadOptions {
2871
3080
  groupChat?: GroupChatModuleConfig | boolean;
2872
3081
  /** Optional password to decrypt the wallet. Must match the password used during creation. */
2873
3082
  password?: string;
3083
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3084
+ market?: MarketModuleConfig | boolean;
2874
3085
  }
2875
3086
  /** Options for importing a wallet */
2876
3087
  interface SphereImportOptions {
@@ -2904,6 +3115,8 @@ interface SphereImportOptions {
2904
3115
  groupChat?: GroupChatModuleConfig | boolean;
2905
3116
  /** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
2906
3117
  password?: string;
3118
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3119
+ market?: MarketModuleConfig | boolean;
2907
3120
  }
2908
3121
  /** L1 (ALPHA blockchain) configuration */
2909
3122
  interface L1Config {
@@ -2951,6 +3164,8 @@ interface SphereInitOptions {
2951
3164
  groupChat?: GroupChatModuleConfig | boolean;
2952
3165
  /** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
2953
3166
  password?: string;
3167
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3168
+ market?: MarketModuleConfig | boolean;
2954
3169
  }
2955
3170
  /** Result of init operation */
2956
3171
  interface SphereInitResult {
@@ -2988,6 +3203,7 @@ declare class Sphere {
2988
3203
  private _payments;
2989
3204
  private _communications;
2990
3205
  private _groupChat;
3206
+ private _market;
2991
3207
  private eventHandlers;
2992
3208
  private _disabledProviders;
2993
3209
  private _providerEventCleanups;
@@ -3035,6 +3251,13 @@ declare class Sphere {
3035
3251
  * (different input shape: { enabled?, relays? }). Both fill relay URLs from network defaults.
3036
3252
  */
3037
3253
  private static resolveGroupChatConfig;
3254
+ /**
3255
+ * Resolve market module config from Sphere.init() options.
3256
+ * - `true` → enable with default API URL
3257
+ * - `MarketModuleConfig` → pass through with defaults
3258
+ * - `undefined` → no market module
3259
+ */
3260
+ private static resolveMarketConfig;
3038
3261
  /**
3039
3262
  * Create new wallet with mnemonic
3040
3263
  */
@@ -3093,6 +3316,8 @@ declare class Sphere {
3093
3316
  get communications(): CommunicationsModule;
3094
3317
  /** Group chat module (NIP-29). Null if not configured. */
3095
3318
  get groupChat(): GroupChatModule | null;
3319
+ /** Market module (intent bulletin board). Null if not configured. */
3320
+ get market(): MarketModule | null;
3096
3321
  /** Current identity (public info only) */
3097
3322
  get identity(): Identity | null;
3098
3323
  /** Is ready */
@@ -685,7 +685,7 @@ interface TrackedAddress extends TrackedAddressEntry {
685
685
  /** Primary nametag (from nametag cache, without @ prefix) */
686
686
  readonly nametag?: string;
687
687
  }
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: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';
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';
689
689
  interface SphereEventMap {
690
690
  'transfer:incoming': IncomingTransfer;
691
691
  'transfer:confirmed': TransferResult;
@@ -696,6 +696,15 @@ interface SphereEventMap {
696
696
  'payment_request:paid': IncomingPaymentRequest$1;
697
697
  'payment_request:response': PaymentRequestResponse;
698
698
  'message:dm': DirectMessage;
699
+ 'message:read': {
700
+ messageIds: string[];
701
+ peerPubkey: string;
702
+ };
703
+ 'message:typing': {
704
+ senderPubkey: string;
705
+ senderNametag?: string;
706
+ timestamp: number;
707
+ };
699
708
  'message:broadcast': BroadcastMessage;
700
709
  'sync:started': {
701
710
  source: string;
@@ -1023,6 +1032,27 @@ interface TransportProvider extends BaseProvider {
1023
1032
  * @returns Unsubscribe function
1024
1033
  */
1025
1034
  onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
1035
+ /**
1036
+ * Send a read receipt for a message
1037
+ * @param recipientTransportPubkey - Transport pubkey of the message sender
1038
+ * @param messageEventId - Event ID of the message being acknowledged
1039
+ */
1040
+ sendReadReceipt?(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
1041
+ /**
1042
+ * Subscribe to incoming read receipts
1043
+ * @returns Unsubscribe function
1044
+ */
1045
+ onReadReceipt?(handler: ReadReceiptHandler): () => void;
1046
+ /**
1047
+ * Send typing indicator to a recipient
1048
+ * @param recipientTransportPubkey - Transport pubkey of the conversation partner
1049
+ */
1050
+ sendTypingIndicator?(recipientTransportPubkey: string): Promise<void>;
1051
+ /**
1052
+ * Subscribe to incoming typing indicators
1053
+ * @returns Unsubscribe function
1054
+ */
1055
+ onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
1026
1056
  /**
1027
1057
  * Get list of configured relay URLs
1028
1058
  */
@@ -1112,6 +1142,10 @@ interface IncomingMessage {
1112
1142
  content: string;
1113
1143
  timestamp: number;
1114
1144
  encrypted: boolean;
1145
+ /** Set when this is a self-wrap replay (sent message recovered from relay) */
1146
+ isSelfWrap?: boolean;
1147
+ /** Recipient pubkey — only present on self-wrap replays */
1148
+ recipientTransportPubkey?: string;
1115
1149
  }
1116
1150
  type MessageHandler = (message: IncomingMessage) => void;
1117
1151
  interface TokenTransferPayload {
@@ -1225,6 +1259,24 @@ interface PeerInfo {
1225
1259
  /** Event timestamp */
1226
1260
  timestamp: number;
1227
1261
  }
1262
+ interface IncomingReadReceipt {
1263
+ /** Transport-specific pubkey of the sender who read the message */
1264
+ senderTransportPubkey: string;
1265
+ /** Event ID of the message that was read */
1266
+ messageEventId: string;
1267
+ /** Timestamp */
1268
+ timestamp: number;
1269
+ }
1270
+ type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
1271
+ interface IncomingTypingIndicator {
1272
+ /** Transport-specific pubkey of the sender who is typing */
1273
+ senderTransportPubkey: string;
1274
+ /** Sender's nametag (if known) */
1275
+ senderNametag?: string;
1276
+ /** Timestamp */
1277
+ timestamp: number;
1278
+ }
1279
+ type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
1228
1280
 
1229
1281
  /**
1230
1282
  * L1 Payments Sub-Module
@@ -2556,6 +2608,10 @@ declare class CommunicationsModule {
2556
2608
  * Get unread count
2557
2609
  */
2558
2610
  getUnreadCount(peerPubkey?: string): number;
2611
+ /**
2612
+ * Send typing indicator to a peer
2613
+ */
2614
+ sendTypingIndicator(peerPubkey: string): Promise<void>;
2559
2615
  /**
2560
2616
  * Subscribe to incoming DMs
2561
2617
  */
@@ -2704,6 +2760,154 @@ declare class GroupChatModule {
2704
2760
  private randomId;
2705
2761
  }
2706
2762
 
2763
+ /**
2764
+ * Market Module Types
2765
+ * Intent bulletin board for posting and discovering intents,
2766
+ * plus real-time feed subscription.
2767
+ */
2768
+ type IntentType = 'buy' | 'sell' | 'service' | 'announcement' | 'other' | (string & {});
2769
+ type IntentStatus = 'active' | 'closed' | 'expired';
2770
+ interface MarketModuleConfig {
2771
+ /** Market API base URL (default: https://market-api.unicity.network) */
2772
+ apiUrl?: string;
2773
+ /** Request timeout in ms (default: 30000) */
2774
+ timeout?: number;
2775
+ }
2776
+ interface MarketModuleDependencies {
2777
+ identity: FullIdentity;
2778
+ emitEvent: <T extends SphereEventType>(type: T, data: SphereEventMap[T]) => void;
2779
+ }
2780
+ interface PostIntentRequest {
2781
+ description: string;
2782
+ intentType: IntentType;
2783
+ category?: string;
2784
+ price?: number;
2785
+ currency?: string;
2786
+ location?: string;
2787
+ contactHandle?: string;
2788
+ expiresInDays?: number;
2789
+ }
2790
+ interface PostIntentResult {
2791
+ intentId: string;
2792
+ message: string;
2793
+ expiresAt: string;
2794
+ }
2795
+ interface MarketIntent {
2796
+ id: string;
2797
+ intentType: IntentType;
2798
+ category?: string;
2799
+ price?: string;
2800
+ currency: string;
2801
+ location?: string;
2802
+ status: IntentStatus;
2803
+ createdAt: string;
2804
+ expiresAt: string;
2805
+ }
2806
+ interface SearchIntentResult {
2807
+ id: string;
2808
+ score: number;
2809
+ agentNametag?: string;
2810
+ agentPublicKey: string;
2811
+ description: string;
2812
+ intentType: IntentType;
2813
+ category?: string;
2814
+ price?: number;
2815
+ currency: string;
2816
+ location?: string;
2817
+ contactMethod: string;
2818
+ contactHandle?: string;
2819
+ createdAt: string;
2820
+ expiresAt: string;
2821
+ }
2822
+ interface SearchFilters {
2823
+ intentType?: IntentType;
2824
+ category?: string;
2825
+ minPrice?: number;
2826
+ maxPrice?: number;
2827
+ location?: string;
2828
+ /** Minimum similarity score (0–1). Results below this threshold are excluded (client-side). */
2829
+ minScore?: number;
2830
+ }
2831
+ interface SearchOptions {
2832
+ filters?: SearchFilters;
2833
+ limit?: number;
2834
+ }
2835
+ interface SearchResult {
2836
+ intents: SearchIntentResult[];
2837
+ count: number;
2838
+ }
2839
+ /** A listing broadcast on the live feed */
2840
+ interface FeedListing {
2841
+ id: string;
2842
+ title: string;
2843
+ descriptionPreview: string;
2844
+ agentName: string;
2845
+ agentId: number;
2846
+ type: IntentType;
2847
+ createdAt: string;
2848
+ }
2849
+ /** WebSocket message: initial batch of recent listings */
2850
+ interface FeedInitialMessage {
2851
+ type: 'initial';
2852
+ listings: FeedListing[];
2853
+ }
2854
+ /** WebSocket message: single new listing */
2855
+ interface FeedNewMessage {
2856
+ type: 'new';
2857
+ listing: FeedListing;
2858
+ }
2859
+ type FeedMessage = FeedInitialMessage | FeedNewMessage;
2860
+ /** Callback for live feed events */
2861
+ type FeedListener = (message: FeedMessage) => void;
2862
+
2863
+ /**
2864
+ * Market Module
2865
+ *
2866
+ * Intent bulletin board — post and discover intents (buy, sell,
2867
+ * service, announcement, other) with secp256k1-signed requests
2868
+ * tied to the wallet identity. Includes real-time feed via WebSocket.
2869
+ */
2870
+
2871
+ declare class MarketModule {
2872
+ private readonly apiUrl;
2873
+ private readonly timeout;
2874
+ private identity;
2875
+ private registered;
2876
+ constructor(config?: MarketModuleConfig);
2877
+ /** Called by Sphere after construction */
2878
+ initialize(deps: MarketModuleDependencies): void;
2879
+ /** No-op — stateless module */
2880
+ load(): Promise<void>;
2881
+ /** No-op — stateless module */
2882
+ destroy(): void;
2883
+ /** Post a new intent (agent is auto-registered on first post) */
2884
+ postIntent(intent: PostIntentRequest): Promise<PostIntentResult>;
2885
+ /** Semantic search for intents (public — no auth required) */
2886
+ search(query: string, opts?: SearchOptions): Promise<SearchResult>;
2887
+ /** List own intents (authenticated) */
2888
+ getMyIntents(): Promise<MarketIntent[]>;
2889
+ /** Close (delete) an intent */
2890
+ closeIntent(intentId: string): Promise<void>;
2891
+ /** Fetch the most recent listings via REST (public — no auth required) */
2892
+ getRecentListings(): Promise<FeedListing[]>;
2893
+ /**
2894
+ * Subscribe to the live listing feed via WebSocket.
2895
+ * Returns an unsubscribe function that closes the connection.
2896
+ *
2897
+ * Requires a WebSocket implementation — works natively in browsers
2898
+ * and in Node.js 21+ (or with the `ws` package).
2899
+ */
2900
+ subscribeFeed(listener: FeedListener): () => void;
2901
+ private ensureIdentity;
2902
+ /** Register the agent's public key with the server (idempotent) */
2903
+ private ensureRegistered;
2904
+ private parseResponse;
2905
+ private apiPost;
2906
+ private apiGet;
2907
+ private apiDelete;
2908
+ private apiPublicPost;
2909
+ }
2910
+
2707
2911
  /** Network configurations */
2708
2912
  declare const NETWORKS: {
2709
2913
  readonly mainnet: {
@@ -2713,6 +2917,7 @@ declare const NETWORKS: {
2713
2917
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2714
2918
  readonly electrumUrl: "wss://fulcrum.alpha.unicity.network:50004";
2715
2919
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2920
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2716
2921
  };
2717
2922
  readonly testnet: {
2718
2923
  readonly name: "Testnet";
@@ -2721,6 +2926,7 @@ declare const NETWORKS: {
2721
2926
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2722
2927
  readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
2723
2928
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2929
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2724
2930
  };
2725
2931
  readonly dev: {
2726
2932
  readonly name: "Development";
@@ -2729,6 +2935,7 @@ declare const NETWORKS: {
2729
2935
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2730
2936
  readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
2731
2937
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2938
+ readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2732
2939
  };
2733
2940
  };
2734
2941
  type NetworkType = keyof typeof NETWORKS;
@@ -2846,6 +3053,8 @@ interface SphereCreateOptions {
2846
3053
  groupChat?: GroupChatModuleConfig | boolean;
2847
3054
  /** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
2848
3055
  password?: string;
3056
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3057
+ market?: MarketModuleConfig | boolean;
2849
3058
  }
2850
3059
  /** Options for loading existing wallet */
2851
3060
  interface SphereLoadOptions {
@@ -2871,6 +3080,8 @@ interface SphereLoadOptions {
2871
3080
  groupChat?: GroupChatModuleConfig | boolean;
2872
3081
  /** Optional password to decrypt the wallet. Must match the password used during creation. */
2873
3082
  password?: string;
3083
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3084
+ market?: MarketModuleConfig | boolean;
2874
3085
  }
2875
3086
  /** Options for importing a wallet */
2876
3087
  interface SphereImportOptions {
@@ -2904,6 +3115,8 @@ interface SphereImportOptions {
2904
3115
  groupChat?: GroupChatModuleConfig | boolean;
2905
3116
  /** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
2906
3117
  password?: string;
3118
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3119
+ market?: MarketModuleConfig | boolean;
2907
3120
  }
2908
3121
  /** L1 (ALPHA blockchain) configuration */
2909
3122
  interface L1Config {
@@ -2951,6 +3164,8 @@ interface SphereInitOptions {
2951
3164
  groupChat?: GroupChatModuleConfig | boolean;
2952
3165
  /** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
2953
3166
  password?: string;
3167
+ /** Market module configuration. true = enable with defaults, object = custom config. */
3168
+ market?: MarketModuleConfig | boolean;
2954
3169
  }
2955
3170
  /** Result of init operation */
2956
3171
  interface SphereInitResult {
@@ -2988,6 +3203,7 @@ declare class Sphere {
2988
3203
  private _payments;
2989
3204
  private _communications;
2990
3205
  private _groupChat;
3206
+ private _market;
2991
3207
  private eventHandlers;
2992
3208
  private _disabledProviders;
2993
3209
  private _providerEventCleanups;
@@ -3035,6 +3251,13 @@ declare class Sphere {
3035
3251
  * (different input shape: { enabled?, relays? }). Both fill relay URLs from network defaults.
3036
3252
  */
3037
3253
  private static resolveGroupChatConfig;
3254
+ /**
3255
+ * Resolve market module config from Sphere.init() options.
3256
+ * - `true` → enable with default API URL
3257
+ * - `MarketModuleConfig` → pass through with defaults
3258
+ * - `undefined` → no market module
3259
+ */
3260
+ private static resolveMarketConfig;
3038
3261
  /**
3039
3262
  * Create new wallet with mnemonic
3040
3263
  */
@@ -3093,6 +3316,8 @@ declare class Sphere {
3093
3316
  get communications(): CommunicationsModule;
3094
3317
  /** Group chat module (NIP-29). Null if not configured. */
3095
3318
  get groupChat(): GroupChatModule | null;
3319
+ /** Market module (intent bulletin board). Null if not configured. */
3320
+ get market(): MarketModule | null;
3096
3321
  /** Current identity (public info only) */
3097
3322
  get identity(): Identity | null;
3098
3323
  /** Is ready */