@unicitylabs/sphere-sdk 0.1.9 → 0.2.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.
@@ -33,6 +33,20 @@ interface Identity {
33
33
  interface FullIdentity extends Identity {
34
34
  readonly privateKey: string;
35
35
  }
36
+ /**
37
+ * Minimal data stored in persistent storage for a tracked address.
38
+ * Only contains user state — derived fields are computed on load.
39
+ */
40
+ interface TrackedAddressEntry {
41
+ /** HD derivation index (0, 1, 2, ...) */
42
+ readonly index: number;
43
+ /** Whether this address is hidden from UI display */
44
+ hidden: boolean;
45
+ /** Timestamp (ms) when this address was first activated */
46
+ readonly createdAt: number;
47
+ /** Timestamp (ms) of last modification */
48
+ updatedAt: number;
49
+ }
36
50
 
37
51
  /**
38
52
  * Storage Provider Interface
@@ -72,6 +86,14 @@ interface StorageProvider extends BaseProvider {
72
86
  * Clear all keys with optional prefix filter
73
87
  */
74
88
  clear(prefix?: string): Promise<void>;
89
+ /**
90
+ * Save tracked addresses (only user state: index, hidden, timestamps)
91
+ */
92
+ saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
93
+ /**
94
+ * Load tracked addresses
95
+ */
96
+ loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
75
97
  }
76
98
  /**
77
99
  * Storage result types
@@ -236,6 +258,8 @@ declare class FileStorageProvider implements StorageProvider {
236
258
  has(key: string): Promise<boolean>;
237
259
  keys(prefix?: string): Promise<string[]>;
238
260
  clear(prefix?: string): Promise<void>;
261
+ saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
262
+ loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
239
263
  /**
240
264
  * Get full storage key with address prefix for per-address keys
241
265
  */
@@ -294,9 +318,10 @@ declare function createFileTokenStorageProvider(config: FileTokenStorageConfig |
294
318
  */
295
319
  interface TransportProvider extends BaseProvider {
296
320
  /**
297
- * Set identity for signing/encryption
321
+ * Set identity for signing/encryption.
322
+ * If the transport is already connected, reconnects with the new identity.
298
323
  */
299
- setIdentity(identity: FullIdentity): void;
324
+ setIdentity(identity: FullIdentity): void | Promise<void>;
300
325
  /**
301
326
  * Send encrypted direct message
302
327
  * @param recipientTransportPubkey - Transport-specific pubkey for messaging
@@ -319,15 +344,36 @@ interface TransportProvider extends BaseProvider {
319
344
  * @returns Unsubscribe function
320
345
  */
321
346
  onTokenTransfer(handler: TokenTransferHandler): () => void;
347
+ /**
348
+ * Resolve any identifier to full peer information.
349
+ * Accepts @nametag, bare nametag, DIRECT://, PROXY://, L1 address, chain pubkey, or transport pubkey.
350
+ * @param identifier - Any supported identifier format
351
+ * @returns PeerInfo or null if not found
352
+ */
353
+ resolve?(identifier: string): Promise<PeerInfo | null>;
322
354
  /**
323
355
  * Resolve nametag to public key
324
356
  */
325
357
  resolveNametag?(nametag: string): Promise<string | null>;
326
358
  /**
327
- * Resolve nametag to full address information
359
+ * Resolve nametag to full peer information
328
360
  * Returns transportPubkey, chainPubkey, l1Address, directAddress, proxyAddress
329
361
  */
330
- resolveNametagInfo?(nametag: string): Promise<NametagInfo | null>;
362
+ resolveNametagInfo?(nametag: string): Promise<PeerInfo | null>;
363
+ /**
364
+ * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
365
+ * Performs reverse lookup: address → binding event → PeerInfo.
366
+ * @param address - L3 address (DIRECT://... or PROXY://...) or L1 address (alpha1...)
367
+ * @returns PeerInfo or null if no binding found for this address
368
+ */
369
+ resolveAddressInfo?(address: string): Promise<PeerInfo | null>;
370
+ /**
371
+ * Resolve transport pubkey to full peer info.
372
+ * Queries binding events authored by the given transport pubkey.
373
+ * @param transportPubkey - Transport-specific pubkey (e.g. 64-char hex string)
374
+ * @returns PeerInfo or null if no binding found
375
+ */
376
+ resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
331
377
  /**
332
378
  * Recover nametag for current identity by decrypting stored encrypted nametag
333
379
  * Used after wallet import to recover associated nametag
@@ -335,14 +381,20 @@ interface TransportProvider extends BaseProvider {
335
381
  */
336
382
  recoverNametag?(): Promise<string | null>;
337
383
  /**
384
+ * Publish identity binding event.
385
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
386
+ * With nametag: adds nametag hash, proxy address, encrypted nametag for recovery.
387
+ * Uses parameterized replaceable event (kind 30078, d=hash(nostrPubkey)).
388
+ * @returns true if successful, false if nametag is taken by another pubkey
389
+ */
390
+ publishIdentityBinding?(chainPubkey: string, l1Address: string, directAddress: string, nametag?: string): Promise<boolean>;
391
+ /**
392
+ * @deprecated Use publishIdentityBinding instead
338
393
  * Register a nametag for this identity
339
- * @param nametag - Nametag to register
340
- * @param chainPubkey - 33-byte compressed secp256k1 public key (for L1/L3)
341
- * @param directAddress - L3 DIRECT address (DIRECT://...)
342
- * @returns true if successful, false if already taken
343
394
  */
344
395
  registerNametag?(nametag: string, chainPubkey: string, directAddress: string): Promise<boolean>;
345
396
  /**
397
+ * @deprecated Use publishIdentityBinding instead
346
398
  * Publish nametag binding
347
399
  */
348
400
  publishNametag?(nametag: string, address: string): Promise<void>;
@@ -402,7 +454,54 @@ interface TransportProvider extends BaseProvider {
402
454
  * Check if a relay is currently connected
403
455
  */
404
456
  isRelayConnected?(relayUrl: string): boolean;
457
+ /**
458
+ * Send an instant split bundle to a recipient.
459
+ * This is a specialized method for INSTANT_SPLIT V5 bundles.
460
+ *
461
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
462
+ * @param bundle - The InstantSplitBundleV5 to send
463
+ * @returns Event ID
464
+ */
465
+ sendInstantSplitBundle?(recipientTransportPubkey: string, bundle: InstantSplitBundlePayload): Promise<string>;
466
+ /**
467
+ * Subscribe to incoming instant split bundles.
468
+ *
469
+ * @param handler - Handler for received bundles
470
+ * @returns Unsubscribe function
471
+ */
472
+ onInstantSplitReceived?(handler: InstantSplitBundleHandler): () => void;
405
473
  }
474
+ /**
475
+ * Payload for sending instant split bundles
476
+ */
477
+ interface InstantSplitBundlePayload {
478
+ /** The bundle JSON string (InstantSplitBundleV5 serialized) */
479
+ bundle: string;
480
+ /** Optional memo */
481
+ memo?: string;
482
+ /** Sender info */
483
+ sender?: {
484
+ transportPubkey: string;
485
+ nametag?: string;
486
+ };
487
+ }
488
+ /**
489
+ * Incoming instant split bundle
490
+ */
491
+ interface IncomingInstantSplitBundle {
492
+ /** Event ID */
493
+ id: string;
494
+ /** Transport-specific pubkey of sender */
495
+ senderTransportPubkey: string;
496
+ /** The bundle JSON string */
497
+ bundle: string;
498
+ /** Timestamp */
499
+ timestamp: number;
500
+ }
501
+ /**
502
+ * Handler for instant split bundles
503
+ */
504
+ type InstantSplitBundleHandler = (bundle: IncomingInstantSplitBundle) => void;
406
505
  interface IncomingMessage {
407
506
  id: string;
408
507
  /** Transport-specific pubkey of sender */
@@ -511,12 +610,13 @@ interface TransportEvent {
511
610
  }
512
611
  type TransportEventCallback = (event: TransportEvent) => void;
513
612
  /**
514
- * Full nametag address information
515
- * Used for resolving nametag to all address formats
613
+ * Resolved peer identity information.
614
+ * Returned by resolve methods contains all public address formats for a peer.
615
+ * Fields nametag and proxyAddress are optional (only present if nametag is registered).
516
616
  */
517
- interface NametagInfo {
518
- /** Nametag name (without @) */
519
- nametag: string;
617
+ interface PeerInfo {
618
+ /** Nametag name (without @), if registered */
619
+ nametag?: string;
520
620
  /** Transport-specific pubkey (for messaging/encryption) */
521
621
  transportPubkey: string;
522
622
  /** 33-byte compressed secp256k1 public key (for L3 chain) */
@@ -525,8 +625,8 @@ interface NametagInfo {
525
625
  l1Address: string;
526
626
  /** L3 DIRECT address (DIRECT://...) */
527
627
  directAddress: string;
528
- /** L3 PROXY address derived from nametag hash (PROXY:...) */
529
- proxyAddress: string;
628
+ /** L3 PROXY address derived from nametag hash (PROXY:...), only if nametag registered */
629
+ proxyAddress?: string;
530
630
  /** Event timestamp */
531
631
  timestamp: number;
532
632
  }
@@ -643,7 +743,7 @@ declare class NostrTransportProvider implements TransportProvider {
643
743
  * Check if a relay is currently connected
644
744
  */
645
745
  isRelayConnected(relayUrl: string): boolean;
646
- setIdentity(identity: FullIdentity): void;
746
+ setIdentity(identity: FullIdentity): Promise<void>;
647
747
  /**
648
748
  * Get the Nostr-format public key (32 bytes / 64 hex chars)
649
749
  * This is the x-coordinate only, without the 02/03 prefix.
@@ -657,14 +757,42 @@ declare class NostrTransportProvider implements TransportProvider {
657
757
  onPaymentRequest(handler: PaymentRequestHandler): () => void;
658
758
  sendPaymentRequestResponse(recipientPubkey: string, payload: PaymentRequestResponsePayload): Promise<string>;
659
759
  onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void;
760
+ /**
761
+ * Resolve any identifier to full peer information.
762
+ * Routes to the appropriate specific resolve method based on identifier format.
763
+ */
764
+ resolve(identifier: string): Promise<PeerInfo | null>;
660
765
  resolveNametag(nametag: string): Promise<string | null>;
661
- resolveNametagInfo(nametag: string): Promise<NametagInfo | null>;
766
+ resolveNametagInfo(nametag: string): Promise<PeerInfo | null>;
767
+ /**
768
+ * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
769
+ * Performs reverse lookup: hash(address) → query '#t' tag → parse binding event.
770
+ * Works with both new identity binding events and legacy nametag binding events.
771
+ */
772
+ resolveAddressInfo(address: string): Promise<PeerInfo | null>;
773
+ /**
774
+ * Resolve transport pubkey (Nostr pubkey) to full peer info.
775
+ * Queries binding events authored by the given pubkey.
776
+ */
777
+ resolveTransportPubkeyInfo(transportPubkey: string): Promise<PeerInfo | null>;
662
778
  /**
663
779
  * Recover nametag for the current identity by searching for encrypted nametag events
664
780
  * Used after wallet import to recover associated nametag
665
781
  * @returns Decrypted nametag or null if none found
666
782
  */
667
783
  recoverNametag(): Promise<string | null>;
784
+ /**
785
+ * Publish identity binding event on Nostr.
786
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
787
+ * With nametag: also publishes nametag hash, proxy address, encrypted nametag for recovery.
788
+ *
789
+ * Uses kind 30078 parameterized replaceable event with d=SHA256('unicity:identity:' + nostrPubkey).
790
+ * Each HD address index has its own Nostr key → its own binding event.
791
+ *
792
+ * @returns true if successful, false if nametag is taken by another pubkey
793
+ */
794
+ publishIdentityBinding(chainPubkey: string, l1Address: string, directAddress: string, nametag?: string): Promise<boolean>;
795
+ /** @deprecated Use publishIdentityBinding instead */
668
796
  publishNametag(nametag: string, address: string): Promise<void>;
669
797
  registerNametag(nametag: string, _publicKey: string, directAddress?: string): Promise<boolean>;
670
798
  private broadcastSubscriptions;
@@ -1026,6 +1154,65 @@ declare function createUnicityAggregatorProvider(config: Omit<UnicityAggregatorP
1026
1154
  /** @deprecated Use createUnicityAggregatorProvider instead */
1027
1155
  declare const createUnicityOracleProvider: typeof createUnicityAggregatorProvider;
1028
1156
 
1157
+ /**
1158
+ * Price Provider Interface
1159
+ *
1160
+ * Platform-independent abstraction for fetching token market prices.
1161
+ * Does not extend BaseProvider — stateless HTTP client with internal caching.
1162
+ */
1163
+ /**
1164
+ * Supported price provider platforms
1165
+ */
1166
+ type PricePlatform = 'coingecko';
1167
+ /**
1168
+ * Price data for a single token
1169
+ */
1170
+ interface TokenPrice {
1171
+ /** Token name used by the price platform (e.g., "bitcoin") */
1172
+ readonly tokenName: string;
1173
+ /** Price in USD */
1174
+ readonly priceUsd: number;
1175
+ /** Price in EUR (if available) */
1176
+ readonly priceEur?: number;
1177
+ /** 24h price change percentage (if available) */
1178
+ readonly change24h?: number;
1179
+ /** Timestamp when this price was fetched */
1180
+ readonly timestamp: number;
1181
+ }
1182
+ /**
1183
+ * Price data provider
1184
+ *
1185
+ * Fetches current market prices for tokens. Implementations handle
1186
+ * caching internally to avoid excessive API calls.
1187
+ *
1188
+ * @example
1189
+ * ```ts
1190
+ * const provider = new CoinGeckoPriceProvider({ apiKey: 'CG-xxx' });
1191
+ * const prices = await provider.getPrices(['bitcoin', 'ethereum']);
1192
+ * console.log(prices.get('bitcoin')?.priceUsd); // 97500
1193
+ * ```
1194
+ */
1195
+ interface PriceProvider {
1196
+ /** Platform identifier (e.g., 'coingecko') */
1197
+ readonly platform: PricePlatform;
1198
+ /**
1199
+ * Get prices for multiple tokens by their platform-compatible names
1200
+ * @param tokenNames - Array of token names (e.g., ['bitcoin', 'ethereum'])
1201
+ * @returns Map of token name to price data
1202
+ */
1203
+ getPrices(tokenNames: string[]): Promise<Map<string, TokenPrice>>;
1204
+ /**
1205
+ * Get price for a single token
1206
+ * @param tokenName - Token name (e.g., 'bitcoin')
1207
+ * @returns Token price or null if not available
1208
+ */
1209
+ getPrice(tokenName: string): Promise<TokenPrice | null>;
1210
+ /**
1211
+ * Clear cached prices
1212
+ */
1213
+ clearCache(): void;
1214
+ }
1215
+
1029
1216
  /**
1030
1217
  * Shared Configuration Interfaces
1031
1218
  * Base types extended by platform-specific implementations
@@ -1081,6 +1268,23 @@ interface L1Config {
1081
1268
  /** Enable vesting classification */
1082
1269
  enableVesting?: boolean;
1083
1270
  }
1271
+ /**
1272
+ * Base price provider configuration
1273
+ */
1274
+ interface BasePriceConfig {
1275
+ /** Which price platform to use (default: 'coingecko') */
1276
+ platform?: PricePlatform;
1277
+ /** API key for the price platform (optional for free tiers) */
1278
+ apiKey?: string;
1279
+ /** Custom base URL (e.g., for CORS proxy in browser environments) */
1280
+ baseUrl?: string;
1281
+ /** Cache TTL in milliseconds (default: 60000) */
1282
+ cacheTtlMs?: number;
1283
+ /** Request timeout in milliseconds (default: 10000) */
1284
+ timeout?: number;
1285
+ /** Enable debug logging */
1286
+ debug?: boolean;
1287
+ }
1084
1288
  /**
1085
1289
  * Base providers result
1086
1290
  * Common structure for all platforms
@@ -1092,6 +1296,8 @@ interface BaseProviders {
1092
1296
  oracle: OracleProvider;
1093
1297
  /** L1 configuration (for passing to Sphere.init) */
1094
1298
  l1?: L1Config;
1299
+ /** Price provider (optional — enables fiat value display) */
1300
+ price?: PriceProvider;
1095
1301
  }
1096
1302
 
1097
1303
  /**
@@ -1127,6 +1333,8 @@ interface NodeProvidersConfig {
1127
1333
  oracle?: NodeOracleConfig;
1128
1334
  /** L1 (ALPHA blockchain) configuration */
1129
1335
  l1?: NodeL1Config;
1336
+ /** Price provider configuration (optional — enables fiat value display) */
1337
+ price?: BasePriceConfig;
1130
1338
  }
1131
1339
  interface NodeProviders {
1132
1340
  storage: StorageProvider;
@@ -1135,6 +1343,8 @@ interface NodeProviders {
1135
1343
  oracle: OracleProvider;
1136
1344
  /** L1 configuration (for passing to Sphere.init) */
1137
1345
  l1?: L1Config;
1346
+ /** Price provider (optional — enables fiat value display) */
1347
+ price?: PriceProvider;
1138
1348
  }
1139
1349
  /**
1140
1350
  * Create all Node.js providers with default configuration