@unicitylabs/sphere-sdk 0.4.7 → 0.4.9

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.
@@ -30,6 +30,175 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
30
30
  ));
31
31
  var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
32
32
 
33
+ // constants.ts
34
+ function getAddressId(directAddress) {
35
+ let hash = directAddress;
36
+ if (hash.startsWith("DIRECT://")) {
37
+ hash = hash.slice(9);
38
+ } else if (hash.startsWith("DIRECT:")) {
39
+ hash = hash.slice(7);
40
+ }
41
+ const first = hash.slice(0, 6).toLowerCase();
42
+ const last = hash.slice(-6).toLowerCase();
43
+ return `DIRECT_${first}_${last}`;
44
+ }
45
+ var DEFAULT_ENCRYPTION_KEY, STORAGE_KEYS_GLOBAL, STORAGE_KEYS_ADDRESS, STORAGE_KEYS, DEFAULT_NOSTR_RELAYS, NIP29_KINDS, DEFAULT_AGGREGATOR_URL, DEV_AGGREGATOR_URL, TEST_AGGREGATOR_URL, DEFAULT_IPFS_GATEWAYS, DEFAULT_BASE_PATH, DEFAULT_DERIVATION_PATH, DEFAULT_ELECTRUM_URL, TEST_ELECTRUM_URL, TOKEN_REGISTRY_URL, TOKEN_REGISTRY_REFRESH_INTERVAL, TEST_NOSTR_RELAYS, DEFAULT_GROUP_RELAYS, NETWORKS;
46
+ var init_constants = __esm({
47
+ "constants.ts"() {
48
+ "use strict";
49
+ DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
50
+ STORAGE_KEYS_GLOBAL = {
51
+ /** Encrypted BIP39 mnemonic */
52
+ MNEMONIC: "mnemonic",
53
+ /** Encrypted master private key */
54
+ MASTER_KEY: "master_key",
55
+ /** BIP32 chain code */
56
+ CHAIN_CODE: "chain_code",
57
+ /** HD derivation path (full path like m/44'/0'/0'/0/0) */
58
+ DERIVATION_PATH: "derivation_path",
59
+ /** Base derivation path (like m/44'/0'/0' without chain/index) */
60
+ BASE_PATH: "base_path",
61
+ /** Derivation mode: bip32, wif_hmac, legacy_hmac */
62
+ DERIVATION_MODE: "derivation_mode",
63
+ /** Wallet source: mnemonic, file, unknown */
64
+ WALLET_SOURCE: "wallet_source",
65
+ /** Wallet existence flag */
66
+ WALLET_EXISTS: "wallet_exists",
67
+ /** Current active address index */
68
+ CURRENT_ADDRESS_INDEX: "current_address_index",
69
+ /** Nametag cache per address (separate from tracked addresses registry) */
70
+ ADDRESS_NAMETAGS: "address_nametags",
71
+ /** Active addresses registry (JSON: TrackedAddressesStorage) */
72
+ TRACKED_ADDRESSES: "tracked_addresses",
73
+ /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
74
+ LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
75
+ /** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
76
+ GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
77
+ /** Cached token registry JSON (fetched from remote) */
78
+ TOKEN_REGISTRY_CACHE: "token_registry_cache",
79
+ /** Timestamp of last token registry cache update (ms since epoch) */
80
+ TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
81
+ /** Cached price data JSON (from CoinGecko or other provider) */
82
+ PRICE_CACHE: "price_cache",
83
+ /** Timestamp of last price cache update (ms since epoch) */
84
+ PRICE_CACHE_TS: "price_cache_ts"
85
+ };
86
+ STORAGE_KEYS_ADDRESS = {
87
+ /** Pending transfers for this address */
88
+ PENDING_TRANSFERS: "pending_transfers",
89
+ /** Transfer outbox for this address */
90
+ OUTBOX: "outbox",
91
+ /** Conversations for this address */
92
+ CONVERSATIONS: "conversations",
93
+ /** Messages for this address */
94
+ MESSAGES: "messages",
95
+ /** Transaction history for this address */
96
+ TRANSACTION_HISTORY: "transaction_history",
97
+ /** Pending V5 finalization tokens (unconfirmed instant split tokens) */
98
+ PENDING_V5_TOKENS: "pending_v5_tokens",
99
+ /** Group chat: joined groups for this address */
100
+ GROUP_CHAT_GROUPS: "group_chat_groups",
101
+ /** Group chat: messages for this address */
102
+ GROUP_CHAT_MESSAGES: "group_chat_messages",
103
+ /** Group chat: members for this address */
104
+ GROUP_CHAT_MEMBERS: "group_chat_members",
105
+ /** Group chat: processed event IDs for deduplication */
106
+ GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
107
+ };
108
+ STORAGE_KEYS = {
109
+ ...STORAGE_KEYS_GLOBAL,
110
+ ...STORAGE_KEYS_ADDRESS
111
+ };
112
+ DEFAULT_NOSTR_RELAYS = [
113
+ "wss://relay.unicity.network",
114
+ "wss://relay.damus.io",
115
+ "wss://nos.lol",
116
+ "wss://relay.nostr.band"
117
+ ];
118
+ NIP29_KINDS = {
119
+ /** Chat message sent to group */
120
+ CHAT_MESSAGE: 9,
121
+ /** Thread root message */
122
+ THREAD_ROOT: 11,
123
+ /** Thread reply message */
124
+ THREAD_REPLY: 12,
125
+ /** User join request */
126
+ JOIN_REQUEST: 9021,
127
+ /** User leave request */
128
+ LEAVE_REQUEST: 9022,
129
+ /** Admin: add/update user */
130
+ PUT_USER: 9e3,
131
+ /** Admin: remove user */
132
+ REMOVE_USER: 9001,
133
+ /** Admin: edit group metadata */
134
+ EDIT_METADATA: 9002,
135
+ /** Admin: delete event */
136
+ DELETE_EVENT: 9005,
137
+ /** Admin: create group */
138
+ CREATE_GROUP: 9007,
139
+ /** Admin: delete group */
140
+ DELETE_GROUP: 9008,
141
+ /** Admin: create invite code */
142
+ CREATE_INVITE: 9009,
143
+ /** Relay-signed group metadata */
144
+ GROUP_METADATA: 39e3,
145
+ /** Relay-signed group admins */
146
+ GROUP_ADMINS: 39001,
147
+ /** Relay-signed group members */
148
+ GROUP_MEMBERS: 39002,
149
+ /** Relay-signed group roles */
150
+ GROUP_ROLES: 39003
151
+ };
152
+ DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
153
+ DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
154
+ TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
155
+ DEFAULT_IPFS_GATEWAYS = [
156
+ "https://unicity-ipfs1.dyndns.org"
157
+ ];
158
+ DEFAULT_BASE_PATH = "m/44'/0'/0'";
159
+ DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
160
+ DEFAULT_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
161
+ TEST_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
162
+ TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
163
+ TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
164
+ TEST_NOSTR_RELAYS = [
165
+ "wss://nostr-relay.testnet.unicity.network"
166
+ ];
167
+ DEFAULT_GROUP_RELAYS = [
168
+ "wss://sphere-relay.unicity.network"
169
+ ];
170
+ NETWORKS = {
171
+ mainnet: {
172
+ name: "Mainnet",
173
+ aggregatorUrl: DEFAULT_AGGREGATOR_URL,
174
+ nostrRelays: DEFAULT_NOSTR_RELAYS,
175
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
176
+ electrumUrl: DEFAULT_ELECTRUM_URL,
177
+ groupRelays: DEFAULT_GROUP_RELAYS,
178
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
179
+ },
180
+ testnet: {
181
+ name: "Testnet",
182
+ aggregatorUrl: TEST_AGGREGATOR_URL,
183
+ nostrRelays: TEST_NOSTR_RELAYS,
184
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
185
+ electrumUrl: TEST_ELECTRUM_URL,
186
+ groupRelays: DEFAULT_GROUP_RELAYS,
187
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
188
+ },
189
+ dev: {
190
+ name: "Development",
191
+ aggregatorUrl: DEV_AGGREGATOR_URL,
192
+ nostrRelays: TEST_NOSTR_RELAYS,
193
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
194
+ electrumUrl: TEST_ELECTRUM_URL,
195
+ groupRelays: DEFAULT_GROUP_RELAYS,
196
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
197
+ }
198
+ };
199
+ }
200
+ });
201
+
33
202
  // core/bech32.ts
34
203
  function convertBits(data, fromBits, toBits, pad) {
35
204
  let acc = 0;
@@ -441,13 +610,16 @@ function disconnect() {
441
610
  if (cb.timeoutId) clearTimeout(cb.timeoutId);
442
611
  });
443
612
  connectionCallbacks.length = 0;
613
+ blockSubscribers.length = 0;
614
+ lastBlockHeader = null;
444
615
  }
445
616
  var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT;
446
617
  var init_network = __esm({
447
618
  "l1/network.ts"() {
448
619
  "use strict";
449
620
  init_addressToScriptHash();
450
- DEFAULT_ENDPOINT = "wss://fulcrum.unicity.network:50004";
621
+ init_constants();
622
+ DEFAULT_ENDPOINT = DEFAULT_ELECTRUM_URL;
451
623
  ws = null;
452
624
  isConnected = false;
453
625
  isConnecting = false;
@@ -472,7 +644,7 @@ var core_exports = {};
472
644
  __export(core_exports, {
473
645
  CHARSET: () => CHARSET,
474
646
  CurrencyUtils: () => CurrencyUtils,
475
- DEFAULT_DERIVATION_PATH: () => DEFAULT_DERIVATION_PATH,
647
+ DEFAULT_DERIVATION_PATH: () => DEFAULT_DERIVATION_PATH2,
476
648
  DEFAULT_TOKEN_DECIMALS: () => DEFAULT_TOKEN_DECIMALS,
477
649
  Sphere: () => Sphere,
478
650
  base58Decode: () => base58Decode,
@@ -495,6 +667,7 @@ __export(core_exports, {
495
667
  deriveChildKey: () => deriveChildKey,
496
668
  deriveKeyAtPath: () => deriveKeyAtPath,
497
669
  deserializeEncrypted: () => deserializeEncrypted,
670
+ discoverAddressesImpl: () => discoverAddressesImpl,
498
671
  doubleSha256: () => doubleSha256,
499
672
  ec: () => ec,
500
673
  encodeBech32: () => encodeBech32,
@@ -544,6 +717,9 @@ __export(core_exports, {
544
717
  });
545
718
  module.exports = __toCommonJS(core_exports);
546
719
 
720
+ // modules/payments/L1PaymentsModule.ts
721
+ init_constants();
722
+
547
723
  // l1/index.ts
548
724
  init_bech32();
549
725
  init_addressToScriptHash();
@@ -557,7 +733,7 @@ var ec = new import_elliptic.default.ec("secp256k1");
557
733
  var CURVE_ORDER = BigInt(
558
734
  "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
559
735
  );
560
- var DEFAULT_DERIVATION_PATH = "m/44'/0'/0'";
736
+ var DEFAULT_DERIVATION_PATH2 = "m/44'/0'/0'";
561
737
  function generateMnemonic2(strength = 128) {
562
738
  return bip39.generateMnemonic(strength);
563
739
  }
@@ -1578,7 +1754,7 @@ var L1PaymentsModule = class {
1578
1754
  _transport;
1579
1755
  constructor(config) {
1580
1756
  this._config = {
1581
- electrumUrl: config?.electrumUrl ?? "wss://fulcrum.unicity.network:50004",
1757
+ electrumUrl: config?.electrumUrl ?? DEFAULT_ELECTRUM_URL,
1582
1758
  network: config?.network ?? "mainnet",
1583
1759
  defaultFeeRate: config?.defaultFeeRate ?? 10,
1584
1760
  enableVesting: config?.enableVesting ?? true
@@ -2415,168 +2591,8 @@ var NametagMinter = class {
2415
2591
  }
2416
2592
  };
2417
2593
 
2418
- // constants.ts
2419
- var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
2420
- var STORAGE_KEYS_GLOBAL = {
2421
- /** Encrypted BIP39 mnemonic */
2422
- MNEMONIC: "mnemonic",
2423
- /** Encrypted master private key */
2424
- MASTER_KEY: "master_key",
2425
- /** BIP32 chain code */
2426
- CHAIN_CODE: "chain_code",
2427
- /** HD derivation path (full path like m/44'/0'/0'/0/0) */
2428
- DERIVATION_PATH: "derivation_path",
2429
- /** Base derivation path (like m/44'/0'/0' without chain/index) */
2430
- BASE_PATH: "base_path",
2431
- /** Derivation mode: bip32, wif_hmac, legacy_hmac */
2432
- DERIVATION_MODE: "derivation_mode",
2433
- /** Wallet source: mnemonic, file, unknown */
2434
- WALLET_SOURCE: "wallet_source",
2435
- /** Wallet existence flag */
2436
- WALLET_EXISTS: "wallet_exists",
2437
- /** Current active address index */
2438
- CURRENT_ADDRESS_INDEX: "current_address_index",
2439
- /** Nametag cache per address (separate from tracked addresses registry) */
2440
- ADDRESS_NAMETAGS: "address_nametags",
2441
- /** Active addresses registry (JSON: TrackedAddressesStorage) */
2442
- TRACKED_ADDRESSES: "tracked_addresses",
2443
- /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
2444
- LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
2445
- /** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
2446
- GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
2447
- /** Cached token registry JSON (fetched from remote) */
2448
- TOKEN_REGISTRY_CACHE: "token_registry_cache",
2449
- /** Timestamp of last token registry cache update (ms since epoch) */
2450
- TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
2451
- /** Cached price data JSON (from CoinGecko or other provider) */
2452
- PRICE_CACHE: "price_cache",
2453
- /** Timestamp of last price cache update (ms since epoch) */
2454
- PRICE_CACHE_TS: "price_cache_ts"
2455
- };
2456
- var STORAGE_KEYS_ADDRESS = {
2457
- /** Pending transfers for this address */
2458
- PENDING_TRANSFERS: "pending_transfers",
2459
- /** Transfer outbox for this address */
2460
- OUTBOX: "outbox",
2461
- /** Conversations for this address */
2462
- CONVERSATIONS: "conversations",
2463
- /** Messages for this address */
2464
- MESSAGES: "messages",
2465
- /** Transaction history for this address */
2466
- TRANSACTION_HISTORY: "transaction_history",
2467
- /** Pending V5 finalization tokens (unconfirmed instant split tokens) */
2468
- PENDING_V5_TOKENS: "pending_v5_tokens",
2469
- /** Group chat: joined groups for this address */
2470
- GROUP_CHAT_GROUPS: "group_chat_groups",
2471
- /** Group chat: messages for this address */
2472
- GROUP_CHAT_MESSAGES: "group_chat_messages",
2473
- /** Group chat: members for this address */
2474
- GROUP_CHAT_MEMBERS: "group_chat_members",
2475
- /** Group chat: processed event IDs for deduplication */
2476
- GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
2477
- };
2478
- var STORAGE_KEYS = {
2479
- ...STORAGE_KEYS_GLOBAL,
2480
- ...STORAGE_KEYS_ADDRESS
2481
- };
2482
- function getAddressId(directAddress) {
2483
- let hash = directAddress;
2484
- if (hash.startsWith("DIRECT://")) {
2485
- hash = hash.slice(9);
2486
- } else if (hash.startsWith("DIRECT:")) {
2487
- hash = hash.slice(7);
2488
- }
2489
- const first = hash.slice(0, 6).toLowerCase();
2490
- const last = hash.slice(-6).toLowerCase();
2491
- return `DIRECT_${first}_${last}`;
2492
- }
2493
- var DEFAULT_NOSTR_RELAYS = [
2494
- "wss://relay.unicity.network",
2495
- "wss://relay.damus.io",
2496
- "wss://nos.lol",
2497
- "wss://relay.nostr.band"
2498
- ];
2499
- var NIP29_KINDS = {
2500
- /** Chat message sent to group */
2501
- CHAT_MESSAGE: 9,
2502
- /** Thread root message */
2503
- THREAD_ROOT: 11,
2504
- /** Thread reply message */
2505
- THREAD_REPLY: 12,
2506
- /** User join request */
2507
- JOIN_REQUEST: 9021,
2508
- /** User leave request */
2509
- LEAVE_REQUEST: 9022,
2510
- /** Admin: add/update user */
2511
- PUT_USER: 9e3,
2512
- /** Admin: remove user */
2513
- REMOVE_USER: 9001,
2514
- /** Admin: edit group metadata */
2515
- EDIT_METADATA: 9002,
2516
- /** Admin: delete event */
2517
- DELETE_EVENT: 9005,
2518
- /** Admin: create group */
2519
- CREATE_GROUP: 9007,
2520
- /** Admin: delete group */
2521
- DELETE_GROUP: 9008,
2522
- /** Admin: create invite code */
2523
- CREATE_INVITE: 9009,
2524
- /** Relay-signed group metadata */
2525
- GROUP_METADATA: 39e3,
2526
- /** Relay-signed group admins */
2527
- GROUP_ADMINS: 39001,
2528
- /** Relay-signed group members */
2529
- GROUP_MEMBERS: 39002,
2530
- /** Relay-signed group roles */
2531
- GROUP_ROLES: 39003
2532
- };
2533
- var DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
2534
- var DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
2535
- var TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
2536
- var DEFAULT_IPFS_GATEWAYS = [
2537
- "https://unicity-ipfs1.dyndns.org"
2538
- ];
2539
- var DEFAULT_BASE_PATH = "m/44'/0'/0'";
2540
- var DEFAULT_DERIVATION_PATH2 = `${DEFAULT_BASE_PATH}/0/0`;
2541
- var DEFAULT_ELECTRUM_URL = "wss://fulcrum.alpha.unicity.network:50004";
2542
- var TEST_ELECTRUM_URL = "wss://fulcrum.alpha.testnet.unicity.network:50004";
2543
- var TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2544
- var TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
2545
- var TEST_NOSTR_RELAYS = [
2546
- "wss://nostr-relay.testnet.unicity.network"
2547
- ];
2548
- var DEFAULT_GROUP_RELAYS = [
2549
- "wss://sphere-relay.unicity.network"
2550
- ];
2551
- var NETWORKS = {
2552
- mainnet: {
2553
- name: "Mainnet",
2554
- aggregatorUrl: DEFAULT_AGGREGATOR_URL,
2555
- nostrRelays: DEFAULT_NOSTR_RELAYS,
2556
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2557
- electrumUrl: DEFAULT_ELECTRUM_URL,
2558
- groupRelays: DEFAULT_GROUP_RELAYS,
2559
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2560
- },
2561
- testnet: {
2562
- name: "Testnet",
2563
- aggregatorUrl: TEST_AGGREGATOR_URL,
2564
- nostrRelays: TEST_NOSTR_RELAYS,
2565
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2566
- electrumUrl: TEST_ELECTRUM_URL,
2567
- groupRelays: DEFAULT_GROUP_RELAYS,
2568
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2569
- },
2570
- dev: {
2571
- name: "Development",
2572
- aggregatorUrl: DEV_AGGREGATOR_URL,
2573
- nostrRelays: TEST_NOSTR_RELAYS,
2574
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2575
- electrumUrl: TEST_ELECTRUM_URL,
2576
- groupRelays: DEFAULT_GROUP_RELAYS,
2577
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2578
- }
2579
- };
2594
+ // modules/payments/PaymentsModule.ts
2595
+ init_constants();
2580
2596
 
2581
2597
  // types/txf.ts
2582
2598
  var ARCHIVED_PREFIX = "archived-";
@@ -2618,6 +2634,7 @@ function parseForkedKey(key) {
2618
2634
  }
2619
2635
 
2620
2636
  // registry/TokenRegistry.ts
2637
+ init_constants();
2621
2638
  var FETCH_TIMEOUT_MS = 1e4;
2622
2639
  var TokenRegistry = class _TokenRegistry {
2623
2640
  static instance = null;
@@ -7430,6 +7447,7 @@ var import_HashAlgorithm6 = require("@unicitylabs/state-transition-sdk/lib/hash/
7430
7447
  var import_UnmaskedPredicate6 = require("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate");
7431
7448
 
7432
7449
  // modules/communications/CommunicationsModule.ts
7450
+ init_constants();
7433
7451
  var CommunicationsModule = class {
7434
7452
  config;
7435
7453
  deps = null;
@@ -7905,6 +7923,7 @@ function createCommunicationsModule(config) {
7905
7923
 
7906
7924
  // modules/groupchat/GroupChatModule.ts
7907
7925
  var import_nostr_js_sdk2 = require("@unicitylabs/nostr-js-sdk");
7926
+ init_constants();
7908
7927
 
7909
7928
  // modules/groupchat/types.ts
7910
7929
  var GroupRole = {
@@ -11749,6 +11768,9 @@ function createMarketModule(config) {
11749
11768
  return new MarketModule(config);
11750
11769
  }
11751
11770
 
11771
+ // core/Sphere.ts
11772
+ init_constants();
11773
+
11752
11774
  // core/encryption.ts
11753
11775
  var import_crypto_js6 = __toESM(require("crypto-js"), 1);
11754
11776
  var DEFAULT_ITERATIONS = 1e5;
@@ -11937,6 +11959,72 @@ async function scanAddressesImpl(deriveAddress, options = {}) {
11937
11959
  };
11938
11960
  }
11939
11961
 
11962
+ // core/discover.ts
11963
+ async function discoverAddressesImpl(deriveTransportPubkey, batchResolve, options = {}) {
11964
+ const maxAddresses = options.maxAddresses ?? 50;
11965
+ const gapLimit = options.gapLimit ?? 20;
11966
+ const batchSize = options.batchSize ?? 20;
11967
+ const { onProgress, signal } = options;
11968
+ const discovered = /* @__PURE__ */ new Map();
11969
+ let consecutiveEmpty = 0;
11970
+ let scanned = 0;
11971
+ const totalBatches = Math.ceil(maxAddresses / batchSize);
11972
+ for (let batchStart = 0; batchStart < maxAddresses; batchStart += batchSize) {
11973
+ if (signal?.aborted) break;
11974
+ if (consecutiveEmpty >= gapLimit) break;
11975
+ const batchEnd = Math.min(batchStart + batchSize, maxAddresses);
11976
+ const batchIndices = [];
11977
+ const pubkeyToIndex = /* @__PURE__ */ new Map();
11978
+ const pubkeyToInfo = /* @__PURE__ */ new Map();
11979
+ for (let i = batchStart; i < batchEnd; i++) {
11980
+ const info = deriveTransportPubkey(i);
11981
+ batchIndices.push(i);
11982
+ pubkeyToIndex.set(info.transportPubkey, i);
11983
+ pubkeyToInfo.set(info.transportPubkey, info);
11984
+ }
11985
+ const batchPubkeys = Array.from(pubkeyToIndex.keys());
11986
+ onProgress?.({
11987
+ currentBatch: Math.floor(batchStart / batchSize) + 1,
11988
+ totalBatches,
11989
+ discoveredCount: discovered.size,
11990
+ currentGap: consecutiveEmpty,
11991
+ phase: "transport"
11992
+ });
11993
+ const peerInfos = await batchResolve(batchPubkeys);
11994
+ const foundInBatch = /* @__PURE__ */ new Set();
11995
+ for (const peer of peerInfos) {
11996
+ const index = pubkeyToIndex.get(peer.transportPubkey);
11997
+ if (index !== void 0) {
11998
+ foundInBatch.add(index);
11999
+ const derived = pubkeyToInfo.get(peer.transportPubkey);
12000
+ discovered.set(index, {
12001
+ index,
12002
+ l1Address: peer.l1Address || derived.l1Address,
12003
+ directAddress: peer.directAddress || derived.directAddress,
12004
+ chainPubkey: peer.chainPubkey || derived.chainPubkey,
12005
+ nametag: peer.nametag,
12006
+ l1Balance: 0,
12007
+ source: "transport"
12008
+ });
12009
+ }
12010
+ }
12011
+ for (const idx of batchIndices) {
12012
+ scanned++;
12013
+ if (foundInBatch.has(idx)) {
12014
+ consecutiveEmpty = 0;
12015
+ } else {
12016
+ consecutiveEmpty++;
12017
+ if (consecutiveEmpty >= gapLimit) break;
12018
+ }
12019
+ }
12020
+ }
12021
+ return {
12022
+ addresses: Array.from(discovered.values()).sort((a, b) => a.index - b.index),
12023
+ scannedCount: scanned,
12024
+ aborted: signal?.aborted ?? false
12025
+ };
12026
+ }
12027
+
11940
12028
  // core/Sphere.ts
11941
12029
  init_network();
11942
12030
 
@@ -12759,7 +12847,9 @@ var Sphere = class _Sphere {
12759
12847
  price: options.price,
12760
12848
  groupChat,
12761
12849
  market,
12762
- password: options.password
12850
+ password: options.password,
12851
+ discoverAddresses: options.discoverAddresses,
12852
+ onProgress: options.onProgress
12763
12853
  });
12764
12854
  return { sphere: sphere2, created: false };
12765
12855
  }
@@ -12787,7 +12877,9 @@ var Sphere = class _Sphere {
12787
12877
  price: options.price,
12788
12878
  groupChat,
12789
12879
  market,
12790
- password: options.password
12880
+ password: options.password,
12881
+ discoverAddresses: options.discoverAddresses,
12882
+ onProgress: options.onProgress
12791
12883
  });
12792
12884
  return { sphere, created: true, generatedMnemonic };
12793
12885
  }
@@ -12848,6 +12940,7 @@ var Sphere = class _Sphere {
12848
12940
  if (await _Sphere.exists(options.storage)) {
12849
12941
  throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
12850
12942
  }
12943
+ const progress = options.onProgress;
12851
12944
  if (!options.storage.isConnected()) {
12852
12945
  await options.storage.connect();
12853
12946
  }
@@ -12865,20 +12958,39 @@ var Sphere = class _Sphere {
12865
12958
  marketConfig
12866
12959
  );
12867
12960
  sphere._password = options.password ?? null;
12961
+ progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
12868
12962
  await sphere.storeMnemonic(options.mnemonic, options.derivationPath);
12869
12963
  await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
12964
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
12870
12965
  await sphere.initializeProviders();
12871
12966
  await sphere.initializeModules();
12967
+ progress?.({ step: "finalizing", message: "Finalizing wallet..." });
12872
12968
  await sphere.finalizeWalletCreation();
12873
12969
  sphere._initialized = true;
12874
12970
  _Sphere.instance = sphere;
12875
12971
  await sphere.ensureAddressTracked(0);
12876
12972
  if (options.nametag) {
12973
+ progress?.({ step: "registering_nametag", message: "Registering nametag..." });
12877
12974
  await sphere.registerNametag(options.nametag);
12878
12975
  } else {
12976
+ progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
12879
12977
  await sphere.recoverNametagFromTransport();
12978
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
12880
12979
  await sphere.syncIdentityWithTransport();
12881
12980
  }
12981
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
12982
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
12983
+ try {
12984
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
12985
+ const result = await sphere.discoverAddresses(discoverOpts);
12986
+ if (result.addresses.length > 0) {
12987
+ console.log(`[Sphere.create] Address discovery: found ${result.addresses.length} address(es)`);
12988
+ }
12989
+ } catch (err) {
12990
+ console.warn("[Sphere.create] Address discovery failed (non-fatal):", err);
12991
+ }
12992
+ }
12993
+ progress?.({ step: "complete", message: "Wallet created" });
12882
12994
  return sphere;
12883
12995
  }
12884
12996
  /**
@@ -12888,6 +13000,7 @@ var Sphere = class _Sphere {
12888
13000
  if (!await _Sphere.exists(options.storage)) {
12889
13001
  throw new Error("No wallet found. Use Sphere.create() to create a new wallet.");
12890
13002
  }
13003
+ const progress = options.onProgress;
12891
13004
  _Sphere.configureTokenRegistry(options.storage, options.network);
12892
13005
  const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
12893
13006
  const marketConfig = _Sphere.resolveMarketConfig(options.market);
@@ -12905,13 +13018,17 @@ var Sphere = class _Sphere {
12905
13018
  if (!options.storage.isConnected()) {
12906
13019
  await options.storage.connect();
12907
13020
  }
13021
+ progress?.({ step: "storing_keys", message: "Loading wallet keys..." });
12908
13022
  await sphere.loadIdentityFromStorage();
13023
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
12909
13024
  await sphere.initializeProviders();
12910
13025
  await sphere.initializeModules();
13026
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
12911
13027
  await sphere.syncIdentityWithTransport();
12912
13028
  sphere._initialized = true;
12913
13029
  _Sphere.instance = sphere;
12914
13030
  if (sphere._identity?.nametag && !sphere._payments.hasNametag()) {
13031
+ progress?.({ step: "registering_nametag", message: "Restoring nametag token..." });
12915
13032
  console.log(`[Sphere] Nametag @${sphere._identity.nametag} has no token, attempting to mint...`);
12916
13033
  try {
12917
13034
  const result = await sphere.mintNametag(sphere._identity.nametag);
@@ -12924,6 +13041,19 @@ var Sphere = class _Sphere {
12924
13041
  console.warn(`[Sphere] Nametag token mint failed:`, err);
12925
13042
  }
12926
13043
  }
13044
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses && sphere._masterKey) {
13045
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
13046
+ try {
13047
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
13048
+ const result = await sphere.discoverAddresses(discoverOpts);
13049
+ if (result.addresses.length > 0) {
13050
+ console.log(`[Sphere.load] Address discovery: found ${result.addresses.length} address(es)`);
13051
+ }
13052
+ } catch (err) {
13053
+ console.warn("[Sphere.load] Address discovery failed (non-fatal):", err);
13054
+ }
13055
+ }
13056
+ progress?.({ step: "complete", message: "Wallet loaded" });
12927
13057
  return sphere;
12928
13058
  }
12929
13059
  /**
@@ -12933,9 +13063,11 @@ var Sphere = class _Sphere {
12933
13063
  if (!options.mnemonic && !options.masterKey) {
12934
13064
  throw new Error("Either mnemonic or masterKey is required");
12935
13065
  }
13066
+ const progress = options.onProgress;
12936
13067
  console.log("[Sphere.import] Starting import...");
12937
13068
  const needsClear = _Sphere.instance !== null || await _Sphere.exists(options.storage);
12938
13069
  if (needsClear) {
13070
+ progress?.({ step: "clearing", message: "Clearing previous wallet data..." });
12939
13071
  console.log("[Sphere.import] Clearing existing wallet data...");
12940
13072
  await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
12941
13073
  console.log("[Sphere.import] Clear done");
@@ -12960,6 +13092,7 @@ var Sphere = class _Sphere {
12960
13092
  marketConfig
12961
13093
  );
12962
13094
  sphere._password = options.password ?? null;
13095
+ progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
12963
13096
  if (options.mnemonic) {
12964
13097
  if (!_Sphere.validateMnemonic(options.mnemonic)) {
12965
13098
  throw new Error("Invalid mnemonic");
@@ -12984,17 +13117,21 @@ var Sphere = class _Sphere {
12984
13117
  options.derivationPath
12985
13118
  );
12986
13119
  }
13120
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
12987
13121
  console.log("[Sphere.import] Initializing providers...");
12988
13122
  await sphere.initializeProviders();
12989
13123
  console.log("[Sphere.import] Providers initialized. Initializing modules...");
12990
13124
  await sphere.initializeModules();
12991
13125
  console.log("[Sphere.import] Modules initialized");
12992
13126
  if (!options.nametag) {
13127
+ progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
12993
13128
  console.log("[Sphere.import] Recovering nametag from transport...");
12994
13129
  await sphere.recoverNametagFromTransport();
12995
13130
  console.log("[Sphere.import] Nametag recovery done");
13131
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
12996
13132
  await sphere.syncIdentityWithTransport();
12997
13133
  }
13134
+ progress?.({ step: "finalizing", message: "Finalizing wallet..." });
12998
13135
  console.log("[Sphere.import] Finalizing wallet creation...");
12999
13136
  await sphere.finalizeWalletCreation();
13000
13137
  sphere._initialized = true;
@@ -13002,10 +13139,12 @@ var Sphere = class _Sphere {
13002
13139
  console.log("[Sphere.import] Tracking address 0...");
13003
13140
  await sphere.ensureAddressTracked(0);
13004
13141
  if (options.nametag) {
13142
+ progress?.({ step: "registering_nametag", message: "Registering nametag..." });
13005
13143
  console.log("[Sphere.import] Registering nametag...");
13006
13144
  await sphere.registerNametag(options.nametag);
13007
13145
  }
13008
13146
  if (sphere._tokenStorageProviders.size > 0) {
13147
+ progress?.({ step: "syncing_tokens", message: "Syncing tokens..." });
13009
13148
  try {
13010
13149
  const syncResult = await sphere._payments.sync();
13011
13150
  console.log(`[Sphere.import] Auto-sync: +${syncResult.added} -${syncResult.removed}`);
@@ -13013,6 +13152,19 @@ var Sphere = class _Sphere {
13013
13152
  console.warn("[Sphere.import] Auto-sync failed (non-fatal):", err);
13014
13153
  }
13015
13154
  }
13155
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
13156
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
13157
+ try {
13158
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
13159
+ const result = await sphere.discoverAddresses(discoverOpts);
13160
+ if (result.addresses.length > 0) {
13161
+ console.log(`[Sphere.import] Address discovery: found ${result.addresses.length} address(es)`);
13162
+ }
13163
+ } catch (err) {
13164
+ console.warn("[Sphere.import] Address discovery failed (non-fatal):", err);
13165
+ }
13166
+ }
13167
+ progress?.({ step: "complete", message: "Import complete" });
13016
13168
  console.log("[Sphere.import] Import complete");
13017
13169
  return sphere;
13018
13170
  }
@@ -13881,6 +14033,23 @@ var Sphere = class _Sphere {
13881
14033
  await provider.initialize();
13882
14034
  }
13883
14035
  await this.reinitializeModulesForNewAddress();
14036
+ this.emitEvent("identity:changed", {
14037
+ l1Address: this._identity.l1Address,
14038
+ directAddress: this._identity.directAddress,
14039
+ chainPubkey: this._identity.chainPubkey,
14040
+ nametag: this._identity.nametag,
14041
+ addressIndex: index
14042
+ });
14043
+ console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
14044
+ this.postSwitchSync(index, newNametag).catch((err) => {
14045
+ console.warn(`[Sphere] Post-switch sync failed for address ${index}:`, err);
14046
+ });
14047
+ }
14048
+ /**
14049
+ * Background transport sync and nametag operations after address switch.
14050
+ * Runs after switchToAddress returns so L1/L3 queries can start immediately.
14051
+ */
14052
+ async postSwitchSync(index, newNametag) {
13884
14053
  if (!newNametag) {
13885
14054
  await this.syncIdentityWithTransport();
13886
14055
  }
@@ -13903,7 +14072,7 @@ var Sphere = class _Sphere {
13903
14072
  nametag: newNametag,
13904
14073
  addressIndex: index
13905
14074
  });
13906
- } else if (this._identity.nametag && !this._payments.hasNametag()) {
14075
+ } else if (this._identity?.nametag && !this._payments.hasNametag()) {
13907
14076
  console.log(`[Sphere] Nametag @${this._identity.nametag} has no token after switch, minting...`);
13908
14077
  try {
13909
14078
  const result = await this.mintNametag(this._identity.nametag);
@@ -13916,14 +14085,6 @@ var Sphere = class _Sphere {
13916
14085
  console.warn(`[Sphere] Nametag token mint failed after switch:`, err);
13917
14086
  }
13918
14087
  }
13919
- this.emitEvent("identity:changed", {
13920
- l1Address: this._identity.l1Address,
13921
- directAddress: this._identity.directAddress,
13922
- chainPubkey: this._identity.chainPubkey,
13923
- nametag: this._identity.nametag,
13924
- addressIndex: index
13925
- });
13926
- console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
13927
14088
  }
13928
14089
  /**
13929
14090
  * Re-initialize modules after address switch
@@ -14130,6 +14291,98 @@ var Sphere = class _Sphere {
14130
14291
  await this.persistTrackedAddresses();
14131
14292
  await this.persistAddressNametags();
14132
14293
  }
14294
+ /**
14295
+ * Discover previously used HD addresses.
14296
+ *
14297
+ * Primary: queries Nostr relay for identity binding events (fast, single batch query).
14298
+ * Secondary: runs L1 balance scan to find legacy addresses with no binding event.
14299
+ *
14300
+ * @example
14301
+ * ```ts
14302
+ * const result = await sphere.discoverAddresses();
14303
+ * console.log(`Found ${result.addresses.length} addresses`);
14304
+ *
14305
+ * // With auto-tracking
14306
+ * await sphere.discoverAddresses({ autoTrack: true });
14307
+ * ```
14308
+ */
14309
+ async discoverAddresses(options = {}) {
14310
+ this.ensureReady();
14311
+ if (!this._masterKey) {
14312
+ throw new Error("Address discovery requires HD master key");
14313
+ }
14314
+ if (!this._transport.discoverAddresses) {
14315
+ throw new Error("Transport provider does not support address discovery");
14316
+ }
14317
+ const includeL1Scan = options.includeL1Scan ?? true;
14318
+ const transportResult = await discoverAddressesImpl(
14319
+ (index) => {
14320
+ const addrInfo = this._deriveAddressInternal(index, false);
14321
+ return {
14322
+ transportPubkey: addrInfo.publicKey.slice(2),
14323
+ // x-only 32 bytes
14324
+ chainPubkey: addrInfo.publicKey,
14325
+ l1Address: addrInfo.address,
14326
+ directAddress: ""
14327
+ // not needed for discovery query
14328
+ };
14329
+ },
14330
+ (pubkeys) => this._transport.discoverAddresses(pubkeys),
14331
+ options
14332
+ );
14333
+ if (includeL1Scan) {
14334
+ try {
14335
+ const l1Result = await this.scanAddresses({
14336
+ maxAddresses: options.maxAddresses,
14337
+ gapLimit: options.gapLimit,
14338
+ signal: options.signal,
14339
+ onProgress: options.onProgress ? (p) => options.onProgress({
14340
+ currentBatch: 0,
14341
+ totalBatches: 0,
14342
+ discoveredCount: p.foundCount,
14343
+ currentGap: p.currentGap,
14344
+ phase: "l1"
14345
+ }) : void 0
14346
+ });
14347
+ for (const l1Addr of l1Result.addresses) {
14348
+ if (l1Addr.isChange) continue;
14349
+ const existing = transportResult.addresses.find((a) => a.index === l1Addr.index);
14350
+ if (existing) {
14351
+ existing.l1Balance = l1Addr.balance;
14352
+ existing.source = "both";
14353
+ if (!existing.nametag && l1Addr.nametag) {
14354
+ existing.nametag = l1Addr.nametag;
14355
+ }
14356
+ } else {
14357
+ const addrInfo = this._deriveAddressInternal(l1Addr.index, false);
14358
+ transportResult.addresses.push({
14359
+ index: l1Addr.index,
14360
+ l1Address: l1Addr.address,
14361
+ directAddress: "",
14362
+ chainPubkey: addrInfo.publicKey,
14363
+ nametag: l1Addr.nametag,
14364
+ l1Balance: l1Addr.balance,
14365
+ source: "l1"
14366
+ });
14367
+ }
14368
+ }
14369
+ transportResult.addresses.sort((a, b) => a.index - b.index);
14370
+ } catch (err) {
14371
+ console.warn("[Sphere] L1 scan failed during discovery (non-fatal):", err);
14372
+ }
14373
+ }
14374
+ if (options.autoTrack && transportResult.addresses.length > 0) {
14375
+ await this.trackScannedAddresses(
14376
+ transportResult.addresses.map((a) => ({
14377
+ index: a.index,
14378
+ // Preserve existing hidden state; default to false for newly discovered
14379
+ hidden: this._trackedAddresses.get(a.index)?.hidden ?? false,
14380
+ nametag: a.nametag
14381
+ }))
14382
+ );
14383
+ }
14384
+ return transportResult;
14385
+ }
14133
14386
  // ===========================================================================
14134
14387
  // Public Methods - Status
14135
14388
  // ===========================================================================
@@ -14701,6 +14954,17 @@ var Sphere = class _Sphere {
14701
14954
  return;
14702
14955
  }
14703
14956
  }
14957
+ const needsUpdate = !existing.directAddress || !existing.l1Address || !existing.chainPubkey || this._identity?.nametag && !existing.nametag;
14958
+ if (needsUpdate) {
14959
+ console.log("[Sphere] Existing binding incomplete, re-publishing with full data");
14960
+ await this._transport.publishIdentityBinding(
14961
+ this._identity.chainPubkey,
14962
+ this._identity.l1Address,
14963
+ this._identity.directAddress || "",
14964
+ this._identity?.nametag || existing.nametag || void 0
14965
+ );
14966
+ return;
14967
+ }
14704
14968
  console.log("[Sphere] Existing binding found, skipping re-publish");
14705
14969
  return;
14706
14970
  }
@@ -15194,6 +15458,7 @@ var CurrencyUtils = {
15194
15458
  init_bech32();
15195
15459
 
15196
15460
  // core/network-health.ts
15461
+ init_constants();
15197
15462
  var DEFAULT_TIMEOUT_MS = 5e3;
15198
15463
  async function checkNetworkHealth(network = "testnet", options) {
15199
15464
  const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -15405,6 +15670,7 @@ async function runCustomCheck(name, checkFn, timeoutMs) {
15405
15670
  deriveChildKey,
15406
15671
  deriveKeyAtPath,
15407
15672
  deserializeEncrypted,
15673
+ discoverAddressesImpl,
15408
15674
  doubleSha256,
15409
15675
  ec,
15410
15676
  encodeBech32,