@unicitylabs/sphere-sdk 0.4.6 → 0.4.8

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.
@@ -984,6 +984,14 @@ interface TransportProvider extends BaseProvider {
984
984
  * @returns PeerInfo or null if no binding found
985
985
  */
986
986
  resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
987
+ /**
988
+ * Batch-resolve multiple transport pubkeys to peer info.
989
+ * Used for HD address discovery: derives transport pubkeys for indices 0..N
990
+ * and queries binding events in a single batch.
991
+ * @param transportPubkeys - Array of transport-specific pubkeys to look up
992
+ * @returns Array of PeerInfo for pubkeys that have binding events (may be shorter than input)
993
+ */
994
+ discoverAddresses?(transportPubkeys: string[]): Promise<PeerInfo[]>;
987
995
  /**
988
996
  * Recover nametag for current identity by decrypting stored encrypted nametag
989
997
  * Used after wallet import to recover associated nametag
@@ -2800,6 +2808,12 @@ declare class GroupChatModule {
2800
2808
  onMessage(handler: (message: GroupMessageData) => void): () => void;
2801
2809
  getRelayUrls(): string[];
2802
2810
  getMyPublicKey(): string | null;
2811
+ /**
2812
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
2813
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
2814
+ * only sends events we don't already have.
2815
+ */
2816
+ private getLatestMessageTimestamp;
2803
2817
  private fetchRelayAdmins;
2804
2818
  private doFetchRelayAdmins;
2805
2819
  private fetchGroupMetadataInternal;
@@ -2987,7 +3001,7 @@ declare const NETWORKS: {
2987
3001
  readonly aggregatorUrl: "https://aggregator.unicity.network/rpc";
2988
3002
  readonly nostrRelays: readonly ["wss://relay.unicity.network", "wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"];
2989
3003
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2990
- readonly electrumUrl: "wss://fulcrum.alpha.unicity.network:50004";
3004
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
2991
3005
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2992
3006
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2993
3007
  };
@@ -2996,7 +3010,7 @@ declare const NETWORKS: {
2996
3010
  readonly aggregatorUrl: "https://goggregator-test.unicity.network";
2997
3011
  readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
2998
3012
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2999
- readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
3013
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
3000
3014
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
3001
3015
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
3002
3016
  };
@@ -3005,7 +3019,7 @@ declare const NETWORKS: {
3005
3019
  readonly aggregatorUrl: "https://dev-aggregator.dyndns.org/rpc";
3006
3020
  readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
3007
3021
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
3008
- readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
3022
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
3009
3023
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
3010
3024
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
3011
3025
  };
@@ -3083,6 +3097,88 @@ interface ScanAddressesResult {
3083
3097
  */
3084
3098
  declare function scanAddressesImpl(deriveAddress: (index: number, isChange: boolean) => AddressInfo, options?: ScanAddressesOptions): Promise<ScanAddressesResult>;
3085
3099
 
3100
+ /**
3101
+ * HD Address Discovery — discover previously used addresses via transport binding events.
3102
+ *
3103
+ * Derives transport pubkeys for HD indices and batch-queries the relay.
3104
+ * Complements L1 scan (scan.ts) by finding L3-only addresses.
3105
+ */
3106
+
3107
+ /** Progress callback for address discovery */
3108
+ interface DiscoverAddressProgress {
3109
+ /** Current batch being queried */
3110
+ currentBatch: number;
3111
+ /** Total batches planned */
3112
+ totalBatches: number;
3113
+ /** Number of addresses discovered so far */
3114
+ discoveredCount: number;
3115
+ /** Current gap count (consecutive empty indices) */
3116
+ currentGap: number;
3117
+ /** Phase: 'transport' or 'l1' */
3118
+ phase: 'transport' | 'l1';
3119
+ }
3120
+ /** Single discovered address result */
3121
+ interface DiscoveredAddress {
3122
+ /** HD derivation index */
3123
+ index: number;
3124
+ /** L1 bech32 address (alpha1...) */
3125
+ l1Address: string;
3126
+ /** L3 DIRECT address */
3127
+ directAddress: string;
3128
+ /** 33-byte compressed chain pubkey */
3129
+ chainPubkey: string;
3130
+ /** Nametag (from binding event) */
3131
+ nametag?: string;
3132
+ /** L1 balance in ALPHA (0 if only discovered via transport) */
3133
+ l1Balance: number;
3134
+ /** Discovery source */
3135
+ source: 'transport' | 'l1' | 'both';
3136
+ }
3137
+ /** Options for address discovery */
3138
+ interface DiscoverAddressesOptions {
3139
+ /** Max HD indices to probe (default: 50) */
3140
+ maxAddresses?: number;
3141
+ /** Stop after N consecutive empty indices (default: 20) */
3142
+ gapLimit?: number;
3143
+ /** Batch size for transport queries (default: 20) */
3144
+ batchSize?: number;
3145
+ /** Also run L1 balance scan (default: true) */
3146
+ includeL1Scan?: boolean;
3147
+ /** Progress callback */
3148
+ onProgress?: (progress: DiscoverAddressProgress) => void;
3149
+ /** Abort signal */
3150
+ signal?: AbortSignal;
3151
+ /** Auto-track discovered addresses (default: true) */
3152
+ autoTrack?: boolean;
3153
+ }
3154
+ /** Result of address discovery */
3155
+ interface DiscoverAddressesResult {
3156
+ /** All discovered addresses */
3157
+ addresses: DiscoveredAddress[];
3158
+ /** Total indices scanned */
3159
+ scannedCount: number;
3160
+ /** Whether scan was aborted */
3161
+ aborted: boolean;
3162
+ }
3163
+ /** Info derived for a single HD index */
3164
+ interface DerivedAddressInfo {
3165
+ transportPubkey: string;
3166
+ chainPubkey: string;
3167
+ l1Address: string;
3168
+ directAddress: string;
3169
+ }
3170
+ /**
3171
+ * Discover used HD addresses via transport binding events.
3172
+ *
3173
+ * Derives transport pubkeys in batches, queries the relay, and uses
3174
+ * gap limit to determine when to stop.
3175
+ *
3176
+ * @param deriveTransportPubkey - function(index) → address info with transportPubkey
3177
+ * @param batchResolve - function(transportPubkeys[]) → PeerInfo[]
3178
+ * @param options - Discovery options
3179
+ */
3180
+ declare function discoverAddressesImpl(deriveTransportPubkey: (index: number) => DerivedAddressInfo, batchResolve: (transportPubkeys: string[]) => Promise<PeerInfo[]>, options?: DiscoverAddressesOptions): Promise<DiscoverAddressesResult>;
3181
+
3086
3182
  /**
3087
3183
  * Legacy File Serialization Types
3088
3184
  */
@@ -3095,6 +3191,17 @@ type DecryptionProgressCallback = (iteration: number, total: number) => Promise<
3095
3191
 
3096
3192
  declare function isValidNametag(nametag: string): boolean;
3097
3193
 
3194
+ /** Steps reported by the onProgress callback during wallet init/create/load/import */
3195
+ type InitProgressStep = 'clearing' | 'storing_keys' | 'initializing' | 'recovering_nametag' | 'registering_nametag' | 'syncing_identity' | 'syncing_tokens' | 'discovering_addresses' | 'finalizing' | 'complete';
3196
+ /** Progress info passed to onProgress callback */
3197
+ interface InitProgress {
3198
+ /** Current step identifier */
3199
+ readonly step: InitProgressStep;
3200
+ /** Human-readable description of what's happening */
3201
+ readonly message: string;
3202
+ }
3203
+ /** Callback for tracking wallet initialization progress */
3204
+ type InitProgressCallback = (progress: InitProgress) => void;
3098
3205
  /** Options for creating a new wallet */
3099
3206
  interface SphereCreateOptions {
3100
3207
  /** BIP39 mnemonic (12 or 24 words) */
@@ -3127,6 +3234,15 @@ interface SphereCreateOptions {
3127
3234
  market?: MarketModuleConfig | boolean;
3128
3235
  /** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
3129
3236
  password?: string;
3237
+ /**
3238
+ * Auto-discover previously used HD addresses after creation.
3239
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3240
+ * - DiscoverAddressesOptions: custom config
3241
+ * - false/undefined: no auto-discovery (default)
3242
+ */
3243
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3244
+ /** Optional callback to report initialization progress steps */
3245
+ onProgress?: InitProgressCallback;
3130
3246
  }
3131
3247
  /** Options for loading existing wallet */
3132
3248
  interface SphereLoadOptions {
@@ -3154,6 +3270,15 @@ interface SphereLoadOptions {
3154
3270
  market?: MarketModuleConfig | boolean;
3155
3271
  /** Optional password to decrypt the wallet. Must match the password used during creation. */
3156
3272
  password?: string;
3273
+ /**
3274
+ * Auto-discover previously used HD addresses on load.
3275
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3276
+ * - DiscoverAddressesOptions: custom config
3277
+ * - false/undefined: no auto-discovery (default)
3278
+ */
3279
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3280
+ /** Optional callback to report initialization progress steps */
3281
+ onProgress?: InitProgressCallback;
3157
3282
  }
3158
3283
  /** Options for importing a wallet */
3159
3284
  interface SphereImportOptions {
@@ -3189,6 +3314,15 @@ interface SphereImportOptions {
3189
3314
  market?: MarketModuleConfig | boolean;
3190
3315
  /** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
3191
3316
  password?: string;
3317
+ /**
3318
+ * Auto-discover previously used HD addresses after import.
3319
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3320
+ * - DiscoverAddressesOptions: custom config
3321
+ * - false/undefined: no auto-discovery (default)
3322
+ */
3323
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3324
+ /** Optional callback to report initialization progress steps */
3325
+ onProgress?: InitProgressCallback;
3192
3326
  }
3193
3327
  /** L1 (ALPHA blockchain) configuration */
3194
3328
  interface L1Config {
@@ -3238,6 +3372,16 @@ interface SphereInitOptions {
3238
3372
  market?: MarketModuleConfig | boolean;
3239
3373
  /** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
3240
3374
  password?: string;
3375
+ /**
3376
+ * Auto-discover previously used HD addresses when creating from mnemonic.
3377
+ * Only applies when wallet is newly created (not on load of existing wallet).
3378
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3379
+ * - DiscoverAddressesOptions: custom config
3380
+ * - false/undefined: no auto-discovery (default)
3381
+ */
3382
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3383
+ /** Optional callback to report initialization progress steps */
3384
+ onProgress?: InitProgressCallback;
3241
3385
  }
3242
3386
  /** Result of init operation */
3243
3387
  interface SphereInitResult {
@@ -3509,14 +3653,9 @@ declare class Sphere {
3509
3653
  * });
3510
3654
  * ```
3511
3655
  */
3512
- static importFromJSON(options: {
3656
+ static importFromJSON(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
3513
3657
  jsonContent: string;
3514
3658
  password?: string;
3515
- storage: StorageProvider;
3516
- transport: TransportProvider;
3517
- oracle: OracleProvider;
3518
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
3519
- l1?: L1Config;
3520
3659
  }): Promise<{
3521
3660
  success: boolean;
3522
3661
  mnemonic?: string;
@@ -3552,7 +3691,7 @@ declare class Sphere {
3552
3691
  * });
3553
3692
  * ```
3554
3693
  */
3555
- static importFromLegacyFile(options: {
3694
+ static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
3556
3695
  /** File content - Uint8Array for .dat, string for .txt */
3557
3696
  fileContent: string | Uint8Array;
3558
3697
  /** File name (used for type detection) */
@@ -3561,18 +3700,6 @@ declare class Sphere {
3561
3700
  password?: string;
3562
3701
  /** Progress callback for long decryption operations */
3563
3702
  onDecryptProgress?: DecryptionProgressCallback;
3564
- /** Storage provider instance */
3565
- storage: StorageProvider;
3566
- /** Transport provider instance */
3567
- transport: TransportProvider;
3568
- /** Oracle provider instance */
3569
- oracle: OracleProvider;
3570
- /** Optional token storage provider */
3571
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
3572
- /** Optional nametag to register */
3573
- nametag?: string;
3574
- /** L1 (ALPHA blockchain) configuration */
3575
- l1?: L1Config;
3576
3703
  }): Promise<{
3577
3704
  success: boolean;
3578
3705
  sphere?: Sphere;
@@ -3673,6 +3800,11 @@ declare class Sphere {
3673
3800
  switchToAddress(index: number, options?: {
3674
3801
  nametag?: string;
3675
3802
  }): Promise<void>;
3803
+ /**
3804
+ * Background transport sync and nametag operations after address switch.
3805
+ * Runs after switchToAddress returns so L1/L3 queries can start immediately.
3806
+ */
3807
+ private postSwitchSync;
3676
3808
  /**
3677
3809
  * Re-initialize modules after address switch
3678
3810
  */
@@ -3762,6 +3894,22 @@ declare class Sphere {
3762
3894
  hidden: boolean;
3763
3895
  nametag?: string;
3764
3896
  }>): Promise<void>;
3897
+ /**
3898
+ * Discover previously used HD addresses.
3899
+ *
3900
+ * Primary: queries Nostr relay for identity binding events (fast, single batch query).
3901
+ * Secondary: runs L1 balance scan to find legacy addresses with no binding event.
3902
+ *
3903
+ * @example
3904
+ * ```ts
3905
+ * const result = await sphere.discoverAddresses();
3906
+ * console.log(`Found ${result.addresses.length} addresses`);
3907
+ *
3908
+ * // With auto-tracking
3909
+ * await sphere.discoverAddresses({ autoTrack: true });
3910
+ * ```
3911
+ */
3912
+ discoverAddresses(options?: DiscoverAddressesOptions): Promise<DiscoverAddressesResult>;
3765
3913
  /**
3766
3914
  * Get aggregated status of all providers, grouped by role.
3767
3915
  *
@@ -4313,4 +4461,4 @@ interface CheckNetworkHealthOptions {
4313
4461
  */
4314
4462
  declare function checkNetworkHealth(network?: NetworkType, options?: CheckNetworkHealthOptions): Promise<NetworkHealthResult>;
4315
4463
 
4316
- export { type AddressInfo, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type EncryptedData, type EncryptionOptions, type KeyPair, type L1Config, type MasterKey, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic };
4464
+ export { type AddressInfo, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type MasterKey, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic };
@@ -984,6 +984,14 @@ interface TransportProvider extends BaseProvider {
984
984
  * @returns PeerInfo or null if no binding found
985
985
  */
986
986
  resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
987
+ /**
988
+ * Batch-resolve multiple transport pubkeys to peer info.
989
+ * Used for HD address discovery: derives transport pubkeys for indices 0..N
990
+ * and queries binding events in a single batch.
991
+ * @param transportPubkeys - Array of transport-specific pubkeys to look up
992
+ * @returns Array of PeerInfo for pubkeys that have binding events (may be shorter than input)
993
+ */
994
+ discoverAddresses?(transportPubkeys: string[]): Promise<PeerInfo[]>;
987
995
  /**
988
996
  * Recover nametag for current identity by decrypting stored encrypted nametag
989
997
  * Used after wallet import to recover associated nametag
@@ -2800,6 +2808,12 @@ declare class GroupChatModule {
2800
2808
  onMessage(handler: (message: GroupMessageData) => void): () => void;
2801
2809
  getRelayUrls(): string[];
2802
2810
  getMyPublicKey(): string | null;
2811
+ /**
2812
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
2813
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
2814
+ * only sends events we don't already have.
2815
+ */
2816
+ private getLatestMessageTimestamp;
2803
2817
  private fetchRelayAdmins;
2804
2818
  private doFetchRelayAdmins;
2805
2819
  private fetchGroupMetadataInternal;
@@ -2987,7 +3001,7 @@ declare const NETWORKS: {
2987
3001
  readonly aggregatorUrl: "https://aggregator.unicity.network/rpc";
2988
3002
  readonly nostrRelays: readonly ["wss://relay.unicity.network", "wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"];
2989
3003
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2990
- readonly electrumUrl: "wss://fulcrum.alpha.unicity.network:50004";
3004
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
2991
3005
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
2992
3006
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2993
3007
  };
@@ -2996,7 +3010,7 @@ declare const NETWORKS: {
2996
3010
  readonly aggregatorUrl: "https://goggregator-test.unicity.network";
2997
3011
  readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
2998
3012
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
2999
- readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
3013
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
3000
3014
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
3001
3015
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
3002
3016
  };
@@ -3005,7 +3019,7 @@ declare const NETWORKS: {
3005
3019
  readonly aggregatorUrl: "https://dev-aggregator.dyndns.org/rpc";
3006
3020
  readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
3007
3021
  readonly ipfsGateways: readonly ["https://unicity-ipfs1.dyndns.org"];
3008
- readonly electrumUrl: "wss://fulcrum.alpha.testnet.unicity.network:50004";
3022
+ readonly electrumUrl: "wss://fulcrum.unicity.network:50004";
3009
3023
  readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
3010
3024
  readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
3011
3025
  };
@@ -3083,6 +3097,88 @@ interface ScanAddressesResult {
3083
3097
  */
3084
3098
  declare function scanAddressesImpl(deriveAddress: (index: number, isChange: boolean) => AddressInfo, options?: ScanAddressesOptions): Promise<ScanAddressesResult>;
3085
3099
 
3100
+ /**
3101
+ * HD Address Discovery — discover previously used addresses via transport binding events.
3102
+ *
3103
+ * Derives transport pubkeys for HD indices and batch-queries the relay.
3104
+ * Complements L1 scan (scan.ts) by finding L3-only addresses.
3105
+ */
3106
+
3107
+ /** Progress callback for address discovery */
3108
+ interface DiscoverAddressProgress {
3109
+ /** Current batch being queried */
3110
+ currentBatch: number;
3111
+ /** Total batches planned */
3112
+ totalBatches: number;
3113
+ /** Number of addresses discovered so far */
3114
+ discoveredCount: number;
3115
+ /** Current gap count (consecutive empty indices) */
3116
+ currentGap: number;
3117
+ /** Phase: 'transport' or 'l1' */
3118
+ phase: 'transport' | 'l1';
3119
+ }
3120
+ /** Single discovered address result */
3121
+ interface DiscoveredAddress {
3122
+ /** HD derivation index */
3123
+ index: number;
3124
+ /** L1 bech32 address (alpha1...) */
3125
+ l1Address: string;
3126
+ /** L3 DIRECT address */
3127
+ directAddress: string;
3128
+ /** 33-byte compressed chain pubkey */
3129
+ chainPubkey: string;
3130
+ /** Nametag (from binding event) */
3131
+ nametag?: string;
3132
+ /** L1 balance in ALPHA (0 if only discovered via transport) */
3133
+ l1Balance: number;
3134
+ /** Discovery source */
3135
+ source: 'transport' | 'l1' | 'both';
3136
+ }
3137
+ /** Options for address discovery */
3138
+ interface DiscoverAddressesOptions {
3139
+ /** Max HD indices to probe (default: 50) */
3140
+ maxAddresses?: number;
3141
+ /** Stop after N consecutive empty indices (default: 20) */
3142
+ gapLimit?: number;
3143
+ /** Batch size for transport queries (default: 20) */
3144
+ batchSize?: number;
3145
+ /** Also run L1 balance scan (default: true) */
3146
+ includeL1Scan?: boolean;
3147
+ /** Progress callback */
3148
+ onProgress?: (progress: DiscoverAddressProgress) => void;
3149
+ /** Abort signal */
3150
+ signal?: AbortSignal;
3151
+ /** Auto-track discovered addresses (default: true) */
3152
+ autoTrack?: boolean;
3153
+ }
3154
+ /** Result of address discovery */
3155
+ interface DiscoverAddressesResult {
3156
+ /** All discovered addresses */
3157
+ addresses: DiscoveredAddress[];
3158
+ /** Total indices scanned */
3159
+ scannedCount: number;
3160
+ /** Whether scan was aborted */
3161
+ aborted: boolean;
3162
+ }
3163
+ /** Info derived for a single HD index */
3164
+ interface DerivedAddressInfo {
3165
+ transportPubkey: string;
3166
+ chainPubkey: string;
3167
+ l1Address: string;
3168
+ directAddress: string;
3169
+ }
3170
+ /**
3171
+ * Discover used HD addresses via transport binding events.
3172
+ *
3173
+ * Derives transport pubkeys in batches, queries the relay, and uses
3174
+ * gap limit to determine when to stop.
3175
+ *
3176
+ * @param deriveTransportPubkey - function(index) → address info with transportPubkey
3177
+ * @param batchResolve - function(transportPubkeys[]) → PeerInfo[]
3178
+ * @param options - Discovery options
3179
+ */
3180
+ declare function discoverAddressesImpl(deriveTransportPubkey: (index: number) => DerivedAddressInfo, batchResolve: (transportPubkeys: string[]) => Promise<PeerInfo[]>, options?: DiscoverAddressesOptions): Promise<DiscoverAddressesResult>;
3181
+
3086
3182
  /**
3087
3183
  * Legacy File Serialization Types
3088
3184
  */
@@ -3095,6 +3191,17 @@ type DecryptionProgressCallback = (iteration: number, total: number) => Promise<
3095
3191
 
3096
3192
  declare function isValidNametag(nametag: string): boolean;
3097
3193
 
3194
+ /** Steps reported by the onProgress callback during wallet init/create/load/import */
3195
+ type InitProgressStep = 'clearing' | 'storing_keys' | 'initializing' | 'recovering_nametag' | 'registering_nametag' | 'syncing_identity' | 'syncing_tokens' | 'discovering_addresses' | 'finalizing' | 'complete';
3196
+ /** Progress info passed to onProgress callback */
3197
+ interface InitProgress {
3198
+ /** Current step identifier */
3199
+ readonly step: InitProgressStep;
3200
+ /** Human-readable description of what's happening */
3201
+ readonly message: string;
3202
+ }
3203
+ /** Callback for tracking wallet initialization progress */
3204
+ type InitProgressCallback = (progress: InitProgress) => void;
3098
3205
  /** Options for creating a new wallet */
3099
3206
  interface SphereCreateOptions {
3100
3207
  /** BIP39 mnemonic (12 or 24 words) */
@@ -3127,6 +3234,15 @@ interface SphereCreateOptions {
3127
3234
  market?: MarketModuleConfig | boolean;
3128
3235
  /** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
3129
3236
  password?: string;
3237
+ /**
3238
+ * Auto-discover previously used HD addresses after creation.
3239
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3240
+ * - DiscoverAddressesOptions: custom config
3241
+ * - false/undefined: no auto-discovery (default)
3242
+ */
3243
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3244
+ /** Optional callback to report initialization progress steps */
3245
+ onProgress?: InitProgressCallback;
3130
3246
  }
3131
3247
  /** Options for loading existing wallet */
3132
3248
  interface SphereLoadOptions {
@@ -3154,6 +3270,15 @@ interface SphereLoadOptions {
3154
3270
  market?: MarketModuleConfig | boolean;
3155
3271
  /** Optional password to decrypt the wallet. Must match the password used during creation. */
3156
3272
  password?: string;
3273
+ /**
3274
+ * Auto-discover previously used HD addresses on load.
3275
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3276
+ * - DiscoverAddressesOptions: custom config
3277
+ * - false/undefined: no auto-discovery (default)
3278
+ */
3279
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3280
+ /** Optional callback to report initialization progress steps */
3281
+ onProgress?: InitProgressCallback;
3157
3282
  }
3158
3283
  /** Options for importing a wallet */
3159
3284
  interface SphereImportOptions {
@@ -3189,6 +3314,15 @@ interface SphereImportOptions {
3189
3314
  market?: MarketModuleConfig | boolean;
3190
3315
  /** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
3191
3316
  password?: string;
3317
+ /**
3318
+ * Auto-discover previously used HD addresses after import.
3319
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3320
+ * - DiscoverAddressesOptions: custom config
3321
+ * - false/undefined: no auto-discovery (default)
3322
+ */
3323
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3324
+ /** Optional callback to report initialization progress steps */
3325
+ onProgress?: InitProgressCallback;
3192
3326
  }
3193
3327
  /** L1 (ALPHA blockchain) configuration */
3194
3328
  interface L1Config {
@@ -3238,6 +3372,16 @@ interface SphereInitOptions {
3238
3372
  market?: MarketModuleConfig | boolean;
3239
3373
  /** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
3240
3374
  password?: string;
3375
+ /**
3376
+ * Auto-discover previously used HD addresses when creating from mnemonic.
3377
+ * Only applies when wallet is newly created (not on load of existing wallet).
3378
+ * - true: discover with defaults (Nostr + L1 scan, autoTrack: true)
3379
+ * - DiscoverAddressesOptions: custom config
3380
+ * - false/undefined: no auto-discovery (default)
3381
+ */
3382
+ discoverAddresses?: boolean | DiscoverAddressesOptions;
3383
+ /** Optional callback to report initialization progress steps */
3384
+ onProgress?: InitProgressCallback;
3241
3385
  }
3242
3386
  /** Result of init operation */
3243
3387
  interface SphereInitResult {
@@ -3509,14 +3653,9 @@ declare class Sphere {
3509
3653
  * });
3510
3654
  * ```
3511
3655
  */
3512
- static importFromJSON(options: {
3656
+ static importFromJSON(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
3513
3657
  jsonContent: string;
3514
3658
  password?: string;
3515
- storage: StorageProvider;
3516
- transport: TransportProvider;
3517
- oracle: OracleProvider;
3518
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
3519
- l1?: L1Config;
3520
3659
  }): Promise<{
3521
3660
  success: boolean;
3522
3661
  mnemonic?: string;
@@ -3552,7 +3691,7 @@ declare class Sphere {
3552
3691
  * });
3553
3692
  * ```
3554
3693
  */
3555
- static importFromLegacyFile(options: {
3694
+ static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
3556
3695
  /** File content - Uint8Array for .dat, string for .txt */
3557
3696
  fileContent: string | Uint8Array;
3558
3697
  /** File name (used for type detection) */
@@ -3561,18 +3700,6 @@ declare class Sphere {
3561
3700
  password?: string;
3562
3701
  /** Progress callback for long decryption operations */
3563
3702
  onDecryptProgress?: DecryptionProgressCallback;
3564
- /** Storage provider instance */
3565
- storage: StorageProvider;
3566
- /** Transport provider instance */
3567
- transport: TransportProvider;
3568
- /** Oracle provider instance */
3569
- oracle: OracleProvider;
3570
- /** Optional token storage provider */
3571
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
3572
- /** Optional nametag to register */
3573
- nametag?: string;
3574
- /** L1 (ALPHA blockchain) configuration */
3575
- l1?: L1Config;
3576
3703
  }): Promise<{
3577
3704
  success: boolean;
3578
3705
  sphere?: Sphere;
@@ -3673,6 +3800,11 @@ declare class Sphere {
3673
3800
  switchToAddress(index: number, options?: {
3674
3801
  nametag?: string;
3675
3802
  }): Promise<void>;
3803
+ /**
3804
+ * Background transport sync and nametag operations after address switch.
3805
+ * Runs after switchToAddress returns so L1/L3 queries can start immediately.
3806
+ */
3807
+ private postSwitchSync;
3676
3808
  /**
3677
3809
  * Re-initialize modules after address switch
3678
3810
  */
@@ -3762,6 +3894,22 @@ declare class Sphere {
3762
3894
  hidden: boolean;
3763
3895
  nametag?: string;
3764
3896
  }>): Promise<void>;
3897
+ /**
3898
+ * Discover previously used HD addresses.
3899
+ *
3900
+ * Primary: queries Nostr relay for identity binding events (fast, single batch query).
3901
+ * Secondary: runs L1 balance scan to find legacy addresses with no binding event.
3902
+ *
3903
+ * @example
3904
+ * ```ts
3905
+ * const result = await sphere.discoverAddresses();
3906
+ * console.log(`Found ${result.addresses.length} addresses`);
3907
+ *
3908
+ * // With auto-tracking
3909
+ * await sphere.discoverAddresses({ autoTrack: true });
3910
+ * ```
3911
+ */
3912
+ discoverAddresses(options?: DiscoverAddressesOptions): Promise<DiscoverAddressesResult>;
3765
3913
  /**
3766
3914
  * Get aggregated status of all providers, grouped by role.
3767
3915
  *
@@ -4313,4 +4461,4 @@ interface CheckNetworkHealthOptions {
4313
4461
  */
4314
4462
  declare function checkNetworkHealth(network?: NetworkType, options?: CheckNetworkHealthOptions): Promise<NetworkHealthResult>;
4315
4463
 
4316
- export { type AddressInfo, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type EncryptedData, type EncryptionOptions, type KeyPair, type L1Config, type MasterKey, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic };
4464
+ export { type AddressInfo, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type MasterKey, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic };