@unicitylabs/sphere-sdk 0.1.8 → 0.2.0

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
  */
@@ -276,6 +300,7 @@ declare class FileTokenStorageProvider implements TokenStorageProvider<TxfStorag
276
300
  load(): Promise<LoadResult<TxfStorageDataBase>>;
277
301
  save(data: TxfStorageDataBase): Promise<SaveResult>;
278
302
  sync(localData: TxfStorageDataBase): Promise<SyncResult<TxfStorageDataBase>>;
303
+ clear(): Promise<boolean>;
279
304
  deleteToken(tokenId: string): Promise<void>;
280
305
  saveToken(tokenId: string, tokenData: unknown): Promise<void>;
281
306
  getToken(tokenId: string): Promise<unknown | null>;
@@ -318,15 +343,36 @@ interface TransportProvider extends BaseProvider {
318
343
  * @returns Unsubscribe function
319
344
  */
320
345
  onTokenTransfer(handler: TokenTransferHandler): () => void;
346
+ /**
347
+ * Resolve any identifier to full peer information.
348
+ * Accepts @nametag, bare nametag, DIRECT://, PROXY://, L1 address, chain pubkey, or transport pubkey.
349
+ * @param identifier - Any supported identifier format
350
+ * @returns PeerInfo or null if not found
351
+ */
352
+ resolve?(identifier: string): Promise<PeerInfo | null>;
321
353
  /**
322
354
  * Resolve nametag to public key
323
355
  */
324
356
  resolveNametag?(nametag: string): Promise<string | null>;
325
357
  /**
326
- * Resolve nametag to full address information
358
+ * Resolve nametag to full peer information
327
359
  * Returns transportPubkey, chainPubkey, l1Address, directAddress, proxyAddress
328
360
  */
329
- resolveNametagInfo?(nametag: string): Promise<NametagInfo | null>;
361
+ resolveNametagInfo?(nametag: string): Promise<PeerInfo | null>;
362
+ /**
363
+ * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
364
+ * Performs reverse lookup: address → binding event → PeerInfo.
365
+ * @param address - L3 address (DIRECT://... or PROXY://...) or L1 address (alpha1...)
366
+ * @returns PeerInfo or null if no binding found for this address
367
+ */
368
+ resolveAddressInfo?(address: string): Promise<PeerInfo | null>;
369
+ /**
370
+ * Resolve transport pubkey to full peer info.
371
+ * Queries binding events authored by the given transport pubkey.
372
+ * @param transportPubkey - Transport-specific pubkey (e.g. 64-char hex string)
373
+ * @returns PeerInfo or null if no binding found
374
+ */
375
+ resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
330
376
  /**
331
377
  * Recover nametag for current identity by decrypting stored encrypted nametag
332
378
  * Used after wallet import to recover associated nametag
@@ -334,14 +380,20 @@ interface TransportProvider extends BaseProvider {
334
380
  */
335
381
  recoverNametag?(): Promise<string | null>;
336
382
  /**
383
+ * Publish identity binding event.
384
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
385
+ * With nametag: adds nametag hash, proxy address, encrypted nametag for recovery.
386
+ * Uses parameterized replaceable event (kind 30078, d=hash(nostrPubkey)).
387
+ * @returns true if successful, false if nametag is taken by another pubkey
388
+ */
389
+ publishIdentityBinding?(chainPubkey: string, l1Address: string, directAddress: string, nametag?: string): Promise<boolean>;
390
+ /**
391
+ * @deprecated Use publishIdentityBinding instead
337
392
  * Register a nametag for this identity
338
- * @param nametag - Nametag to register
339
- * @param chainPubkey - 33-byte compressed secp256k1 public key (for L1/L3)
340
- * @param directAddress - L3 DIRECT address (DIRECT://...)
341
- * @returns true if successful, false if already taken
342
393
  */
343
394
  registerNametag?(nametag: string, chainPubkey: string, directAddress: string): Promise<boolean>;
344
395
  /**
396
+ * @deprecated Use publishIdentityBinding instead
345
397
  * Publish nametag binding
346
398
  */
347
399
  publishNametag?(nametag: string, address: string): Promise<void>;
@@ -401,7 +453,54 @@ interface TransportProvider extends BaseProvider {
401
453
  * Check if a relay is currently connected
402
454
  */
403
455
  isRelayConnected?(relayUrl: string): boolean;
456
+ /**
457
+ * Send an instant split bundle to a recipient.
458
+ * This is a specialized method for INSTANT_SPLIT V5 bundles.
459
+ *
460
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
461
+ * @param bundle - The InstantSplitBundleV5 to send
462
+ * @returns Event ID
463
+ */
464
+ sendInstantSplitBundle?(recipientTransportPubkey: string, bundle: InstantSplitBundlePayload): Promise<string>;
465
+ /**
466
+ * Subscribe to incoming instant split bundles.
467
+ *
468
+ * @param handler - Handler for received bundles
469
+ * @returns Unsubscribe function
470
+ */
471
+ onInstantSplitReceived?(handler: InstantSplitBundleHandler): () => void;
472
+ }
473
+ /**
474
+ * Payload for sending instant split bundles
475
+ */
476
+ interface InstantSplitBundlePayload {
477
+ /** The bundle JSON string (InstantSplitBundleV5 serialized) */
478
+ bundle: string;
479
+ /** Optional memo */
480
+ memo?: string;
481
+ /** Sender info */
482
+ sender?: {
483
+ transportPubkey: string;
484
+ nametag?: string;
485
+ };
404
486
  }
487
+ /**
488
+ * Incoming instant split bundle
489
+ */
490
+ interface IncomingInstantSplitBundle {
491
+ /** Event ID */
492
+ id: string;
493
+ /** Transport-specific pubkey of sender */
494
+ senderTransportPubkey: string;
495
+ /** The bundle JSON string */
496
+ bundle: string;
497
+ /** Timestamp */
498
+ timestamp: number;
499
+ }
500
+ /**
501
+ * Handler for instant split bundles
502
+ */
503
+ type InstantSplitBundleHandler = (bundle: IncomingInstantSplitBundle) => void;
405
504
  interface IncomingMessage {
406
505
  id: string;
407
506
  /** Transport-specific pubkey of sender */
@@ -510,12 +609,13 @@ interface TransportEvent {
510
609
  }
511
610
  type TransportEventCallback = (event: TransportEvent) => void;
512
611
  /**
513
- * Full nametag address information
514
- * Used for resolving nametag to all address formats
612
+ * Resolved peer identity information.
613
+ * Returned by resolve methods contains all public address formats for a peer.
614
+ * Fields nametag and proxyAddress are optional (only present if nametag is registered).
515
615
  */
516
- interface NametagInfo {
517
- /** Nametag name (without @) */
518
- nametag: string;
616
+ interface PeerInfo {
617
+ /** Nametag name (without @), if registered */
618
+ nametag?: string;
519
619
  /** Transport-specific pubkey (for messaging/encryption) */
520
620
  transportPubkey: string;
521
621
  /** 33-byte compressed secp256k1 public key (for L3 chain) */
@@ -524,8 +624,8 @@ interface NametagInfo {
524
624
  l1Address: string;
525
625
  /** L3 DIRECT address (DIRECT://...) */
526
626
  directAddress: string;
527
- /** L3 PROXY address derived from nametag hash (PROXY:...) */
528
- proxyAddress: string;
627
+ /** L3 PROXY address derived from nametag hash (PROXY:...), only if nametag registered */
628
+ proxyAddress?: string;
529
629
  /** Event timestamp */
530
630
  timestamp: number;
531
631
  }
@@ -656,14 +756,42 @@ declare class NostrTransportProvider implements TransportProvider {
656
756
  onPaymentRequest(handler: PaymentRequestHandler): () => void;
657
757
  sendPaymentRequestResponse(recipientPubkey: string, payload: PaymentRequestResponsePayload): Promise<string>;
658
758
  onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void;
759
+ /**
760
+ * Resolve any identifier to full peer information.
761
+ * Routes to the appropriate specific resolve method based on identifier format.
762
+ */
763
+ resolve(identifier: string): Promise<PeerInfo | null>;
659
764
  resolveNametag(nametag: string): Promise<string | null>;
660
- resolveNametagInfo(nametag: string): Promise<NametagInfo | null>;
765
+ resolveNametagInfo(nametag: string): Promise<PeerInfo | null>;
766
+ /**
767
+ * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
768
+ * Performs reverse lookup: hash(address) → query '#t' tag → parse binding event.
769
+ * Works with both new identity binding events and legacy nametag binding events.
770
+ */
771
+ resolveAddressInfo(address: string): Promise<PeerInfo | null>;
772
+ /**
773
+ * Resolve transport pubkey (Nostr pubkey) to full peer info.
774
+ * Queries binding events authored by the given pubkey.
775
+ */
776
+ resolveTransportPubkeyInfo(transportPubkey: string): Promise<PeerInfo | null>;
661
777
  /**
662
778
  * Recover nametag for the current identity by searching for encrypted nametag events
663
779
  * Used after wallet import to recover associated nametag
664
780
  * @returns Decrypted nametag or null if none found
665
781
  */
666
782
  recoverNametag(): Promise<string | null>;
783
+ /**
784
+ * Publish identity binding event on Nostr.
785
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
786
+ * With nametag: also publishes nametag hash, proxy address, encrypted nametag for recovery.
787
+ *
788
+ * Uses kind 30078 parameterized replaceable event with d=SHA256('unicity:identity:' + nostrPubkey).
789
+ * Each HD address index has its own Nostr key → its own binding event.
790
+ *
791
+ * @returns true if successful, false if nametag is taken by another pubkey
792
+ */
793
+ publishIdentityBinding(chainPubkey: string, l1Address: string, directAddress: string, nametag?: string): Promise<boolean>;
794
+ /** @deprecated Use publishIdentityBinding instead */
667
795
  publishNametag(nametag: string, address: string): Promise<void>;
668
796
  registerNametag(nametag: string, _publicKey: string, directAddress?: string): Promise<boolean>;
669
797
  private broadcastSubscriptions;
@@ -1025,6 +1153,65 @@ declare function createUnicityAggregatorProvider(config: Omit<UnicityAggregatorP
1025
1153
  /** @deprecated Use createUnicityAggregatorProvider instead */
1026
1154
  declare const createUnicityOracleProvider: typeof createUnicityAggregatorProvider;
1027
1155
 
1156
+ /**
1157
+ * Price Provider Interface
1158
+ *
1159
+ * Platform-independent abstraction for fetching token market prices.
1160
+ * Does not extend BaseProvider — stateless HTTP client with internal caching.
1161
+ */
1162
+ /**
1163
+ * Supported price provider platforms
1164
+ */
1165
+ type PricePlatform = 'coingecko';
1166
+ /**
1167
+ * Price data for a single token
1168
+ */
1169
+ interface TokenPrice {
1170
+ /** Token name used by the price platform (e.g., "bitcoin") */
1171
+ readonly tokenName: string;
1172
+ /** Price in USD */
1173
+ readonly priceUsd: number;
1174
+ /** Price in EUR (if available) */
1175
+ readonly priceEur?: number;
1176
+ /** 24h price change percentage (if available) */
1177
+ readonly change24h?: number;
1178
+ /** Timestamp when this price was fetched */
1179
+ readonly timestamp: number;
1180
+ }
1181
+ /**
1182
+ * Price data provider
1183
+ *
1184
+ * Fetches current market prices for tokens. Implementations handle
1185
+ * caching internally to avoid excessive API calls.
1186
+ *
1187
+ * @example
1188
+ * ```ts
1189
+ * const provider = new CoinGeckoPriceProvider({ apiKey: 'CG-xxx' });
1190
+ * const prices = await provider.getPrices(['bitcoin', 'ethereum']);
1191
+ * console.log(prices.get('bitcoin')?.priceUsd); // 97500
1192
+ * ```
1193
+ */
1194
+ interface PriceProvider {
1195
+ /** Platform identifier (e.g., 'coingecko') */
1196
+ readonly platform: PricePlatform;
1197
+ /**
1198
+ * Get prices for multiple tokens by their platform-compatible names
1199
+ * @param tokenNames - Array of token names (e.g., ['bitcoin', 'ethereum'])
1200
+ * @returns Map of token name to price data
1201
+ */
1202
+ getPrices(tokenNames: string[]): Promise<Map<string, TokenPrice>>;
1203
+ /**
1204
+ * Get price for a single token
1205
+ * @param tokenName - Token name (e.g., 'bitcoin')
1206
+ * @returns Token price or null if not available
1207
+ */
1208
+ getPrice(tokenName: string): Promise<TokenPrice | null>;
1209
+ /**
1210
+ * Clear cached prices
1211
+ */
1212
+ clearCache(): void;
1213
+ }
1214
+
1028
1215
  /**
1029
1216
  * Shared Configuration Interfaces
1030
1217
  * Base types extended by platform-specific implementations
@@ -1080,6 +1267,23 @@ interface L1Config {
1080
1267
  /** Enable vesting classification */
1081
1268
  enableVesting?: boolean;
1082
1269
  }
1270
+ /**
1271
+ * Base price provider configuration
1272
+ */
1273
+ interface BasePriceConfig {
1274
+ /** Which price platform to use (default: 'coingecko') */
1275
+ platform?: PricePlatform;
1276
+ /** API key for the price platform (optional for free tiers) */
1277
+ apiKey?: string;
1278
+ /** Custom base URL (e.g., for CORS proxy in browser environments) */
1279
+ baseUrl?: string;
1280
+ /** Cache TTL in milliseconds (default: 60000) */
1281
+ cacheTtlMs?: number;
1282
+ /** Request timeout in milliseconds (default: 10000) */
1283
+ timeout?: number;
1284
+ /** Enable debug logging */
1285
+ debug?: boolean;
1286
+ }
1083
1287
  /**
1084
1288
  * Base providers result
1085
1289
  * Common structure for all platforms
@@ -1091,6 +1295,8 @@ interface BaseProviders {
1091
1295
  oracle: OracleProvider;
1092
1296
  /** L1 configuration (for passing to Sphere.init) */
1093
1297
  l1?: L1Config;
1298
+ /** Price provider (optional — enables fiat value display) */
1299
+ price?: PriceProvider;
1094
1300
  }
1095
1301
 
1096
1302
  /**
@@ -1126,6 +1332,8 @@ interface NodeProvidersConfig {
1126
1332
  oracle?: NodeOracleConfig;
1127
1333
  /** L1 (ALPHA blockchain) configuration */
1128
1334
  l1?: NodeL1Config;
1335
+ /** Price provider configuration (optional — enables fiat value display) */
1336
+ price?: BasePriceConfig;
1129
1337
  }
1130
1338
  interface NodeProviders {
1131
1339
  storage: StorageProvider;
@@ -1134,6 +1342,8 @@ interface NodeProviders {
1134
1342
  oracle: OracleProvider;
1135
1343
  /** L1 configuration (for passing to Sphere.init) */
1136
1344
  l1?: L1Config;
1345
+ /** Price provider (optional — enables fiat value display) */
1346
+ price?: PriceProvider;
1137
1347
  }
1138
1348
  /**
1139
1349
  * Create all Node.js providers with default configuration