@unicitylabs/sphere-sdk 0.4.7 → 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.
package/dist/index.cjs CHANGED
@@ -30,6 +30,228 @@ 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 getAddressStorageKey(addressId, key) {
35
+ return `${addressId}_${key}`;
36
+ }
37
+ function getAddressId(directAddress) {
38
+ let hash = directAddress;
39
+ if (hash.startsWith("DIRECT://")) {
40
+ hash = hash.slice(9);
41
+ } else if (hash.startsWith("DIRECT:")) {
42
+ hash = hash.slice(7);
43
+ }
44
+ const first = hash.slice(0, 6).toLowerCase();
45
+ const last = hash.slice(-6).toLowerCase();
46
+ return `DIRECT_${first}_${last}`;
47
+ }
48
+ var STORAGE_PREFIX, DEFAULT_ENCRYPTION_KEY, STORAGE_KEYS_GLOBAL, STORAGE_KEYS_ADDRESS, STORAGE_KEYS, DEFAULT_NOSTR_RELAYS, NOSTR_EVENT_KINDS, NIP29_KINDS, DEFAULT_AGGREGATOR_URL, DEV_AGGREGATOR_URL, TEST_AGGREGATOR_URL, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_IPFS_GATEWAYS, DEFAULT_IPFS_BOOTSTRAP_PEERS, DEFAULT_BASE_PATH, DEFAULT_DERIVATION_PATH, COIN_TYPES, DEFAULT_ELECTRUM_URL, TEST_ELECTRUM_URL, TOKEN_REGISTRY_URL, TOKEN_REGISTRY_REFRESH_INTERVAL, TEST_NOSTR_RELAYS, DEFAULT_GROUP_RELAYS, NETWORKS, TIMEOUTS, LIMITS;
49
+ var init_constants = __esm({
50
+ "constants.ts"() {
51
+ "use strict";
52
+ STORAGE_PREFIX = "sphere_";
53
+ DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
54
+ STORAGE_KEYS_GLOBAL = {
55
+ /** Encrypted BIP39 mnemonic */
56
+ MNEMONIC: "mnemonic",
57
+ /** Encrypted master private key */
58
+ MASTER_KEY: "master_key",
59
+ /** BIP32 chain code */
60
+ CHAIN_CODE: "chain_code",
61
+ /** HD derivation path (full path like m/44'/0'/0'/0/0) */
62
+ DERIVATION_PATH: "derivation_path",
63
+ /** Base derivation path (like m/44'/0'/0' without chain/index) */
64
+ BASE_PATH: "base_path",
65
+ /** Derivation mode: bip32, wif_hmac, legacy_hmac */
66
+ DERIVATION_MODE: "derivation_mode",
67
+ /** Wallet source: mnemonic, file, unknown */
68
+ WALLET_SOURCE: "wallet_source",
69
+ /** Wallet existence flag */
70
+ WALLET_EXISTS: "wallet_exists",
71
+ /** Current active address index */
72
+ CURRENT_ADDRESS_INDEX: "current_address_index",
73
+ /** Nametag cache per address (separate from tracked addresses registry) */
74
+ ADDRESS_NAMETAGS: "address_nametags",
75
+ /** Active addresses registry (JSON: TrackedAddressesStorage) */
76
+ TRACKED_ADDRESSES: "tracked_addresses",
77
+ /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
78
+ LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
79
+ /** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
80
+ GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
81
+ /** Cached token registry JSON (fetched from remote) */
82
+ TOKEN_REGISTRY_CACHE: "token_registry_cache",
83
+ /** Timestamp of last token registry cache update (ms since epoch) */
84
+ TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
85
+ /** Cached price data JSON (from CoinGecko or other provider) */
86
+ PRICE_CACHE: "price_cache",
87
+ /** Timestamp of last price cache update (ms since epoch) */
88
+ PRICE_CACHE_TS: "price_cache_ts"
89
+ };
90
+ STORAGE_KEYS_ADDRESS = {
91
+ /** Pending transfers for this address */
92
+ PENDING_TRANSFERS: "pending_transfers",
93
+ /** Transfer outbox for this address */
94
+ OUTBOX: "outbox",
95
+ /** Conversations for this address */
96
+ CONVERSATIONS: "conversations",
97
+ /** Messages for this address */
98
+ MESSAGES: "messages",
99
+ /** Transaction history for this address */
100
+ TRANSACTION_HISTORY: "transaction_history",
101
+ /** Pending V5 finalization tokens (unconfirmed instant split tokens) */
102
+ PENDING_V5_TOKENS: "pending_v5_tokens",
103
+ /** Group chat: joined groups for this address */
104
+ GROUP_CHAT_GROUPS: "group_chat_groups",
105
+ /** Group chat: messages for this address */
106
+ GROUP_CHAT_MESSAGES: "group_chat_messages",
107
+ /** Group chat: members for this address */
108
+ GROUP_CHAT_MEMBERS: "group_chat_members",
109
+ /** Group chat: processed event IDs for deduplication */
110
+ GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
111
+ };
112
+ STORAGE_KEYS = {
113
+ ...STORAGE_KEYS_GLOBAL,
114
+ ...STORAGE_KEYS_ADDRESS
115
+ };
116
+ DEFAULT_NOSTR_RELAYS = [
117
+ "wss://relay.unicity.network",
118
+ "wss://relay.damus.io",
119
+ "wss://nos.lol",
120
+ "wss://relay.nostr.band"
121
+ ];
122
+ NOSTR_EVENT_KINDS = {
123
+ /** NIP-04 encrypted direct message */
124
+ DIRECT_MESSAGE: 4,
125
+ /** Token transfer (Unicity custom - 31113) */
126
+ TOKEN_TRANSFER: 31113,
127
+ /** Payment request (Unicity custom - 31115) */
128
+ PAYMENT_REQUEST: 31115,
129
+ /** Payment request response (Unicity custom - 31116) */
130
+ PAYMENT_REQUEST_RESPONSE: 31116,
131
+ /** Nametag binding (NIP-78 app-specific data) */
132
+ NAMETAG_BINDING: 30078,
133
+ /** Public broadcast */
134
+ BROADCAST: 1
135
+ };
136
+ NIP29_KINDS = {
137
+ /** Chat message sent to group */
138
+ CHAT_MESSAGE: 9,
139
+ /** Thread root message */
140
+ THREAD_ROOT: 11,
141
+ /** Thread reply message */
142
+ THREAD_REPLY: 12,
143
+ /** User join request */
144
+ JOIN_REQUEST: 9021,
145
+ /** User leave request */
146
+ LEAVE_REQUEST: 9022,
147
+ /** Admin: add/update user */
148
+ PUT_USER: 9e3,
149
+ /** Admin: remove user */
150
+ REMOVE_USER: 9001,
151
+ /** Admin: edit group metadata */
152
+ EDIT_METADATA: 9002,
153
+ /** Admin: delete event */
154
+ DELETE_EVENT: 9005,
155
+ /** Admin: create group */
156
+ CREATE_GROUP: 9007,
157
+ /** Admin: delete group */
158
+ DELETE_GROUP: 9008,
159
+ /** Admin: create invite code */
160
+ CREATE_INVITE: 9009,
161
+ /** Relay-signed group metadata */
162
+ GROUP_METADATA: 39e3,
163
+ /** Relay-signed group admins */
164
+ GROUP_ADMINS: 39001,
165
+ /** Relay-signed group members */
166
+ GROUP_MEMBERS: 39002,
167
+ /** Relay-signed group roles */
168
+ GROUP_ROLES: 39003
169
+ };
170
+ DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
171
+ DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
172
+ TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
173
+ DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
174
+ DEFAULT_IPFS_GATEWAYS = [
175
+ "https://unicity-ipfs1.dyndns.org"
176
+ ];
177
+ DEFAULT_IPFS_BOOTSTRAP_PEERS = [
178
+ "/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
179
+ "/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
180
+ "/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
181
+ "/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
182
+ ];
183
+ DEFAULT_BASE_PATH = "m/44'/0'/0'";
184
+ DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
185
+ COIN_TYPES = {
186
+ /** ALPHA token (L1 blockchain) */
187
+ ALPHA: "ALPHA",
188
+ /** Test token */
189
+ TEST: "TEST"
190
+ };
191
+ DEFAULT_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
192
+ TEST_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
193
+ TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
194
+ TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
195
+ TEST_NOSTR_RELAYS = [
196
+ "wss://nostr-relay.testnet.unicity.network"
197
+ ];
198
+ DEFAULT_GROUP_RELAYS = [
199
+ "wss://sphere-relay.unicity.network"
200
+ ];
201
+ NETWORKS = {
202
+ mainnet: {
203
+ name: "Mainnet",
204
+ aggregatorUrl: DEFAULT_AGGREGATOR_URL,
205
+ nostrRelays: DEFAULT_NOSTR_RELAYS,
206
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
207
+ electrumUrl: DEFAULT_ELECTRUM_URL,
208
+ groupRelays: DEFAULT_GROUP_RELAYS,
209
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
210
+ },
211
+ testnet: {
212
+ name: "Testnet",
213
+ aggregatorUrl: TEST_AGGREGATOR_URL,
214
+ nostrRelays: TEST_NOSTR_RELAYS,
215
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
216
+ electrumUrl: TEST_ELECTRUM_URL,
217
+ groupRelays: DEFAULT_GROUP_RELAYS,
218
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
219
+ },
220
+ dev: {
221
+ name: "Development",
222
+ aggregatorUrl: DEV_AGGREGATOR_URL,
223
+ nostrRelays: TEST_NOSTR_RELAYS,
224
+ ipfsGateways: DEFAULT_IPFS_GATEWAYS,
225
+ electrumUrl: TEST_ELECTRUM_URL,
226
+ groupRelays: DEFAULT_GROUP_RELAYS,
227
+ tokenRegistryUrl: TOKEN_REGISTRY_URL
228
+ }
229
+ };
230
+ TIMEOUTS = {
231
+ /** WebSocket connection timeout */
232
+ WEBSOCKET_CONNECT: 1e4,
233
+ /** Nostr relay reconnect delay */
234
+ NOSTR_RECONNECT_DELAY: 3e3,
235
+ /** Max reconnect attempts */
236
+ MAX_RECONNECT_ATTEMPTS: 5,
237
+ /** Proof polling interval */
238
+ PROOF_POLL_INTERVAL: 1e3,
239
+ /** Sync interval */
240
+ SYNC_INTERVAL: 6e4
241
+ };
242
+ LIMITS = {
243
+ /** Min nametag length */
244
+ NAMETAG_MIN_LENGTH: 3,
245
+ /** Max nametag length */
246
+ NAMETAG_MAX_LENGTH: 20,
247
+ /** Max memo length */
248
+ MEMO_MAX_LENGTH: 500,
249
+ /** Max message length */
250
+ MESSAGE_MAX_LENGTH: 1e4
251
+ };
252
+ }
253
+ });
254
+
33
255
  // core/bech32.ts
34
256
  function convertBits(data, fromBits, toBits, pad) {
35
257
  let acc = 0;
@@ -447,7 +669,8 @@ var init_network = __esm({
447
669
  "l1/network.ts"() {
448
670
  "use strict";
449
671
  init_addressToScriptHash();
450
- DEFAULT_ENDPOINT = "wss://fulcrum.unicity.network:50004";
672
+ init_constants();
673
+ DEFAULT_ENDPOINT = DEFAULT_ELECTRUM_URL;
451
674
  ws = null;
452
675
  isConnected = false;
453
676
  isConnecting = false;
@@ -611,6 +834,9 @@ __export(index_exports, {
611
834
  });
612
835
  module.exports = __toCommonJS(index_exports);
613
836
 
837
+ // modules/payments/L1PaymentsModule.ts
838
+ init_constants();
839
+
614
840
  // l1/index.ts
615
841
  var l1_exports = {};
616
842
  __export(l1_exports, {
@@ -1796,7 +2022,7 @@ var L1PaymentsModule = class {
1796
2022
  _transport;
1797
2023
  constructor(config) {
1798
2024
  this._config = {
1799
- electrumUrl: config?.electrumUrl ?? "wss://fulcrum.unicity.network:50004",
2025
+ electrumUrl: config?.electrumUrl ?? DEFAULT_ELECTRUM_URL,
1800
2026
  network: config?.network ?? "mainnet",
1801
2027
  defaultFeeRate: config?.defaultFeeRate ?? 10,
1802
2028
  enableVesting: config?.enableVesting ?? true
@@ -2636,221 +2862,8 @@ var NametagMinter = class {
2636
2862
  }
2637
2863
  };
2638
2864
 
2639
- // constants.ts
2640
- var STORAGE_PREFIX = "sphere_";
2641
- var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
2642
- var STORAGE_KEYS_GLOBAL = {
2643
- /** Encrypted BIP39 mnemonic */
2644
- MNEMONIC: "mnemonic",
2645
- /** Encrypted master private key */
2646
- MASTER_KEY: "master_key",
2647
- /** BIP32 chain code */
2648
- CHAIN_CODE: "chain_code",
2649
- /** HD derivation path (full path like m/44'/0'/0'/0/0) */
2650
- DERIVATION_PATH: "derivation_path",
2651
- /** Base derivation path (like m/44'/0'/0' without chain/index) */
2652
- BASE_PATH: "base_path",
2653
- /** Derivation mode: bip32, wif_hmac, legacy_hmac */
2654
- DERIVATION_MODE: "derivation_mode",
2655
- /** Wallet source: mnemonic, file, unknown */
2656
- WALLET_SOURCE: "wallet_source",
2657
- /** Wallet existence flag */
2658
- WALLET_EXISTS: "wallet_exists",
2659
- /** Current active address index */
2660
- CURRENT_ADDRESS_INDEX: "current_address_index",
2661
- /** Nametag cache per address (separate from tracked addresses registry) */
2662
- ADDRESS_NAMETAGS: "address_nametags",
2663
- /** Active addresses registry (JSON: TrackedAddressesStorage) */
2664
- TRACKED_ADDRESSES: "tracked_addresses",
2665
- /** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
2666
- LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
2667
- /** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
2668
- GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
2669
- /** Cached token registry JSON (fetched from remote) */
2670
- TOKEN_REGISTRY_CACHE: "token_registry_cache",
2671
- /** Timestamp of last token registry cache update (ms since epoch) */
2672
- TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
2673
- /** Cached price data JSON (from CoinGecko or other provider) */
2674
- PRICE_CACHE: "price_cache",
2675
- /** Timestamp of last price cache update (ms since epoch) */
2676
- PRICE_CACHE_TS: "price_cache_ts"
2677
- };
2678
- var STORAGE_KEYS_ADDRESS = {
2679
- /** Pending transfers for this address */
2680
- PENDING_TRANSFERS: "pending_transfers",
2681
- /** Transfer outbox for this address */
2682
- OUTBOX: "outbox",
2683
- /** Conversations for this address */
2684
- CONVERSATIONS: "conversations",
2685
- /** Messages for this address */
2686
- MESSAGES: "messages",
2687
- /** Transaction history for this address */
2688
- TRANSACTION_HISTORY: "transaction_history",
2689
- /** Pending V5 finalization tokens (unconfirmed instant split tokens) */
2690
- PENDING_V5_TOKENS: "pending_v5_tokens",
2691
- /** Group chat: joined groups for this address */
2692
- GROUP_CHAT_GROUPS: "group_chat_groups",
2693
- /** Group chat: messages for this address */
2694
- GROUP_CHAT_MESSAGES: "group_chat_messages",
2695
- /** Group chat: members for this address */
2696
- GROUP_CHAT_MEMBERS: "group_chat_members",
2697
- /** Group chat: processed event IDs for deduplication */
2698
- GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
2699
- };
2700
- var STORAGE_KEYS = {
2701
- ...STORAGE_KEYS_GLOBAL,
2702
- ...STORAGE_KEYS_ADDRESS
2703
- };
2704
- function getAddressStorageKey(addressId, key) {
2705
- return `${addressId}_${key}`;
2706
- }
2707
- function getAddressId(directAddress) {
2708
- let hash = directAddress;
2709
- if (hash.startsWith("DIRECT://")) {
2710
- hash = hash.slice(9);
2711
- } else if (hash.startsWith("DIRECT:")) {
2712
- hash = hash.slice(7);
2713
- }
2714
- const first = hash.slice(0, 6).toLowerCase();
2715
- const last = hash.slice(-6).toLowerCase();
2716
- return `DIRECT_${first}_${last}`;
2717
- }
2718
- var DEFAULT_NOSTR_RELAYS = [
2719
- "wss://relay.unicity.network",
2720
- "wss://relay.damus.io",
2721
- "wss://nos.lol",
2722
- "wss://relay.nostr.band"
2723
- ];
2724
- var NOSTR_EVENT_KINDS = {
2725
- /** NIP-04 encrypted direct message */
2726
- DIRECT_MESSAGE: 4,
2727
- /** Token transfer (Unicity custom - 31113) */
2728
- TOKEN_TRANSFER: 31113,
2729
- /** Payment request (Unicity custom - 31115) */
2730
- PAYMENT_REQUEST: 31115,
2731
- /** Payment request response (Unicity custom - 31116) */
2732
- PAYMENT_REQUEST_RESPONSE: 31116,
2733
- /** Nametag binding (NIP-78 app-specific data) */
2734
- NAMETAG_BINDING: 30078,
2735
- /** Public broadcast */
2736
- BROADCAST: 1
2737
- };
2738
- var NIP29_KINDS = {
2739
- /** Chat message sent to group */
2740
- CHAT_MESSAGE: 9,
2741
- /** Thread root message */
2742
- THREAD_ROOT: 11,
2743
- /** Thread reply message */
2744
- THREAD_REPLY: 12,
2745
- /** User join request */
2746
- JOIN_REQUEST: 9021,
2747
- /** User leave request */
2748
- LEAVE_REQUEST: 9022,
2749
- /** Admin: add/update user */
2750
- PUT_USER: 9e3,
2751
- /** Admin: remove user */
2752
- REMOVE_USER: 9001,
2753
- /** Admin: edit group metadata */
2754
- EDIT_METADATA: 9002,
2755
- /** Admin: delete event */
2756
- DELETE_EVENT: 9005,
2757
- /** Admin: create group */
2758
- CREATE_GROUP: 9007,
2759
- /** Admin: delete group */
2760
- DELETE_GROUP: 9008,
2761
- /** Admin: create invite code */
2762
- CREATE_INVITE: 9009,
2763
- /** Relay-signed group metadata */
2764
- GROUP_METADATA: 39e3,
2765
- /** Relay-signed group admins */
2766
- GROUP_ADMINS: 39001,
2767
- /** Relay-signed group members */
2768
- GROUP_MEMBERS: 39002,
2769
- /** Relay-signed group roles */
2770
- GROUP_ROLES: 39003
2771
- };
2772
- var DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
2773
- var DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
2774
- var TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
2775
- var DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
2776
- var DEFAULT_IPFS_GATEWAYS = [
2777
- "https://unicity-ipfs1.dyndns.org"
2778
- ];
2779
- var DEFAULT_IPFS_BOOTSTRAP_PEERS = [
2780
- "/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
2781
- "/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
2782
- "/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
2783
- "/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
2784
- ];
2785
- var DEFAULT_BASE_PATH = "m/44'/0'/0'";
2786
- var DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
2787
- var COIN_TYPES = {
2788
- /** ALPHA token (L1 blockchain) */
2789
- ALPHA: "ALPHA",
2790
- /** Test token */
2791
- TEST: "TEST"
2792
- };
2793
- var DEFAULT_ELECTRUM_URL = "wss://fulcrum.alpha.unicity.network:50004";
2794
- var TEST_ELECTRUM_URL = "wss://fulcrum.alpha.testnet.unicity.network:50004";
2795
- var TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
2796
- var TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
2797
- var TEST_NOSTR_RELAYS = [
2798
- "wss://nostr-relay.testnet.unicity.network"
2799
- ];
2800
- var DEFAULT_GROUP_RELAYS = [
2801
- "wss://sphere-relay.unicity.network"
2802
- ];
2803
- var NETWORKS = {
2804
- mainnet: {
2805
- name: "Mainnet",
2806
- aggregatorUrl: DEFAULT_AGGREGATOR_URL,
2807
- nostrRelays: DEFAULT_NOSTR_RELAYS,
2808
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2809
- electrumUrl: DEFAULT_ELECTRUM_URL,
2810
- groupRelays: DEFAULT_GROUP_RELAYS,
2811
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2812
- },
2813
- testnet: {
2814
- name: "Testnet",
2815
- aggregatorUrl: TEST_AGGREGATOR_URL,
2816
- nostrRelays: TEST_NOSTR_RELAYS,
2817
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2818
- electrumUrl: TEST_ELECTRUM_URL,
2819
- groupRelays: DEFAULT_GROUP_RELAYS,
2820
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2821
- },
2822
- dev: {
2823
- name: "Development",
2824
- aggregatorUrl: DEV_AGGREGATOR_URL,
2825
- nostrRelays: TEST_NOSTR_RELAYS,
2826
- ipfsGateways: DEFAULT_IPFS_GATEWAYS,
2827
- electrumUrl: TEST_ELECTRUM_URL,
2828
- groupRelays: DEFAULT_GROUP_RELAYS,
2829
- tokenRegistryUrl: TOKEN_REGISTRY_URL
2830
- }
2831
- };
2832
- var TIMEOUTS = {
2833
- /** WebSocket connection timeout */
2834
- WEBSOCKET_CONNECT: 1e4,
2835
- /** Nostr relay reconnect delay */
2836
- NOSTR_RECONNECT_DELAY: 3e3,
2837
- /** Max reconnect attempts */
2838
- MAX_RECONNECT_ATTEMPTS: 5,
2839
- /** Proof polling interval */
2840
- PROOF_POLL_INTERVAL: 1e3,
2841
- /** Sync interval */
2842
- SYNC_INTERVAL: 6e4
2843
- };
2844
- var LIMITS = {
2845
- /** Min nametag length */
2846
- NAMETAG_MIN_LENGTH: 3,
2847
- /** Max nametag length */
2848
- NAMETAG_MAX_LENGTH: 20,
2849
- /** Max memo length */
2850
- MEMO_MAX_LENGTH: 500,
2851
- /** Max message length */
2852
- MESSAGE_MAX_LENGTH: 1e4
2853
- };
2865
+ // modules/payments/PaymentsModule.ts
2866
+ init_constants();
2854
2867
 
2855
2868
  // types/txf.ts
2856
2869
  var ARCHIVED_PREFIX = "archived-";
@@ -2895,6 +2908,7 @@ function isValidTokenId(tokenId) {
2895
2908
  }
2896
2909
 
2897
2910
  // registry/TokenRegistry.ts
2911
+ init_constants();
2898
2912
  var FETCH_TIMEOUT_MS = 1e4;
2899
2913
  var TokenRegistry = class _TokenRegistry {
2900
2914
  static instance = null;
@@ -7792,6 +7806,7 @@ var import_HashAlgorithm6 = require("@unicitylabs/state-transition-sdk/lib/hash/
7792
7806
  var import_UnmaskedPredicate6 = require("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate");
7793
7807
 
7794
7808
  // modules/communications/CommunicationsModule.ts
7809
+ init_constants();
7795
7810
  var CommunicationsModule = class {
7796
7811
  config;
7797
7812
  deps = null;
@@ -8267,6 +8282,7 @@ function createCommunicationsModule(config) {
8267
8282
 
8268
8283
  // modules/groupchat/GroupChatModule.ts
8269
8284
  var import_nostr_js_sdk2 = require("@unicitylabs/nostr-js-sdk");
8285
+ init_constants();
8270
8286
 
8271
8287
  // modules/groupchat/types.ts
8272
8288
  var GroupRole = {
@@ -12111,6 +12127,9 @@ function createMarketModule(config) {
12111
12127
  return new MarketModule(config);
12112
12128
  }
12113
12129
 
12130
+ // core/Sphere.ts
12131
+ init_constants();
12132
+
12114
12133
  // core/encryption.ts
12115
12134
  var import_crypto_js6 = __toESM(require("crypto-js"), 1);
12116
12135
  function encryptSimple(plaintext, password) {
@@ -12214,6 +12233,72 @@ async function scanAddressesImpl(deriveAddress, options = {}) {
12214
12233
  };
12215
12234
  }
12216
12235
 
12236
+ // core/discover.ts
12237
+ async function discoverAddressesImpl(deriveTransportPubkey, batchResolve, options = {}) {
12238
+ const maxAddresses = options.maxAddresses ?? 50;
12239
+ const gapLimit = options.gapLimit ?? 20;
12240
+ const batchSize = options.batchSize ?? 20;
12241
+ const { onProgress, signal } = options;
12242
+ const discovered = /* @__PURE__ */ new Map();
12243
+ let consecutiveEmpty = 0;
12244
+ let scanned = 0;
12245
+ const totalBatches = Math.ceil(maxAddresses / batchSize);
12246
+ for (let batchStart = 0; batchStart < maxAddresses; batchStart += batchSize) {
12247
+ if (signal?.aborted) break;
12248
+ if (consecutiveEmpty >= gapLimit) break;
12249
+ const batchEnd = Math.min(batchStart + batchSize, maxAddresses);
12250
+ const batchIndices = [];
12251
+ const pubkeyToIndex = /* @__PURE__ */ new Map();
12252
+ const pubkeyToInfo = /* @__PURE__ */ new Map();
12253
+ for (let i = batchStart; i < batchEnd; i++) {
12254
+ const info = deriveTransportPubkey(i);
12255
+ batchIndices.push(i);
12256
+ pubkeyToIndex.set(info.transportPubkey, i);
12257
+ pubkeyToInfo.set(info.transportPubkey, info);
12258
+ }
12259
+ const batchPubkeys = Array.from(pubkeyToIndex.keys());
12260
+ onProgress?.({
12261
+ currentBatch: Math.floor(batchStart / batchSize) + 1,
12262
+ totalBatches,
12263
+ discoveredCount: discovered.size,
12264
+ currentGap: consecutiveEmpty,
12265
+ phase: "transport"
12266
+ });
12267
+ const peerInfos = await batchResolve(batchPubkeys);
12268
+ const foundInBatch = /* @__PURE__ */ new Set();
12269
+ for (const peer of peerInfos) {
12270
+ const index = pubkeyToIndex.get(peer.transportPubkey);
12271
+ if (index !== void 0) {
12272
+ foundInBatch.add(index);
12273
+ const derived = pubkeyToInfo.get(peer.transportPubkey);
12274
+ discovered.set(index, {
12275
+ index,
12276
+ l1Address: peer.l1Address || derived.l1Address,
12277
+ directAddress: peer.directAddress || derived.directAddress,
12278
+ chainPubkey: peer.chainPubkey || derived.chainPubkey,
12279
+ nametag: peer.nametag,
12280
+ l1Balance: 0,
12281
+ source: "transport"
12282
+ });
12283
+ }
12284
+ }
12285
+ for (const idx of batchIndices) {
12286
+ scanned++;
12287
+ if (foundInBatch.has(idx)) {
12288
+ consecutiveEmpty = 0;
12289
+ } else {
12290
+ consecutiveEmpty++;
12291
+ if (consecutiveEmpty >= gapLimit) break;
12292
+ }
12293
+ }
12294
+ }
12295
+ return {
12296
+ addresses: Array.from(discovered.values()).sort((a, b) => a.index - b.index),
12297
+ scannedCount: scanned,
12298
+ aborted: signal?.aborted ?? false
12299
+ };
12300
+ }
12301
+
12217
12302
  // core/Sphere.ts
12218
12303
  init_network();
12219
12304
 
@@ -13036,7 +13121,9 @@ var Sphere = class _Sphere {
13036
13121
  price: options.price,
13037
13122
  groupChat,
13038
13123
  market,
13039
- password: options.password
13124
+ password: options.password,
13125
+ discoverAddresses: options.discoverAddresses,
13126
+ onProgress: options.onProgress
13040
13127
  });
13041
13128
  return { sphere: sphere2, created: false };
13042
13129
  }
@@ -13064,7 +13151,9 @@ var Sphere = class _Sphere {
13064
13151
  price: options.price,
13065
13152
  groupChat,
13066
13153
  market,
13067
- password: options.password
13154
+ password: options.password,
13155
+ discoverAddresses: options.discoverAddresses,
13156
+ onProgress: options.onProgress
13068
13157
  });
13069
13158
  return { sphere, created: true, generatedMnemonic };
13070
13159
  }
@@ -13125,6 +13214,7 @@ var Sphere = class _Sphere {
13125
13214
  if (await _Sphere.exists(options.storage)) {
13126
13215
  throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
13127
13216
  }
13217
+ const progress = options.onProgress;
13128
13218
  if (!options.storage.isConnected()) {
13129
13219
  await options.storage.connect();
13130
13220
  }
@@ -13142,20 +13232,39 @@ var Sphere = class _Sphere {
13142
13232
  marketConfig
13143
13233
  );
13144
13234
  sphere._password = options.password ?? null;
13235
+ progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
13145
13236
  await sphere.storeMnemonic(options.mnemonic, options.derivationPath);
13146
13237
  await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
13238
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
13147
13239
  await sphere.initializeProviders();
13148
13240
  await sphere.initializeModules();
13241
+ progress?.({ step: "finalizing", message: "Finalizing wallet..." });
13149
13242
  await sphere.finalizeWalletCreation();
13150
13243
  sphere._initialized = true;
13151
13244
  _Sphere.instance = sphere;
13152
13245
  await sphere.ensureAddressTracked(0);
13153
13246
  if (options.nametag) {
13247
+ progress?.({ step: "registering_nametag", message: "Registering nametag..." });
13154
13248
  await sphere.registerNametag(options.nametag);
13155
13249
  } else {
13250
+ progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
13156
13251
  await sphere.recoverNametagFromTransport();
13252
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
13157
13253
  await sphere.syncIdentityWithTransport();
13158
13254
  }
13255
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
13256
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
13257
+ try {
13258
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
13259
+ const result = await sphere.discoverAddresses(discoverOpts);
13260
+ if (result.addresses.length > 0) {
13261
+ console.log(`[Sphere.create] Address discovery: found ${result.addresses.length} address(es)`);
13262
+ }
13263
+ } catch (err) {
13264
+ console.warn("[Sphere.create] Address discovery failed (non-fatal):", err);
13265
+ }
13266
+ }
13267
+ progress?.({ step: "complete", message: "Wallet created" });
13159
13268
  return sphere;
13160
13269
  }
13161
13270
  /**
@@ -13165,6 +13274,7 @@ var Sphere = class _Sphere {
13165
13274
  if (!await _Sphere.exists(options.storage)) {
13166
13275
  throw new Error("No wallet found. Use Sphere.create() to create a new wallet.");
13167
13276
  }
13277
+ const progress = options.onProgress;
13168
13278
  _Sphere.configureTokenRegistry(options.storage, options.network);
13169
13279
  const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
13170
13280
  const marketConfig = _Sphere.resolveMarketConfig(options.market);
@@ -13182,13 +13292,17 @@ var Sphere = class _Sphere {
13182
13292
  if (!options.storage.isConnected()) {
13183
13293
  await options.storage.connect();
13184
13294
  }
13295
+ progress?.({ step: "storing_keys", message: "Loading wallet keys..." });
13185
13296
  await sphere.loadIdentityFromStorage();
13297
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
13186
13298
  await sphere.initializeProviders();
13187
13299
  await sphere.initializeModules();
13300
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
13188
13301
  await sphere.syncIdentityWithTransport();
13189
13302
  sphere._initialized = true;
13190
13303
  _Sphere.instance = sphere;
13191
13304
  if (sphere._identity?.nametag && !sphere._payments.hasNametag()) {
13305
+ progress?.({ step: "registering_nametag", message: "Restoring nametag token..." });
13192
13306
  console.log(`[Sphere] Nametag @${sphere._identity.nametag} has no token, attempting to mint...`);
13193
13307
  try {
13194
13308
  const result = await sphere.mintNametag(sphere._identity.nametag);
@@ -13201,6 +13315,19 @@ var Sphere = class _Sphere {
13201
13315
  console.warn(`[Sphere] Nametag token mint failed:`, err);
13202
13316
  }
13203
13317
  }
13318
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses && sphere._masterKey) {
13319
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
13320
+ try {
13321
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
13322
+ const result = await sphere.discoverAddresses(discoverOpts);
13323
+ if (result.addresses.length > 0) {
13324
+ console.log(`[Sphere.load] Address discovery: found ${result.addresses.length} address(es)`);
13325
+ }
13326
+ } catch (err) {
13327
+ console.warn("[Sphere.load] Address discovery failed (non-fatal):", err);
13328
+ }
13329
+ }
13330
+ progress?.({ step: "complete", message: "Wallet loaded" });
13204
13331
  return sphere;
13205
13332
  }
13206
13333
  /**
@@ -13210,9 +13337,11 @@ var Sphere = class _Sphere {
13210
13337
  if (!options.mnemonic && !options.masterKey) {
13211
13338
  throw new Error("Either mnemonic or masterKey is required");
13212
13339
  }
13340
+ const progress = options.onProgress;
13213
13341
  console.log("[Sphere.import] Starting import...");
13214
13342
  const needsClear = _Sphere.instance !== null || await _Sphere.exists(options.storage);
13215
13343
  if (needsClear) {
13344
+ progress?.({ step: "clearing", message: "Clearing previous wallet data..." });
13216
13345
  console.log("[Sphere.import] Clearing existing wallet data...");
13217
13346
  await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
13218
13347
  console.log("[Sphere.import] Clear done");
@@ -13237,6 +13366,7 @@ var Sphere = class _Sphere {
13237
13366
  marketConfig
13238
13367
  );
13239
13368
  sphere._password = options.password ?? null;
13369
+ progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
13240
13370
  if (options.mnemonic) {
13241
13371
  if (!_Sphere.validateMnemonic(options.mnemonic)) {
13242
13372
  throw new Error("Invalid mnemonic");
@@ -13261,17 +13391,21 @@ var Sphere = class _Sphere {
13261
13391
  options.derivationPath
13262
13392
  );
13263
13393
  }
13394
+ progress?.({ step: "initializing", message: "Initializing wallet..." });
13264
13395
  console.log("[Sphere.import] Initializing providers...");
13265
13396
  await sphere.initializeProviders();
13266
13397
  console.log("[Sphere.import] Providers initialized. Initializing modules...");
13267
13398
  await sphere.initializeModules();
13268
13399
  console.log("[Sphere.import] Modules initialized");
13269
13400
  if (!options.nametag) {
13401
+ progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
13270
13402
  console.log("[Sphere.import] Recovering nametag from transport...");
13271
13403
  await sphere.recoverNametagFromTransport();
13272
13404
  console.log("[Sphere.import] Nametag recovery done");
13405
+ progress?.({ step: "syncing_identity", message: "Publishing identity..." });
13273
13406
  await sphere.syncIdentityWithTransport();
13274
13407
  }
13408
+ progress?.({ step: "finalizing", message: "Finalizing wallet..." });
13275
13409
  console.log("[Sphere.import] Finalizing wallet creation...");
13276
13410
  await sphere.finalizeWalletCreation();
13277
13411
  sphere._initialized = true;
@@ -13279,10 +13413,12 @@ var Sphere = class _Sphere {
13279
13413
  console.log("[Sphere.import] Tracking address 0...");
13280
13414
  await sphere.ensureAddressTracked(0);
13281
13415
  if (options.nametag) {
13416
+ progress?.({ step: "registering_nametag", message: "Registering nametag..." });
13282
13417
  console.log("[Sphere.import] Registering nametag...");
13283
13418
  await sphere.registerNametag(options.nametag);
13284
13419
  }
13285
13420
  if (sphere._tokenStorageProviders.size > 0) {
13421
+ progress?.({ step: "syncing_tokens", message: "Syncing tokens..." });
13286
13422
  try {
13287
13423
  const syncResult = await sphere._payments.sync();
13288
13424
  console.log(`[Sphere.import] Auto-sync: +${syncResult.added} -${syncResult.removed}`);
@@ -13290,6 +13426,19 @@ var Sphere = class _Sphere {
13290
13426
  console.warn("[Sphere.import] Auto-sync failed (non-fatal):", err);
13291
13427
  }
13292
13428
  }
13429
+ if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
13430
+ progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
13431
+ try {
13432
+ const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
13433
+ const result = await sphere.discoverAddresses(discoverOpts);
13434
+ if (result.addresses.length > 0) {
13435
+ console.log(`[Sphere.import] Address discovery: found ${result.addresses.length} address(es)`);
13436
+ }
13437
+ } catch (err) {
13438
+ console.warn("[Sphere.import] Address discovery failed (non-fatal):", err);
13439
+ }
13440
+ }
13441
+ progress?.({ step: "complete", message: "Import complete" });
13293
13442
  console.log("[Sphere.import] Import complete");
13294
13443
  return sphere;
13295
13444
  }
@@ -14158,6 +14307,23 @@ var Sphere = class _Sphere {
14158
14307
  await provider.initialize();
14159
14308
  }
14160
14309
  await this.reinitializeModulesForNewAddress();
14310
+ this.emitEvent("identity:changed", {
14311
+ l1Address: this._identity.l1Address,
14312
+ directAddress: this._identity.directAddress,
14313
+ chainPubkey: this._identity.chainPubkey,
14314
+ nametag: this._identity.nametag,
14315
+ addressIndex: index
14316
+ });
14317
+ console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
14318
+ this.postSwitchSync(index, newNametag).catch((err) => {
14319
+ console.warn(`[Sphere] Post-switch sync failed for address ${index}:`, err);
14320
+ });
14321
+ }
14322
+ /**
14323
+ * Background transport sync and nametag operations after address switch.
14324
+ * Runs after switchToAddress returns so L1/L3 queries can start immediately.
14325
+ */
14326
+ async postSwitchSync(index, newNametag) {
14161
14327
  if (!newNametag) {
14162
14328
  await this.syncIdentityWithTransport();
14163
14329
  }
@@ -14180,7 +14346,7 @@ var Sphere = class _Sphere {
14180
14346
  nametag: newNametag,
14181
14347
  addressIndex: index
14182
14348
  });
14183
- } else if (this._identity.nametag && !this._payments.hasNametag()) {
14349
+ } else if (this._identity?.nametag && !this._payments.hasNametag()) {
14184
14350
  console.log(`[Sphere] Nametag @${this._identity.nametag} has no token after switch, minting...`);
14185
14351
  try {
14186
14352
  const result = await this.mintNametag(this._identity.nametag);
@@ -14193,14 +14359,6 @@ var Sphere = class _Sphere {
14193
14359
  console.warn(`[Sphere] Nametag token mint failed after switch:`, err);
14194
14360
  }
14195
14361
  }
14196
- this.emitEvent("identity:changed", {
14197
- l1Address: this._identity.l1Address,
14198
- directAddress: this._identity.directAddress,
14199
- chainPubkey: this._identity.chainPubkey,
14200
- nametag: this._identity.nametag,
14201
- addressIndex: index
14202
- });
14203
- console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
14204
14362
  }
14205
14363
  /**
14206
14364
  * Re-initialize modules after address switch
@@ -14407,6 +14565,98 @@ var Sphere = class _Sphere {
14407
14565
  await this.persistTrackedAddresses();
14408
14566
  await this.persistAddressNametags();
14409
14567
  }
14568
+ /**
14569
+ * Discover previously used HD addresses.
14570
+ *
14571
+ * Primary: queries Nostr relay for identity binding events (fast, single batch query).
14572
+ * Secondary: runs L1 balance scan to find legacy addresses with no binding event.
14573
+ *
14574
+ * @example
14575
+ * ```ts
14576
+ * const result = await sphere.discoverAddresses();
14577
+ * console.log(`Found ${result.addresses.length} addresses`);
14578
+ *
14579
+ * // With auto-tracking
14580
+ * await sphere.discoverAddresses({ autoTrack: true });
14581
+ * ```
14582
+ */
14583
+ async discoverAddresses(options = {}) {
14584
+ this.ensureReady();
14585
+ if (!this._masterKey) {
14586
+ throw new Error("Address discovery requires HD master key");
14587
+ }
14588
+ if (!this._transport.discoverAddresses) {
14589
+ throw new Error("Transport provider does not support address discovery");
14590
+ }
14591
+ const includeL1Scan = options.includeL1Scan ?? true;
14592
+ const transportResult = await discoverAddressesImpl(
14593
+ (index) => {
14594
+ const addrInfo = this._deriveAddressInternal(index, false);
14595
+ return {
14596
+ transportPubkey: addrInfo.publicKey.slice(2),
14597
+ // x-only 32 bytes
14598
+ chainPubkey: addrInfo.publicKey,
14599
+ l1Address: addrInfo.address,
14600
+ directAddress: ""
14601
+ // not needed for discovery query
14602
+ };
14603
+ },
14604
+ (pubkeys) => this._transport.discoverAddresses(pubkeys),
14605
+ options
14606
+ );
14607
+ if (includeL1Scan) {
14608
+ try {
14609
+ const l1Result = await this.scanAddresses({
14610
+ maxAddresses: options.maxAddresses,
14611
+ gapLimit: options.gapLimit,
14612
+ signal: options.signal,
14613
+ onProgress: options.onProgress ? (p) => options.onProgress({
14614
+ currentBatch: 0,
14615
+ totalBatches: 0,
14616
+ discoveredCount: p.foundCount,
14617
+ currentGap: p.currentGap,
14618
+ phase: "l1"
14619
+ }) : void 0
14620
+ });
14621
+ for (const l1Addr of l1Result.addresses) {
14622
+ if (l1Addr.isChange) continue;
14623
+ const existing = transportResult.addresses.find((a) => a.index === l1Addr.index);
14624
+ if (existing) {
14625
+ existing.l1Balance = l1Addr.balance;
14626
+ existing.source = "both";
14627
+ if (!existing.nametag && l1Addr.nametag) {
14628
+ existing.nametag = l1Addr.nametag;
14629
+ }
14630
+ } else {
14631
+ const addrInfo = this._deriveAddressInternal(l1Addr.index, false);
14632
+ transportResult.addresses.push({
14633
+ index: l1Addr.index,
14634
+ l1Address: l1Addr.address,
14635
+ directAddress: "",
14636
+ chainPubkey: addrInfo.publicKey,
14637
+ nametag: l1Addr.nametag,
14638
+ l1Balance: l1Addr.balance,
14639
+ source: "l1"
14640
+ });
14641
+ }
14642
+ }
14643
+ transportResult.addresses.sort((a, b) => a.index - b.index);
14644
+ } catch (err) {
14645
+ console.warn("[Sphere] L1 scan failed during discovery (non-fatal):", err);
14646
+ }
14647
+ }
14648
+ if (options.autoTrack && transportResult.addresses.length > 0) {
14649
+ await this.trackScannedAddresses(
14650
+ transportResult.addresses.map((a) => ({
14651
+ index: a.index,
14652
+ // Preserve existing hidden state; default to false for newly discovered
14653
+ hidden: this._trackedAddresses.get(a.index)?.hidden ?? false,
14654
+ nametag: a.nametag
14655
+ }))
14656
+ );
14657
+ }
14658
+ return transportResult;
14659
+ }
14410
14660
  // ===========================================================================
14411
14661
  // Public Methods - Status
14412
14662
  // ===========================================================================
@@ -14978,6 +15228,17 @@ var Sphere = class _Sphere {
14978
15228
  return;
14979
15229
  }
14980
15230
  }
15231
+ const needsUpdate = !existing.directAddress || !existing.l1Address || !existing.chainPubkey || this._identity?.nametag && !existing.nametag;
15232
+ if (needsUpdate) {
15233
+ console.log("[Sphere] Existing binding incomplete, re-publishing with full data");
15234
+ await this._transport.publishIdentityBinding(
15235
+ this._identity.chainPubkey,
15236
+ this._identity.l1Address,
15237
+ this._identity.directAddress || "",
15238
+ this._identity?.nametag || existing.nametag || void 0
15239
+ );
15240
+ return;
15241
+ }
14981
15242
  console.log("[Sphere] Existing binding found, skipping re-publish");
14982
15243
  return;
14983
15244
  }
@@ -15466,6 +15727,7 @@ function formatAmount(amount, options = {}) {
15466
15727
  init_bech32();
15467
15728
 
15468
15729
  // core/network-health.ts
15730
+ init_constants();
15469
15731
  var DEFAULT_TIMEOUT_MS = 5e3;
15470
15732
  async function checkNetworkHealth(network = "testnet", options) {
15471
15733
  const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -15651,6 +15913,9 @@ async function runCustomCheck(name, checkFn, timeoutMs) {
15651
15913
  }
15652
15914
  }
15653
15915
 
15916
+ // index.ts
15917
+ init_constants();
15918
+
15654
15919
  // types/payment-session.ts
15655
15920
  function createPaymentSession(params) {
15656
15921
  const now = Date.now();
@@ -15722,6 +15987,9 @@ var SphereError = class extends Error {
15722
15987
  }
15723
15988
  };
15724
15989
 
15990
+ // index.ts
15991
+ init_constants();
15992
+
15725
15993
  // validation/token-validator.ts
15726
15994
  var TokenValidator = class {
15727
15995
  aggregatorClient = null;
@@ -16050,6 +16318,7 @@ function createTokenValidator(options) {
16050
16318
  var import_nostr_js_sdk4 = require("@unicitylabs/nostr-js-sdk");
16051
16319
 
16052
16320
  // price/CoinGeckoPriceProvider.ts
16321
+ init_constants();
16053
16322
  var CoinGeckoPriceProvider = class {
16054
16323
  platform = "coingecko";
16055
16324
  cache = /* @__PURE__ */ new Map();