@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.
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +484 -246
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +171 -23
- package/dist/core/index.d.ts +171 -23
- package/dist/core/index.js +483 -246
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +40 -2
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +40 -2
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +40 -2
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +16 -3
- package/dist/impl/nodejs/index.d.ts +16 -3
- package/dist/impl/nodejs/index.js +40 -2
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +540 -297
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +155 -25
- package/dist/index.d.ts +155 -25
- package/dist/index.js +540 -297
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +68 -1
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +68 -1
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,6 +14,228 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// constants.ts
|
|
18
|
+
function getAddressStorageKey(addressId, key) {
|
|
19
|
+
return `${addressId}_${key}`;
|
|
20
|
+
}
|
|
21
|
+
function getAddressId(directAddress) {
|
|
22
|
+
let hash = directAddress;
|
|
23
|
+
if (hash.startsWith("DIRECT://")) {
|
|
24
|
+
hash = hash.slice(9);
|
|
25
|
+
} else if (hash.startsWith("DIRECT:")) {
|
|
26
|
+
hash = hash.slice(7);
|
|
27
|
+
}
|
|
28
|
+
const first = hash.slice(0, 6).toLowerCase();
|
|
29
|
+
const last = hash.slice(-6).toLowerCase();
|
|
30
|
+
return `DIRECT_${first}_${last}`;
|
|
31
|
+
}
|
|
32
|
+
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;
|
|
33
|
+
var init_constants = __esm({
|
|
34
|
+
"constants.ts"() {
|
|
35
|
+
"use strict";
|
|
36
|
+
STORAGE_PREFIX = "sphere_";
|
|
37
|
+
DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
|
|
38
|
+
STORAGE_KEYS_GLOBAL = {
|
|
39
|
+
/** Encrypted BIP39 mnemonic */
|
|
40
|
+
MNEMONIC: "mnemonic",
|
|
41
|
+
/** Encrypted master private key */
|
|
42
|
+
MASTER_KEY: "master_key",
|
|
43
|
+
/** BIP32 chain code */
|
|
44
|
+
CHAIN_CODE: "chain_code",
|
|
45
|
+
/** HD derivation path (full path like m/44'/0'/0'/0/0) */
|
|
46
|
+
DERIVATION_PATH: "derivation_path",
|
|
47
|
+
/** Base derivation path (like m/44'/0'/0' without chain/index) */
|
|
48
|
+
BASE_PATH: "base_path",
|
|
49
|
+
/** Derivation mode: bip32, wif_hmac, legacy_hmac */
|
|
50
|
+
DERIVATION_MODE: "derivation_mode",
|
|
51
|
+
/** Wallet source: mnemonic, file, unknown */
|
|
52
|
+
WALLET_SOURCE: "wallet_source",
|
|
53
|
+
/** Wallet existence flag */
|
|
54
|
+
WALLET_EXISTS: "wallet_exists",
|
|
55
|
+
/** Current active address index */
|
|
56
|
+
CURRENT_ADDRESS_INDEX: "current_address_index",
|
|
57
|
+
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
58
|
+
ADDRESS_NAMETAGS: "address_nametags",
|
|
59
|
+
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
60
|
+
TRACKED_ADDRESSES: "tracked_addresses",
|
|
61
|
+
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
62
|
+
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
63
|
+
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
64
|
+
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
65
|
+
/** Cached token registry JSON (fetched from remote) */
|
|
66
|
+
TOKEN_REGISTRY_CACHE: "token_registry_cache",
|
|
67
|
+
/** Timestamp of last token registry cache update (ms since epoch) */
|
|
68
|
+
TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
|
|
69
|
+
/** Cached price data JSON (from CoinGecko or other provider) */
|
|
70
|
+
PRICE_CACHE: "price_cache",
|
|
71
|
+
/** Timestamp of last price cache update (ms since epoch) */
|
|
72
|
+
PRICE_CACHE_TS: "price_cache_ts"
|
|
73
|
+
};
|
|
74
|
+
STORAGE_KEYS_ADDRESS = {
|
|
75
|
+
/** Pending transfers for this address */
|
|
76
|
+
PENDING_TRANSFERS: "pending_transfers",
|
|
77
|
+
/** Transfer outbox for this address */
|
|
78
|
+
OUTBOX: "outbox",
|
|
79
|
+
/** Conversations for this address */
|
|
80
|
+
CONVERSATIONS: "conversations",
|
|
81
|
+
/** Messages for this address */
|
|
82
|
+
MESSAGES: "messages",
|
|
83
|
+
/** Transaction history for this address */
|
|
84
|
+
TRANSACTION_HISTORY: "transaction_history",
|
|
85
|
+
/** Pending V5 finalization tokens (unconfirmed instant split tokens) */
|
|
86
|
+
PENDING_V5_TOKENS: "pending_v5_tokens",
|
|
87
|
+
/** Group chat: joined groups for this address */
|
|
88
|
+
GROUP_CHAT_GROUPS: "group_chat_groups",
|
|
89
|
+
/** Group chat: messages for this address */
|
|
90
|
+
GROUP_CHAT_MESSAGES: "group_chat_messages",
|
|
91
|
+
/** Group chat: members for this address */
|
|
92
|
+
GROUP_CHAT_MEMBERS: "group_chat_members",
|
|
93
|
+
/** Group chat: processed event IDs for deduplication */
|
|
94
|
+
GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
|
|
95
|
+
};
|
|
96
|
+
STORAGE_KEYS = {
|
|
97
|
+
...STORAGE_KEYS_GLOBAL,
|
|
98
|
+
...STORAGE_KEYS_ADDRESS
|
|
99
|
+
};
|
|
100
|
+
DEFAULT_NOSTR_RELAYS = [
|
|
101
|
+
"wss://relay.unicity.network",
|
|
102
|
+
"wss://relay.damus.io",
|
|
103
|
+
"wss://nos.lol",
|
|
104
|
+
"wss://relay.nostr.band"
|
|
105
|
+
];
|
|
106
|
+
NOSTR_EVENT_KINDS = {
|
|
107
|
+
/** NIP-04 encrypted direct message */
|
|
108
|
+
DIRECT_MESSAGE: 4,
|
|
109
|
+
/** Token transfer (Unicity custom - 31113) */
|
|
110
|
+
TOKEN_TRANSFER: 31113,
|
|
111
|
+
/** Payment request (Unicity custom - 31115) */
|
|
112
|
+
PAYMENT_REQUEST: 31115,
|
|
113
|
+
/** Payment request response (Unicity custom - 31116) */
|
|
114
|
+
PAYMENT_REQUEST_RESPONSE: 31116,
|
|
115
|
+
/** Nametag binding (NIP-78 app-specific data) */
|
|
116
|
+
NAMETAG_BINDING: 30078,
|
|
117
|
+
/** Public broadcast */
|
|
118
|
+
BROADCAST: 1
|
|
119
|
+
};
|
|
120
|
+
NIP29_KINDS = {
|
|
121
|
+
/** Chat message sent to group */
|
|
122
|
+
CHAT_MESSAGE: 9,
|
|
123
|
+
/** Thread root message */
|
|
124
|
+
THREAD_ROOT: 11,
|
|
125
|
+
/** Thread reply message */
|
|
126
|
+
THREAD_REPLY: 12,
|
|
127
|
+
/** User join request */
|
|
128
|
+
JOIN_REQUEST: 9021,
|
|
129
|
+
/** User leave request */
|
|
130
|
+
LEAVE_REQUEST: 9022,
|
|
131
|
+
/** Admin: add/update user */
|
|
132
|
+
PUT_USER: 9e3,
|
|
133
|
+
/** Admin: remove user */
|
|
134
|
+
REMOVE_USER: 9001,
|
|
135
|
+
/** Admin: edit group metadata */
|
|
136
|
+
EDIT_METADATA: 9002,
|
|
137
|
+
/** Admin: delete event */
|
|
138
|
+
DELETE_EVENT: 9005,
|
|
139
|
+
/** Admin: create group */
|
|
140
|
+
CREATE_GROUP: 9007,
|
|
141
|
+
/** Admin: delete group */
|
|
142
|
+
DELETE_GROUP: 9008,
|
|
143
|
+
/** Admin: create invite code */
|
|
144
|
+
CREATE_INVITE: 9009,
|
|
145
|
+
/** Relay-signed group metadata */
|
|
146
|
+
GROUP_METADATA: 39e3,
|
|
147
|
+
/** Relay-signed group admins */
|
|
148
|
+
GROUP_ADMINS: 39001,
|
|
149
|
+
/** Relay-signed group members */
|
|
150
|
+
GROUP_MEMBERS: 39002,
|
|
151
|
+
/** Relay-signed group roles */
|
|
152
|
+
GROUP_ROLES: 39003
|
|
153
|
+
};
|
|
154
|
+
DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
|
|
155
|
+
DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
|
|
156
|
+
TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
|
|
157
|
+
DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
|
|
158
|
+
DEFAULT_IPFS_GATEWAYS = [
|
|
159
|
+
"https://unicity-ipfs1.dyndns.org"
|
|
160
|
+
];
|
|
161
|
+
DEFAULT_IPFS_BOOTSTRAP_PEERS = [
|
|
162
|
+
"/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
|
|
163
|
+
"/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
|
|
164
|
+
"/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
|
|
165
|
+
"/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
|
|
166
|
+
];
|
|
167
|
+
DEFAULT_BASE_PATH = "m/44'/0'/0'";
|
|
168
|
+
DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
|
|
169
|
+
COIN_TYPES = {
|
|
170
|
+
/** ALPHA token (L1 blockchain) */
|
|
171
|
+
ALPHA: "ALPHA",
|
|
172
|
+
/** Test token */
|
|
173
|
+
TEST: "TEST"
|
|
174
|
+
};
|
|
175
|
+
DEFAULT_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
|
|
176
|
+
TEST_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
|
|
177
|
+
TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
178
|
+
TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
|
|
179
|
+
TEST_NOSTR_RELAYS = [
|
|
180
|
+
"wss://nostr-relay.testnet.unicity.network"
|
|
181
|
+
];
|
|
182
|
+
DEFAULT_GROUP_RELAYS = [
|
|
183
|
+
"wss://sphere-relay.unicity.network"
|
|
184
|
+
];
|
|
185
|
+
NETWORKS = {
|
|
186
|
+
mainnet: {
|
|
187
|
+
name: "Mainnet",
|
|
188
|
+
aggregatorUrl: DEFAULT_AGGREGATOR_URL,
|
|
189
|
+
nostrRelays: DEFAULT_NOSTR_RELAYS,
|
|
190
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
191
|
+
electrumUrl: DEFAULT_ELECTRUM_URL,
|
|
192
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
193
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
194
|
+
},
|
|
195
|
+
testnet: {
|
|
196
|
+
name: "Testnet",
|
|
197
|
+
aggregatorUrl: TEST_AGGREGATOR_URL,
|
|
198
|
+
nostrRelays: TEST_NOSTR_RELAYS,
|
|
199
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
200
|
+
electrumUrl: TEST_ELECTRUM_URL,
|
|
201
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
202
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
203
|
+
},
|
|
204
|
+
dev: {
|
|
205
|
+
name: "Development",
|
|
206
|
+
aggregatorUrl: DEV_AGGREGATOR_URL,
|
|
207
|
+
nostrRelays: TEST_NOSTR_RELAYS,
|
|
208
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
209
|
+
electrumUrl: TEST_ELECTRUM_URL,
|
|
210
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
211
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
TIMEOUTS = {
|
|
215
|
+
/** WebSocket connection timeout */
|
|
216
|
+
WEBSOCKET_CONNECT: 1e4,
|
|
217
|
+
/** Nostr relay reconnect delay */
|
|
218
|
+
NOSTR_RECONNECT_DELAY: 3e3,
|
|
219
|
+
/** Max reconnect attempts */
|
|
220
|
+
MAX_RECONNECT_ATTEMPTS: 5,
|
|
221
|
+
/** Proof polling interval */
|
|
222
|
+
PROOF_POLL_INTERVAL: 1e3,
|
|
223
|
+
/** Sync interval */
|
|
224
|
+
SYNC_INTERVAL: 6e4
|
|
225
|
+
};
|
|
226
|
+
LIMITS = {
|
|
227
|
+
/** Min nametag length */
|
|
228
|
+
NAMETAG_MIN_LENGTH: 3,
|
|
229
|
+
/** Max nametag length */
|
|
230
|
+
NAMETAG_MAX_LENGTH: 20,
|
|
231
|
+
/** Max memo length */
|
|
232
|
+
MEMO_MAX_LENGTH: 500,
|
|
233
|
+
/** Max message length */
|
|
234
|
+
MESSAGE_MAX_LENGTH: 1e4
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
17
239
|
// core/bech32.ts
|
|
18
240
|
function convertBits(data, fromBits, toBits, pad) {
|
|
19
241
|
let acc = 0;
|
|
@@ -430,7 +652,8 @@ var init_network = __esm({
|
|
|
430
652
|
"l1/network.ts"() {
|
|
431
653
|
"use strict";
|
|
432
654
|
init_addressToScriptHash();
|
|
433
|
-
|
|
655
|
+
init_constants();
|
|
656
|
+
DEFAULT_ENDPOINT = DEFAULT_ELECTRUM_URL;
|
|
434
657
|
ws = null;
|
|
435
658
|
isConnected = false;
|
|
436
659
|
isConnecting = false;
|
|
@@ -450,6 +673,9 @@ var init_network = __esm({
|
|
|
450
673
|
}
|
|
451
674
|
});
|
|
452
675
|
|
|
676
|
+
// modules/payments/L1PaymentsModule.ts
|
|
677
|
+
init_constants();
|
|
678
|
+
|
|
453
679
|
// l1/index.ts
|
|
454
680
|
var l1_exports = {};
|
|
455
681
|
__export(l1_exports, {
|
|
@@ -1635,7 +1861,7 @@ var L1PaymentsModule = class {
|
|
|
1635
1861
|
_transport;
|
|
1636
1862
|
constructor(config) {
|
|
1637
1863
|
this._config = {
|
|
1638
|
-
electrumUrl: config?.electrumUrl ??
|
|
1864
|
+
electrumUrl: config?.electrumUrl ?? DEFAULT_ELECTRUM_URL,
|
|
1639
1865
|
network: config?.network ?? "mainnet",
|
|
1640
1866
|
defaultFeeRate: config?.defaultFeeRate ?? 10,
|
|
1641
1867
|
enableVesting: config?.enableVesting ?? true
|
|
@@ -2475,221 +2701,8 @@ var NametagMinter = class {
|
|
|
2475
2701
|
}
|
|
2476
2702
|
};
|
|
2477
2703
|
|
|
2478
|
-
//
|
|
2479
|
-
|
|
2480
|
-
var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
|
|
2481
|
-
var STORAGE_KEYS_GLOBAL = {
|
|
2482
|
-
/** Encrypted BIP39 mnemonic */
|
|
2483
|
-
MNEMONIC: "mnemonic",
|
|
2484
|
-
/** Encrypted master private key */
|
|
2485
|
-
MASTER_KEY: "master_key",
|
|
2486
|
-
/** BIP32 chain code */
|
|
2487
|
-
CHAIN_CODE: "chain_code",
|
|
2488
|
-
/** HD derivation path (full path like m/44'/0'/0'/0/0) */
|
|
2489
|
-
DERIVATION_PATH: "derivation_path",
|
|
2490
|
-
/** Base derivation path (like m/44'/0'/0' without chain/index) */
|
|
2491
|
-
BASE_PATH: "base_path",
|
|
2492
|
-
/** Derivation mode: bip32, wif_hmac, legacy_hmac */
|
|
2493
|
-
DERIVATION_MODE: "derivation_mode",
|
|
2494
|
-
/** Wallet source: mnemonic, file, unknown */
|
|
2495
|
-
WALLET_SOURCE: "wallet_source",
|
|
2496
|
-
/** Wallet existence flag */
|
|
2497
|
-
WALLET_EXISTS: "wallet_exists",
|
|
2498
|
-
/** Current active address index */
|
|
2499
|
-
CURRENT_ADDRESS_INDEX: "current_address_index",
|
|
2500
|
-
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
2501
|
-
ADDRESS_NAMETAGS: "address_nametags",
|
|
2502
|
-
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
2503
|
-
TRACKED_ADDRESSES: "tracked_addresses",
|
|
2504
|
-
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
2505
|
-
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
2506
|
-
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
2507
|
-
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
2508
|
-
/** Cached token registry JSON (fetched from remote) */
|
|
2509
|
-
TOKEN_REGISTRY_CACHE: "token_registry_cache",
|
|
2510
|
-
/** Timestamp of last token registry cache update (ms since epoch) */
|
|
2511
|
-
TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
|
|
2512
|
-
/** Cached price data JSON (from CoinGecko or other provider) */
|
|
2513
|
-
PRICE_CACHE: "price_cache",
|
|
2514
|
-
/** Timestamp of last price cache update (ms since epoch) */
|
|
2515
|
-
PRICE_CACHE_TS: "price_cache_ts"
|
|
2516
|
-
};
|
|
2517
|
-
var STORAGE_KEYS_ADDRESS = {
|
|
2518
|
-
/** Pending transfers for this address */
|
|
2519
|
-
PENDING_TRANSFERS: "pending_transfers",
|
|
2520
|
-
/** Transfer outbox for this address */
|
|
2521
|
-
OUTBOX: "outbox",
|
|
2522
|
-
/** Conversations for this address */
|
|
2523
|
-
CONVERSATIONS: "conversations",
|
|
2524
|
-
/** Messages for this address */
|
|
2525
|
-
MESSAGES: "messages",
|
|
2526
|
-
/** Transaction history for this address */
|
|
2527
|
-
TRANSACTION_HISTORY: "transaction_history",
|
|
2528
|
-
/** Pending V5 finalization tokens (unconfirmed instant split tokens) */
|
|
2529
|
-
PENDING_V5_TOKENS: "pending_v5_tokens",
|
|
2530
|
-
/** Group chat: joined groups for this address */
|
|
2531
|
-
GROUP_CHAT_GROUPS: "group_chat_groups",
|
|
2532
|
-
/** Group chat: messages for this address */
|
|
2533
|
-
GROUP_CHAT_MESSAGES: "group_chat_messages",
|
|
2534
|
-
/** Group chat: members for this address */
|
|
2535
|
-
GROUP_CHAT_MEMBERS: "group_chat_members",
|
|
2536
|
-
/** Group chat: processed event IDs for deduplication */
|
|
2537
|
-
GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
|
|
2538
|
-
};
|
|
2539
|
-
var STORAGE_KEYS = {
|
|
2540
|
-
...STORAGE_KEYS_GLOBAL,
|
|
2541
|
-
...STORAGE_KEYS_ADDRESS
|
|
2542
|
-
};
|
|
2543
|
-
function getAddressStorageKey(addressId, key) {
|
|
2544
|
-
return `${addressId}_${key}`;
|
|
2545
|
-
}
|
|
2546
|
-
function getAddressId(directAddress) {
|
|
2547
|
-
let hash = directAddress;
|
|
2548
|
-
if (hash.startsWith("DIRECT://")) {
|
|
2549
|
-
hash = hash.slice(9);
|
|
2550
|
-
} else if (hash.startsWith("DIRECT:")) {
|
|
2551
|
-
hash = hash.slice(7);
|
|
2552
|
-
}
|
|
2553
|
-
const first = hash.slice(0, 6).toLowerCase();
|
|
2554
|
-
const last = hash.slice(-6).toLowerCase();
|
|
2555
|
-
return `DIRECT_${first}_${last}`;
|
|
2556
|
-
}
|
|
2557
|
-
var DEFAULT_NOSTR_RELAYS = [
|
|
2558
|
-
"wss://relay.unicity.network",
|
|
2559
|
-
"wss://relay.damus.io",
|
|
2560
|
-
"wss://nos.lol",
|
|
2561
|
-
"wss://relay.nostr.band"
|
|
2562
|
-
];
|
|
2563
|
-
var NOSTR_EVENT_KINDS = {
|
|
2564
|
-
/** NIP-04 encrypted direct message */
|
|
2565
|
-
DIRECT_MESSAGE: 4,
|
|
2566
|
-
/** Token transfer (Unicity custom - 31113) */
|
|
2567
|
-
TOKEN_TRANSFER: 31113,
|
|
2568
|
-
/** Payment request (Unicity custom - 31115) */
|
|
2569
|
-
PAYMENT_REQUEST: 31115,
|
|
2570
|
-
/** Payment request response (Unicity custom - 31116) */
|
|
2571
|
-
PAYMENT_REQUEST_RESPONSE: 31116,
|
|
2572
|
-
/** Nametag binding (NIP-78 app-specific data) */
|
|
2573
|
-
NAMETAG_BINDING: 30078,
|
|
2574
|
-
/** Public broadcast */
|
|
2575
|
-
BROADCAST: 1
|
|
2576
|
-
};
|
|
2577
|
-
var NIP29_KINDS = {
|
|
2578
|
-
/** Chat message sent to group */
|
|
2579
|
-
CHAT_MESSAGE: 9,
|
|
2580
|
-
/** Thread root message */
|
|
2581
|
-
THREAD_ROOT: 11,
|
|
2582
|
-
/** Thread reply message */
|
|
2583
|
-
THREAD_REPLY: 12,
|
|
2584
|
-
/** User join request */
|
|
2585
|
-
JOIN_REQUEST: 9021,
|
|
2586
|
-
/** User leave request */
|
|
2587
|
-
LEAVE_REQUEST: 9022,
|
|
2588
|
-
/** Admin: add/update user */
|
|
2589
|
-
PUT_USER: 9e3,
|
|
2590
|
-
/** Admin: remove user */
|
|
2591
|
-
REMOVE_USER: 9001,
|
|
2592
|
-
/** Admin: edit group metadata */
|
|
2593
|
-
EDIT_METADATA: 9002,
|
|
2594
|
-
/** Admin: delete event */
|
|
2595
|
-
DELETE_EVENT: 9005,
|
|
2596
|
-
/** Admin: create group */
|
|
2597
|
-
CREATE_GROUP: 9007,
|
|
2598
|
-
/** Admin: delete group */
|
|
2599
|
-
DELETE_GROUP: 9008,
|
|
2600
|
-
/** Admin: create invite code */
|
|
2601
|
-
CREATE_INVITE: 9009,
|
|
2602
|
-
/** Relay-signed group metadata */
|
|
2603
|
-
GROUP_METADATA: 39e3,
|
|
2604
|
-
/** Relay-signed group admins */
|
|
2605
|
-
GROUP_ADMINS: 39001,
|
|
2606
|
-
/** Relay-signed group members */
|
|
2607
|
-
GROUP_MEMBERS: 39002,
|
|
2608
|
-
/** Relay-signed group roles */
|
|
2609
|
-
GROUP_ROLES: 39003
|
|
2610
|
-
};
|
|
2611
|
-
var DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
|
|
2612
|
-
var DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
|
|
2613
|
-
var TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
|
|
2614
|
-
var DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
|
|
2615
|
-
var DEFAULT_IPFS_GATEWAYS = [
|
|
2616
|
-
"https://unicity-ipfs1.dyndns.org"
|
|
2617
|
-
];
|
|
2618
|
-
var DEFAULT_IPFS_BOOTSTRAP_PEERS = [
|
|
2619
|
-
"/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
|
|
2620
|
-
"/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
|
|
2621
|
-
"/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
|
|
2622
|
-
"/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
|
|
2623
|
-
];
|
|
2624
|
-
var DEFAULT_BASE_PATH = "m/44'/0'/0'";
|
|
2625
|
-
var DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
|
|
2626
|
-
var COIN_TYPES = {
|
|
2627
|
-
/** ALPHA token (L1 blockchain) */
|
|
2628
|
-
ALPHA: "ALPHA",
|
|
2629
|
-
/** Test token */
|
|
2630
|
-
TEST: "TEST"
|
|
2631
|
-
};
|
|
2632
|
-
var DEFAULT_ELECTRUM_URL = "wss://fulcrum.alpha.unicity.network:50004";
|
|
2633
|
-
var TEST_ELECTRUM_URL = "wss://fulcrum.alpha.testnet.unicity.network:50004";
|
|
2634
|
-
var TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
2635
|
-
var TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
|
|
2636
|
-
var TEST_NOSTR_RELAYS = [
|
|
2637
|
-
"wss://nostr-relay.testnet.unicity.network"
|
|
2638
|
-
];
|
|
2639
|
-
var DEFAULT_GROUP_RELAYS = [
|
|
2640
|
-
"wss://sphere-relay.unicity.network"
|
|
2641
|
-
];
|
|
2642
|
-
var NETWORKS = {
|
|
2643
|
-
mainnet: {
|
|
2644
|
-
name: "Mainnet",
|
|
2645
|
-
aggregatorUrl: DEFAULT_AGGREGATOR_URL,
|
|
2646
|
-
nostrRelays: DEFAULT_NOSTR_RELAYS,
|
|
2647
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2648
|
-
electrumUrl: DEFAULT_ELECTRUM_URL,
|
|
2649
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2650
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2651
|
-
},
|
|
2652
|
-
testnet: {
|
|
2653
|
-
name: "Testnet",
|
|
2654
|
-
aggregatorUrl: TEST_AGGREGATOR_URL,
|
|
2655
|
-
nostrRelays: TEST_NOSTR_RELAYS,
|
|
2656
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2657
|
-
electrumUrl: TEST_ELECTRUM_URL,
|
|
2658
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2659
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2660
|
-
},
|
|
2661
|
-
dev: {
|
|
2662
|
-
name: "Development",
|
|
2663
|
-
aggregatorUrl: DEV_AGGREGATOR_URL,
|
|
2664
|
-
nostrRelays: TEST_NOSTR_RELAYS,
|
|
2665
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2666
|
-
electrumUrl: TEST_ELECTRUM_URL,
|
|
2667
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2668
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2669
|
-
}
|
|
2670
|
-
};
|
|
2671
|
-
var TIMEOUTS = {
|
|
2672
|
-
/** WebSocket connection timeout */
|
|
2673
|
-
WEBSOCKET_CONNECT: 1e4,
|
|
2674
|
-
/** Nostr relay reconnect delay */
|
|
2675
|
-
NOSTR_RECONNECT_DELAY: 3e3,
|
|
2676
|
-
/** Max reconnect attempts */
|
|
2677
|
-
MAX_RECONNECT_ATTEMPTS: 5,
|
|
2678
|
-
/** Proof polling interval */
|
|
2679
|
-
PROOF_POLL_INTERVAL: 1e3,
|
|
2680
|
-
/** Sync interval */
|
|
2681
|
-
SYNC_INTERVAL: 6e4
|
|
2682
|
-
};
|
|
2683
|
-
var LIMITS = {
|
|
2684
|
-
/** Min nametag length */
|
|
2685
|
-
NAMETAG_MIN_LENGTH: 3,
|
|
2686
|
-
/** Max nametag length */
|
|
2687
|
-
NAMETAG_MAX_LENGTH: 20,
|
|
2688
|
-
/** Max memo length */
|
|
2689
|
-
MEMO_MAX_LENGTH: 500,
|
|
2690
|
-
/** Max message length */
|
|
2691
|
-
MESSAGE_MAX_LENGTH: 1e4
|
|
2692
|
-
};
|
|
2704
|
+
// modules/payments/PaymentsModule.ts
|
|
2705
|
+
init_constants();
|
|
2693
2706
|
|
|
2694
2707
|
// types/txf.ts
|
|
2695
2708
|
var ARCHIVED_PREFIX = "archived-";
|
|
@@ -2734,6 +2747,7 @@ function isValidTokenId(tokenId) {
|
|
|
2734
2747
|
}
|
|
2735
2748
|
|
|
2736
2749
|
// registry/TokenRegistry.ts
|
|
2750
|
+
init_constants();
|
|
2737
2751
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
2738
2752
|
var TokenRegistry = class _TokenRegistry {
|
|
2739
2753
|
static instance = null;
|
|
@@ -7631,6 +7645,7 @@ import { HashAlgorithm as HashAlgorithm6 } from "@unicitylabs/state-transition-s
|
|
|
7631
7645
|
import { UnmaskedPredicate as UnmaskedPredicate6 } from "@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate";
|
|
7632
7646
|
|
|
7633
7647
|
// modules/communications/CommunicationsModule.ts
|
|
7648
|
+
init_constants();
|
|
7634
7649
|
var CommunicationsModule = class {
|
|
7635
7650
|
config;
|
|
7636
7651
|
deps = null;
|
|
@@ -8105,6 +8120,7 @@ function createCommunicationsModule(config) {
|
|
|
8105
8120
|
}
|
|
8106
8121
|
|
|
8107
8122
|
// modules/groupchat/GroupChatModule.ts
|
|
8123
|
+
init_constants();
|
|
8108
8124
|
import {
|
|
8109
8125
|
NostrClient,
|
|
8110
8126
|
NostrKeyManager,
|
|
@@ -8360,10 +8376,12 @@ var GroupChatModule = class {
|
|
|
8360
8376
|
if (!this.client) return;
|
|
8361
8377
|
const groupIds = Array.from(this.groups.keys());
|
|
8362
8378
|
if (groupIds.length === 0) return;
|
|
8379
|
+
const latestTimestamp = this.getLatestMessageTimestamp(groupIds);
|
|
8363
8380
|
this.trackSubscription(
|
|
8364
8381
|
createNip29Filter({
|
|
8365
8382
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
8366
|
-
"#h": groupIds
|
|
8383
|
+
"#h": groupIds,
|
|
8384
|
+
...latestTimestamp ? { since: latestTimestamp } : {}
|
|
8367
8385
|
}),
|
|
8368
8386
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
8369
8387
|
);
|
|
@@ -8384,10 +8402,12 @@ var GroupChatModule = class {
|
|
|
8384
8402
|
}
|
|
8385
8403
|
subscribeToGroup(groupId) {
|
|
8386
8404
|
if (!this.client) return;
|
|
8405
|
+
const latestTimestamp = this.getLatestMessageTimestamp([groupId]);
|
|
8387
8406
|
this.trackSubscription(
|
|
8388
8407
|
createNip29Filter({
|
|
8389
8408
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
8390
|
-
"#h": [groupId]
|
|
8409
|
+
"#h": [groupId],
|
|
8410
|
+
...latestTimestamp ? { since: latestTimestamp } : {}
|
|
8391
8411
|
}),
|
|
8392
8412
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
8393
8413
|
);
|
|
@@ -9079,6 +9099,23 @@ var GroupChatModule = class {
|
|
|
9079
9099
|
getMyPublicKey() {
|
|
9080
9100
|
return this.keyManager?.getPublicKeyHex() || null;
|
|
9081
9101
|
}
|
|
9102
|
+
/**
|
|
9103
|
+
* Returns the latest message timestamp (in Nostr seconds) across the given groups,
|
|
9104
|
+
* or 0 if no messages exist. Used to set `since` on subscriptions so the relay
|
|
9105
|
+
* only sends events we don't already have.
|
|
9106
|
+
*/
|
|
9107
|
+
getLatestMessageTimestamp(groupIds) {
|
|
9108
|
+
let latest = 0;
|
|
9109
|
+
for (const gid of groupIds) {
|
|
9110
|
+
const msgs = this.messages.get(gid);
|
|
9111
|
+
if (!msgs) continue;
|
|
9112
|
+
for (const m of msgs) {
|
|
9113
|
+
const ts = Math.floor(m.timestamp / 1e3);
|
|
9114
|
+
if (ts > latest) latest = ts;
|
|
9115
|
+
}
|
|
9116
|
+
}
|
|
9117
|
+
return latest;
|
|
9118
|
+
}
|
|
9082
9119
|
// ===========================================================================
|
|
9083
9120
|
// Private — Relay Admin
|
|
9084
9121
|
// ===========================================================================
|
|
@@ -11933,6 +11970,9 @@ function createMarketModule(config) {
|
|
|
11933
11970
|
return new MarketModule(config);
|
|
11934
11971
|
}
|
|
11935
11972
|
|
|
11973
|
+
// core/Sphere.ts
|
|
11974
|
+
init_constants();
|
|
11975
|
+
|
|
11936
11976
|
// core/encryption.ts
|
|
11937
11977
|
import CryptoJS6 from "crypto-js";
|
|
11938
11978
|
function encryptSimple(plaintext, password) {
|
|
@@ -12036,6 +12076,72 @@ async function scanAddressesImpl(deriveAddress, options = {}) {
|
|
|
12036
12076
|
};
|
|
12037
12077
|
}
|
|
12038
12078
|
|
|
12079
|
+
// core/discover.ts
|
|
12080
|
+
async function discoverAddressesImpl(deriveTransportPubkey, batchResolve, options = {}) {
|
|
12081
|
+
const maxAddresses = options.maxAddresses ?? 50;
|
|
12082
|
+
const gapLimit = options.gapLimit ?? 20;
|
|
12083
|
+
const batchSize = options.batchSize ?? 20;
|
|
12084
|
+
const { onProgress, signal } = options;
|
|
12085
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
12086
|
+
let consecutiveEmpty = 0;
|
|
12087
|
+
let scanned = 0;
|
|
12088
|
+
const totalBatches = Math.ceil(maxAddresses / batchSize);
|
|
12089
|
+
for (let batchStart = 0; batchStart < maxAddresses; batchStart += batchSize) {
|
|
12090
|
+
if (signal?.aborted) break;
|
|
12091
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12092
|
+
const batchEnd = Math.min(batchStart + batchSize, maxAddresses);
|
|
12093
|
+
const batchIndices = [];
|
|
12094
|
+
const pubkeyToIndex = /* @__PURE__ */ new Map();
|
|
12095
|
+
const pubkeyToInfo = /* @__PURE__ */ new Map();
|
|
12096
|
+
for (let i = batchStart; i < batchEnd; i++) {
|
|
12097
|
+
const info = deriveTransportPubkey(i);
|
|
12098
|
+
batchIndices.push(i);
|
|
12099
|
+
pubkeyToIndex.set(info.transportPubkey, i);
|
|
12100
|
+
pubkeyToInfo.set(info.transportPubkey, info);
|
|
12101
|
+
}
|
|
12102
|
+
const batchPubkeys = Array.from(pubkeyToIndex.keys());
|
|
12103
|
+
onProgress?.({
|
|
12104
|
+
currentBatch: Math.floor(batchStart / batchSize) + 1,
|
|
12105
|
+
totalBatches,
|
|
12106
|
+
discoveredCount: discovered.size,
|
|
12107
|
+
currentGap: consecutiveEmpty,
|
|
12108
|
+
phase: "transport"
|
|
12109
|
+
});
|
|
12110
|
+
const peerInfos = await batchResolve(batchPubkeys);
|
|
12111
|
+
const foundInBatch = /* @__PURE__ */ new Set();
|
|
12112
|
+
for (const peer of peerInfos) {
|
|
12113
|
+
const index = pubkeyToIndex.get(peer.transportPubkey);
|
|
12114
|
+
if (index !== void 0) {
|
|
12115
|
+
foundInBatch.add(index);
|
|
12116
|
+
const derived = pubkeyToInfo.get(peer.transportPubkey);
|
|
12117
|
+
discovered.set(index, {
|
|
12118
|
+
index,
|
|
12119
|
+
l1Address: peer.l1Address || derived.l1Address,
|
|
12120
|
+
directAddress: peer.directAddress || derived.directAddress,
|
|
12121
|
+
chainPubkey: peer.chainPubkey || derived.chainPubkey,
|
|
12122
|
+
nametag: peer.nametag,
|
|
12123
|
+
l1Balance: 0,
|
|
12124
|
+
source: "transport"
|
|
12125
|
+
});
|
|
12126
|
+
}
|
|
12127
|
+
}
|
|
12128
|
+
for (const idx of batchIndices) {
|
|
12129
|
+
scanned++;
|
|
12130
|
+
if (foundInBatch.has(idx)) {
|
|
12131
|
+
consecutiveEmpty = 0;
|
|
12132
|
+
} else {
|
|
12133
|
+
consecutiveEmpty++;
|
|
12134
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12135
|
+
}
|
|
12136
|
+
}
|
|
12137
|
+
}
|
|
12138
|
+
return {
|
|
12139
|
+
addresses: Array.from(discovered.values()).sort((a, b) => a.index - b.index),
|
|
12140
|
+
scannedCount: scanned,
|
|
12141
|
+
aborted: signal?.aborted ?? false
|
|
12142
|
+
};
|
|
12143
|
+
}
|
|
12144
|
+
|
|
12039
12145
|
// core/Sphere.ts
|
|
12040
12146
|
init_network();
|
|
12041
12147
|
|
|
@@ -12858,7 +12964,9 @@ var Sphere = class _Sphere {
|
|
|
12858
12964
|
price: options.price,
|
|
12859
12965
|
groupChat,
|
|
12860
12966
|
market,
|
|
12861
|
-
password: options.password
|
|
12967
|
+
password: options.password,
|
|
12968
|
+
discoverAddresses: options.discoverAddresses,
|
|
12969
|
+
onProgress: options.onProgress
|
|
12862
12970
|
});
|
|
12863
12971
|
return { sphere: sphere2, created: false };
|
|
12864
12972
|
}
|
|
@@ -12886,7 +12994,9 @@ var Sphere = class _Sphere {
|
|
|
12886
12994
|
price: options.price,
|
|
12887
12995
|
groupChat,
|
|
12888
12996
|
market,
|
|
12889
|
-
password: options.password
|
|
12997
|
+
password: options.password,
|
|
12998
|
+
discoverAddresses: options.discoverAddresses,
|
|
12999
|
+
onProgress: options.onProgress
|
|
12890
13000
|
});
|
|
12891
13001
|
return { sphere, created: true, generatedMnemonic };
|
|
12892
13002
|
}
|
|
@@ -12947,6 +13057,7 @@ var Sphere = class _Sphere {
|
|
|
12947
13057
|
if (await _Sphere.exists(options.storage)) {
|
|
12948
13058
|
throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
|
|
12949
13059
|
}
|
|
13060
|
+
const progress = options.onProgress;
|
|
12950
13061
|
if (!options.storage.isConnected()) {
|
|
12951
13062
|
await options.storage.connect();
|
|
12952
13063
|
}
|
|
@@ -12964,20 +13075,39 @@ var Sphere = class _Sphere {
|
|
|
12964
13075
|
marketConfig
|
|
12965
13076
|
);
|
|
12966
13077
|
sphere._password = options.password ?? null;
|
|
13078
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
12967
13079
|
await sphere.storeMnemonic(options.mnemonic, options.derivationPath);
|
|
12968
13080
|
await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
|
|
13081
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
12969
13082
|
await sphere.initializeProviders();
|
|
12970
13083
|
await sphere.initializeModules();
|
|
13084
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
12971
13085
|
await sphere.finalizeWalletCreation();
|
|
12972
13086
|
sphere._initialized = true;
|
|
12973
13087
|
_Sphere.instance = sphere;
|
|
12974
13088
|
await sphere.ensureAddressTracked(0);
|
|
12975
13089
|
if (options.nametag) {
|
|
13090
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
12976
13091
|
await sphere.registerNametag(options.nametag);
|
|
12977
13092
|
} else {
|
|
13093
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
12978
13094
|
await sphere.recoverNametagFromTransport();
|
|
13095
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
12979
13096
|
await sphere.syncIdentityWithTransport();
|
|
12980
13097
|
}
|
|
13098
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13099
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13100
|
+
try {
|
|
13101
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13102
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13103
|
+
if (result.addresses.length > 0) {
|
|
13104
|
+
console.log(`[Sphere.create] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13105
|
+
}
|
|
13106
|
+
} catch (err) {
|
|
13107
|
+
console.warn("[Sphere.create] Address discovery failed (non-fatal):", err);
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
13110
|
+
progress?.({ step: "complete", message: "Wallet created" });
|
|
12981
13111
|
return sphere;
|
|
12982
13112
|
}
|
|
12983
13113
|
/**
|
|
@@ -12987,6 +13117,7 @@ var Sphere = class _Sphere {
|
|
|
12987
13117
|
if (!await _Sphere.exists(options.storage)) {
|
|
12988
13118
|
throw new Error("No wallet found. Use Sphere.create() to create a new wallet.");
|
|
12989
13119
|
}
|
|
13120
|
+
const progress = options.onProgress;
|
|
12990
13121
|
_Sphere.configureTokenRegistry(options.storage, options.network);
|
|
12991
13122
|
const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
|
|
12992
13123
|
const marketConfig = _Sphere.resolveMarketConfig(options.market);
|
|
@@ -13004,13 +13135,17 @@ var Sphere = class _Sphere {
|
|
|
13004
13135
|
if (!options.storage.isConnected()) {
|
|
13005
13136
|
await options.storage.connect();
|
|
13006
13137
|
}
|
|
13138
|
+
progress?.({ step: "storing_keys", message: "Loading wallet keys..." });
|
|
13007
13139
|
await sphere.loadIdentityFromStorage();
|
|
13140
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13008
13141
|
await sphere.initializeProviders();
|
|
13009
13142
|
await sphere.initializeModules();
|
|
13143
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13010
13144
|
await sphere.syncIdentityWithTransport();
|
|
13011
13145
|
sphere._initialized = true;
|
|
13012
13146
|
_Sphere.instance = sphere;
|
|
13013
13147
|
if (sphere._identity?.nametag && !sphere._payments.hasNametag()) {
|
|
13148
|
+
progress?.({ step: "registering_nametag", message: "Restoring nametag token..." });
|
|
13014
13149
|
console.log(`[Sphere] Nametag @${sphere._identity.nametag} has no token, attempting to mint...`);
|
|
13015
13150
|
try {
|
|
13016
13151
|
const result = await sphere.mintNametag(sphere._identity.nametag);
|
|
@@ -13023,6 +13158,19 @@ var Sphere = class _Sphere {
|
|
|
13023
13158
|
console.warn(`[Sphere] Nametag token mint failed:`, err);
|
|
13024
13159
|
}
|
|
13025
13160
|
}
|
|
13161
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses && sphere._masterKey) {
|
|
13162
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13163
|
+
try {
|
|
13164
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13165
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13166
|
+
if (result.addresses.length > 0) {
|
|
13167
|
+
console.log(`[Sphere.load] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13168
|
+
}
|
|
13169
|
+
} catch (err) {
|
|
13170
|
+
console.warn("[Sphere.load] Address discovery failed (non-fatal):", err);
|
|
13171
|
+
}
|
|
13172
|
+
}
|
|
13173
|
+
progress?.({ step: "complete", message: "Wallet loaded" });
|
|
13026
13174
|
return sphere;
|
|
13027
13175
|
}
|
|
13028
13176
|
/**
|
|
@@ -13032,9 +13180,11 @@ var Sphere = class _Sphere {
|
|
|
13032
13180
|
if (!options.mnemonic && !options.masterKey) {
|
|
13033
13181
|
throw new Error("Either mnemonic or masterKey is required");
|
|
13034
13182
|
}
|
|
13183
|
+
const progress = options.onProgress;
|
|
13035
13184
|
console.log("[Sphere.import] Starting import...");
|
|
13036
13185
|
const needsClear = _Sphere.instance !== null || await _Sphere.exists(options.storage);
|
|
13037
13186
|
if (needsClear) {
|
|
13187
|
+
progress?.({ step: "clearing", message: "Clearing previous wallet data..." });
|
|
13038
13188
|
console.log("[Sphere.import] Clearing existing wallet data...");
|
|
13039
13189
|
await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
|
|
13040
13190
|
console.log("[Sphere.import] Clear done");
|
|
@@ -13059,6 +13209,7 @@ var Sphere = class _Sphere {
|
|
|
13059
13209
|
marketConfig
|
|
13060
13210
|
);
|
|
13061
13211
|
sphere._password = options.password ?? null;
|
|
13212
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
13062
13213
|
if (options.mnemonic) {
|
|
13063
13214
|
if (!_Sphere.validateMnemonic(options.mnemonic)) {
|
|
13064
13215
|
throw new Error("Invalid mnemonic");
|
|
@@ -13083,17 +13234,21 @@ var Sphere = class _Sphere {
|
|
|
13083
13234
|
options.derivationPath
|
|
13084
13235
|
);
|
|
13085
13236
|
}
|
|
13237
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13086
13238
|
console.log("[Sphere.import] Initializing providers...");
|
|
13087
13239
|
await sphere.initializeProviders();
|
|
13088
13240
|
console.log("[Sphere.import] Providers initialized. Initializing modules...");
|
|
13089
13241
|
await sphere.initializeModules();
|
|
13090
13242
|
console.log("[Sphere.import] Modules initialized");
|
|
13091
13243
|
if (!options.nametag) {
|
|
13244
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
13092
13245
|
console.log("[Sphere.import] Recovering nametag from transport...");
|
|
13093
13246
|
await sphere.recoverNametagFromTransport();
|
|
13094
13247
|
console.log("[Sphere.import] Nametag recovery done");
|
|
13248
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13095
13249
|
await sphere.syncIdentityWithTransport();
|
|
13096
13250
|
}
|
|
13251
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
13097
13252
|
console.log("[Sphere.import] Finalizing wallet creation...");
|
|
13098
13253
|
await sphere.finalizeWalletCreation();
|
|
13099
13254
|
sphere._initialized = true;
|
|
@@ -13101,10 +13256,12 @@ var Sphere = class _Sphere {
|
|
|
13101
13256
|
console.log("[Sphere.import] Tracking address 0...");
|
|
13102
13257
|
await sphere.ensureAddressTracked(0);
|
|
13103
13258
|
if (options.nametag) {
|
|
13259
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
13104
13260
|
console.log("[Sphere.import] Registering nametag...");
|
|
13105
13261
|
await sphere.registerNametag(options.nametag);
|
|
13106
13262
|
}
|
|
13107
13263
|
if (sphere._tokenStorageProviders.size > 0) {
|
|
13264
|
+
progress?.({ step: "syncing_tokens", message: "Syncing tokens..." });
|
|
13108
13265
|
try {
|
|
13109
13266
|
const syncResult = await sphere._payments.sync();
|
|
13110
13267
|
console.log(`[Sphere.import] Auto-sync: +${syncResult.added} -${syncResult.removed}`);
|
|
@@ -13112,6 +13269,19 @@ var Sphere = class _Sphere {
|
|
|
13112
13269
|
console.warn("[Sphere.import] Auto-sync failed (non-fatal):", err);
|
|
13113
13270
|
}
|
|
13114
13271
|
}
|
|
13272
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13273
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13274
|
+
try {
|
|
13275
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13276
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13277
|
+
if (result.addresses.length > 0) {
|
|
13278
|
+
console.log(`[Sphere.import] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13279
|
+
}
|
|
13280
|
+
} catch (err) {
|
|
13281
|
+
console.warn("[Sphere.import] Address discovery failed (non-fatal):", err);
|
|
13282
|
+
}
|
|
13283
|
+
}
|
|
13284
|
+
progress?.({ step: "complete", message: "Import complete" });
|
|
13115
13285
|
console.log("[Sphere.import] Import complete");
|
|
13116
13286
|
return sphere;
|
|
13117
13287
|
}
|
|
@@ -13525,55 +13695,44 @@ var Sphere = class _Sphere {
|
|
|
13525
13695
|
* ```
|
|
13526
13696
|
*/
|
|
13527
13697
|
static async importFromJSON(options) {
|
|
13698
|
+
const { jsonContent, password, ...baseOptions } = options;
|
|
13528
13699
|
try {
|
|
13529
|
-
const data = JSON.parse(
|
|
13700
|
+
const data = JSON.parse(jsonContent);
|
|
13530
13701
|
if (data.version !== "1.0" || data.type !== "sphere-wallet") {
|
|
13531
13702
|
return { success: false, error: "Invalid wallet format" };
|
|
13532
13703
|
}
|
|
13533
13704
|
let mnemonic = data.mnemonic;
|
|
13534
13705
|
let masterKey = data.wallet.masterPrivateKey;
|
|
13535
|
-
if (data.encrypted &&
|
|
13706
|
+
if (data.encrypted && password) {
|
|
13536
13707
|
if (mnemonic) {
|
|
13537
|
-
const decrypted = decryptSimple(mnemonic,
|
|
13708
|
+
const decrypted = decryptSimple(mnemonic, password);
|
|
13538
13709
|
if (!decrypted) {
|
|
13539
13710
|
return { success: false, error: "Failed to decrypt mnemonic - wrong password?" };
|
|
13540
13711
|
}
|
|
13541
13712
|
mnemonic = decrypted;
|
|
13542
13713
|
}
|
|
13543
13714
|
if (masterKey) {
|
|
13544
|
-
const decrypted = decryptSimple(masterKey,
|
|
13715
|
+
const decrypted = decryptSimple(masterKey, password);
|
|
13545
13716
|
if (!decrypted) {
|
|
13546
13717
|
return { success: false, error: "Failed to decrypt master key - wrong password?" };
|
|
13547
13718
|
}
|
|
13548
13719
|
masterKey = decrypted;
|
|
13549
13720
|
}
|
|
13550
|
-
} else if (data.encrypted && !
|
|
13721
|
+
} else if (data.encrypted && !password) {
|
|
13551
13722
|
return { success: false, error: "Password required for encrypted wallet" };
|
|
13552
13723
|
}
|
|
13553
13724
|
const basePath = data.wallet.descriptorPath ? `m/${data.wallet.descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13554
13725
|
if (mnemonic) {
|
|
13555
|
-
await _Sphere.import({
|
|
13556
|
-
mnemonic,
|
|
13557
|
-
basePath,
|
|
13558
|
-
storage: options.storage,
|
|
13559
|
-
transport: options.transport,
|
|
13560
|
-
oracle: options.oracle,
|
|
13561
|
-
tokenStorage: options.tokenStorage,
|
|
13562
|
-
l1: options.l1
|
|
13563
|
-
});
|
|
13726
|
+
await _Sphere.import({ ...baseOptions, mnemonic, basePath });
|
|
13564
13727
|
return { success: true, mnemonic };
|
|
13565
13728
|
}
|
|
13566
13729
|
if (masterKey) {
|
|
13567
13730
|
await _Sphere.import({
|
|
13731
|
+
...baseOptions,
|
|
13568
13732
|
masterKey,
|
|
13569
13733
|
chainCode: data.wallet.chainCode,
|
|
13570
13734
|
basePath,
|
|
13571
|
-
derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
|
|
13572
|
-
storage: options.storage,
|
|
13573
|
-
transport: options.transport,
|
|
13574
|
-
oracle: options.oracle,
|
|
13575
|
-
tokenStorage: options.tokenStorage,
|
|
13576
|
-
l1: options.l1
|
|
13735
|
+
derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
|
|
13577
13736
|
});
|
|
13578
13737
|
return { success: true };
|
|
13579
13738
|
}
|
|
@@ -13616,7 +13775,7 @@ var Sphere = class _Sphere {
|
|
|
13616
13775
|
* ```
|
|
13617
13776
|
*/
|
|
13618
13777
|
static async importFromLegacyFile(options) {
|
|
13619
|
-
const { fileContent, fileName, password, onDecryptProgress } = options;
|
|
13778
|
+
const { fileContent, fileName, password, onDecryptProgress, ...baseOptions } = options;
|
|
13620
13779
|
const fileType = _Sphere.detectLegacyFileType(fileName, fileContent);
|
|
13621
13780
|
if (fileType === "unknown") {
|
|
13622
13781
|
return { success: false, error: "Unknown file format" };
|
|
@@ -13626,15 +13785,7 @@ var Sphere = class _Sphere {
|
|
|
13626
13785
|
if (!_Sphere.validateMnemonic(mnemonic)) {
|
|
13627
13786
|
return { success: false, error: "Invalid mnemonic phrase" };
|
|
13628
13787
|
}
|
|
13629
|
-
const sphere = await _Sphere.import({
|
|
13630
|
-
mnemonic,
|
|
13631
|
-
storage: options.storage,
|
|
13632
|
-
transport: options.transport,
|
|
13633
|
-
oracle: options.oracle,
|
|
13634
|
-
tokenStorage: options.tokenStorage,
|
|
13635
|
-
nametag: options.nametag,
|
|
13636
|
-
l1: options.l1
|
|
13637
|
-
});
|
|
13788
|
+
const sphere = await _Sphere.import({ ...baseOptions, mnemonic });
|
|
13638
13789
|
return { success: true, sphere, mnemonic };
|
|
13639
13790
|
}
|
|
13640
13791
|
if (fileType === "dat") {
|
|
@@ -13654,16 +13805,11 @@ var Sphere = class _Sphere {
|
|
|
13654
13805
|
const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
|
|
13655
13806
|
const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13656
13807
|
const sphere = await _Sphere.import({
|
|
13808
|
+
...baseOptions,
|
|
13657
13809
|
masterKey,
|
|
13658
13810
|
chainCode,
|
|
13659
13811
|
basePath,
|
|
13660
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13661
|
-
storage: options.storage,
|
|
13662
|
-
transport: options.transport,
|
|
13663
|
-
oracle: options.oracle,
|
|
13664
|
-
tokenStorage: options.tokenStorage,
|
|
13665
|
-
nametag: options.nametag,
|
|
13666
|
-
l1: options.l1
|
|
13812
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13667
13813
|
});
|
|
13668
13814
|
return { success: true, sphere };
|
|
13669
13815
|
}
|
|
@@ -13686,16 +13832,11 @@ var Sphere = class _Sphere {
|
|
|
13686
13832
|
const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
|
|
13687
13833
|
const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13688
13834
|
const sphere = await _Sphere.import({
|
|
13835
|
+
...baseOptions,
|
|
13689
13836
|
masterKey,
|
|
13690
13837
|
chainCode,
|
|
13691
13838
|
basePath,
|
|
13692
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13693
|
-
storage: options.storage,
|
|
13694
|
-
transport: options.transport,
|
|
13695
|
-
oracle: options.oracle,
|
|
13696
|
-
tokenStorage: options.tokenStorage,
|
|
13697
|
-
nametag: options.nametag,
|
|
13698
|
-
l1: options.l1
|
|
13839
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13699
13840
|
});
|
|
13700
13841
|
return { success: true, sphere };
|
|
13701
13842
|
}
|
|
@@ -13709,13 +13850,9 @@ var Sphere = class _Sphere {
|
|
|
13709
13850
|
}
|
|
13710
13851
|
if (parsed.type === "sphere-wallet") {
|
|
13711
13852
|
const result = await _Sphere.importFromJSON({
|
|
13853
|
+
...baseOptions,
|
|
13712
13854
|
jsonContent: content,
|
|
13713
|
-
password
|
|
13714
|
-
storage: options.storage,
|
|
13715
|
-
transport: options.transport,
|
|
13716
|
-
oracle: options.oracle,
|
|
13717
|
-
tokenStorage: options.tokenStorage,
|
|
13718
|
-
l1: options.l1
|
|
13855
|
+
password
|
|
13719
13856
|
});
|
|
13720
13857
|
if (result.success) {
|
|
13721
13858
|
const sphere2 = _Sphere.getInstance();
|
|
@@ -13757,29 +13894,15 @@ var Sphere = class _Sphere {
|
|
|
13757
13894
|
const isBIP32 = derivationMode === "bip32" || !!chainCode;
|
|
13758
13895
|
const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
|
|
13759
13896
|
if (mnemonic) {
|
|
13760
|
-
const sphere2 = await _Sphere.import({
|
|
13761
|
-
mnemonic,
|
|
13762
|
-
basePath,
|
|
13763
|
-
storage: options.storage,
|
|
13764
|
-
transport: options.transport,
|
|
13765
|
-
oracle: options.oracle,
|
|
13766
|
-
tokenStorage: options.tokenStorage,
|
|
13767
|
-
nametag: options.nametag,
|
|
13768
|
-
l1: options.l1
|
|
13769
|
-
});
|
|
13897
|
+
const sphere2 = await _Sphere.import({ ...baseOptions, mnemonic, basePath });
|
|
13770
13898
|
return { success: true, sphere: sphere2, mnemonic };
|
|
13771
13899
|
}
|
|
13772
13900
|
const sphere = await _Sphere.import({
|
|
13901
|
+
...baseOptions,
|
|
13773
13902
|
masterKey,
|
|
13774
13903
|
chainCode,
|
|
13775
13904
|
basePath,
|
|
13776
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13777
|
-
storage: options.storage,
|
|
13778
|
-
transport: options.transport,
|
|
13779
|
-
oracle: options.oracle,
|
|
13780
|
-
tokenStorage: options.tokenStorage,
|
|
13781
|
-
nametag: options.nametag,
|
|
13782
|
-
l1: options.l1
|
|
13905
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13783
13906
|
});
|
|
13784
13907
|
return { success: true, sphere };
|
|
13785
13908
|
}
|
|
@@ -14027,6 +14150,23 @@ var Sphere = class _Sphere {
|
|
|
14027
14150
|
await provider.initialize();
|
|
14028
14151
|
}
|
|
14029
14152
|
await this.reinitializeModulesForNewAddress();
|
|
14153
|
+
this.emitEvent("identity:changed", {
|
|
14154
|
+
l1Address: this._identity.l1Address,
|
|
14155
|
+
directAddress: this._identity.directAddress,
|
|
14156
|
+
chainPubkey: this._identity.chainPubkey,
|
|
14157
|
+
nametag: this._identity.nametag,
|
|
14158
|
+
addressIndex: index
|
|
14159
|
+
});
|
|
14160
|
+
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14161
|
+
this.postSwitchSync(index, newNametag).catch((err) => {
|
|
14162
|
+
console.warn(`[Sphere] Post-switch sync failed for address ${index}:`, err);
|
|
14163
|
+
});
|
|
14164
|
+
}
|
|
14165
|
+
/**
|
|
14166
|
+
* Background transport sync and nametag operations after address switch.
|
|
14167
|
+
* Runs after switchToAddress returns so L1/L3 queries can start immediately.
|
|
14168
|
+
*/
|
|
14169
|
+
async postSwitchSync(index, newNametag) {
|
|
14030
14170
|
if (!newNametag) {
|
|
14031
14171
|
await this.syncIdentityWithTransport();
|
|
14032
14172
|
}
|
|
@@ -14049,7 +14189,7 @@ var Sphere = class _Sphere {
|
|
|
14049
14189
|
nametag: newNametag,
|
|
14050
14190
|
addressIndex: index
|
|
14051
14191
|
});
|
|
14052
|
-
} else if (this._identity
|
|
14192
|
+
} else if (this._identity?.nametag && !this._payments.hasNametag()) {
|
|
14053
14193
|
console.log(`[Sphere] Nametag @${this._identity.nametag} has no token after switch, minting...`);
|
|
14054
14194
|
try {
|
|
14055
14195
|
const result = await this.mintNametag(this._identity.nametag);
|
|
@@ -14062,14 +14202,6 @@ var Sphere = class _Sphere {
|
|
|
14062
14202
|
console.warn(`[Sphere] Nametag token mint failed after switch:`, err);
|
|
14063
14203
|
}
|
|
14064
14204
|
}
|
|
14065
|
-
this.emitEvent("identity:changed", {
|
|
14066
|
-
l1Address: this._identity.l1Address,
|
|
14067
|
-
directAddress: this._identity.directAddress,
|
|
14068
|
-
chainPubkey: this._identity.chainPubkey,
|
|
14069
|
-
nametag: this._identity.nametag,
|
|
14070
|
-
addressIndex: index
|
|
14071
|
-
});
|
|
14072
|
-
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14073
14205
|
}
|
|
14074
14206
|
/**
|
|
14075
14207
|
* Re-initialize modules after address switch
|
|
@@ -14276,6 +14408,98 @@ var Sphere = class _Sphere {
|
|
|
14276
14408
|
await this.persistTrackedAddresses();
|
|
14277
14409
|
await this.persistAddressNametags();
|
|
14278
14410
|
}
|
|
14411
|
+
/**
|
|
14412
|
+
* Discover previously used HD addresses.
|
|
14413
|
+
*
|
|
14414
|
+
* Primary: queries Nostr relay for identity binding events (fast, single batch query).
|
|
14415
|
+
* Secondary: runs L1 balance scan to find legacy addresses with no binding event.
|
|
14416
|
+
*
|
|
14417
|
+
* @example
|
|
14418
|
+
* ```ts
|
|
14419
|
+
* const result = await sphere.discoverAddresses();
|
|
14420
|
+
* console.log(`Found ${result.addresses.length} addresses`);
|
|
14421
|
+
*
|
|
14422
|
+
* // With auto-tracking
|
|
14423
|
+
* await sphere.discoverAddresses({ autoTrack: true });
|
|
14424
|
+
* ```
|
|
14425
|
+
*/
|
|
14426
|
+
async discoverAddresses(options = {}) {
|
|
14427
|
+
this.ensureReady();
|
|
14428
|
+
if (!this._masterKey) {
|
|
14429
|
+
throw new Error("Address discovery requires HD master key");
|
|
14430
|
+
}
|
|
14431
|
+
if (!this._transport.discoverAddresses) {
|
|
14432
|
+
throw new Error("Transport provider does not support address discovery");
|
|
14433
|
+
}
|
|
14434
|
+
const includeL1Scan = options.includeL1Scan ?? true;
|
|
14435
|
+
const transportResult = await discoverAddressesImpl(
|
|
14436
|
+
(index) => {
|
|
14437
|
+
const addrInfo = this._deriveAddressInternal(index, false);
|
|
14438
|
+
return {
|
|
14439
|
+
transportPubkey: addrInfo.publicKey.slice(2),
|
|
14440
|
+
// x-only 32 bytes
|
|
14441
|
+
chainPubkey: addrInfo.publicKey,
|
|
14442
|
+
l1Address: addrInfo.address,
|
|
14443
|
+
directAddress: ""
|
|
14444
|
+
// not needed for discovery query
|
|
14445
|
+
};
|
|
14446
|
+
},
|
|
14447
|
+
(pubkeys) => this._transport.discoverAddresses(pubkeys),
|
|
14448
|
+
options
|
|
14449
|
+
);
|
|
14450
|
+
if (includeL1Scan) {
|
|
14451
|
+
try {
|
|
14452
|
+
const l1Result = await this.scanAddresses({
|
|
14453
|
+
maxAddresses: options.maxAddresses,
|
|
14454
|
+
gapLimit: options.gapLimit,
|
|
14455
|
+
signal: options.signal,
|
|
14456
|
+
onProgress: options.onProgress ? (p) => options.onProgress({
|
|
14457
|
+
currentBatch: 0,
|
|
14458
|
+
totalBatches: 0,
|
|
14459
|
+
discoveredCount: p.foundCount,
|
|
14460
|
+
currentGap: p.currentGap,
|
|
14461
|
+
phase: "l1"
|
|
14462
|
+
}) : void 0
|
|
14463
|
+
});
|
|
14464
|
+
for (const l1Addr of l1Result.addresses) {
|
|
14465
|
+
if (l1Addr.isChange) continue;
|
|
14466
|
+
const existing = transportResult.addresses.find((a) => a.index === l1Addr.index);
|
|
14467
|
+
if (existing) {
|
|
14468
|
+
existing.l1Balance = l1Addr.balance;
|
|
14469
|
+
existing.source = "both";
|
|
14470
|
+
if (!existing.nametag && l1Addr.nametag) {
|
|
14471
|
+
existing.nametag = l1Addr.nametag;
|
|
14472
|
+
}
|
|
14473
|
+
} else {
|
|
14474
|
+
const addrInfo = this._deriveAddressInternal(l1Addr.index, false);
|
|
14475
|
+
transportResult.addresses.push({
|
|
14476
|
+
index: l1Addr.index,
|
|
14477
|
+
l1Address: l1Addr.address,
|
|
14478
|
+
directAddress: "",
|
|
14479
|
+
chainPubkey: addrInfo.publicKey,
|
|
14480
|
+
nametag: l1Addr.nametag,
|
|
14481
|
+
l1Balance: l1Addr.balance,
|
|
14482
|
+
source: "l1"
|
|
14483
|
+
});
|
|
14484
|
+
}
|
|
14485
|
+
}
|
|
14486
|
+
transportResult.addresses.sort((a, b) => a.index - b.index);
|
|
14487
|
+
} catch (err) {
|
|
14488
|
+
console.warn("[Sphere] L1 scan failed during discovery (non-fatal):", err);
|
|
14489
|
+
}
|
|
14490
|
+
}
|
|
14491
|
+
if (options.autoTrack && transportResult.addresses.length > 0) {
|
|
14492
|
+
await this.trackScannedAddresses(
|
|
14493
|
+
transportResult.addresses.map((a) => ({
|
|
14494
|
+
index: a.index,
|
|
14495
|
+
// Preserve existing hidden state; default to false for newly discovered
|
|
14496
|
+
hidden: this._trackedAddresses.get(a.index)?.hidden ?? false,
|
|
14497
|
+
nametag: a.nametag
|
|
14498
|
+
}))
|
|
14499
|
+
);
|
|
14500
|
+
}
|
|
14501
|
+
return transportResult;
|
|
14502
|
+
}
|
|
14279
14503
|
// ===========================================================================
|
|
14280
14504
|
// Public Methods - Status
|
|
14281
14505
|
// ===========================================================================
|
|
@@ -14847,6 +15071,17 @@ var Sphere = class _Sphere {
|
|
|
14847
15071
|
return;
|
|
14848
15072
|
}
|
|
14849
15073
|
}
|
|
15074
|
+
const needsUpdate = !existing.directAddress || !existing.l1Address || !existing.chainPubkey || this._identity?.nametag && !existing.nametag;
|
|
15075
|
+
if (needsUpdate) {
|
|
15076
|
+
console.log("[Sphere] Existing binding incomplete, re-publishing with full data");
|
|
15077
|
+
await this._transport.publishIdentityBinding(
|
|
15078
|
+
this._identity.chainPubkey,
|
|
15079
|
+
this._identity.l1Address,
|
|
15080
|
+
this._identity.directAddress || "",
|
|
15081
|
+
this._identity?.nametag || existing.nametag || void 0
|
|
15082
|
+
);
|
|
15083
|
+
return;
|
|
15084
|
+
}
|
|
14850
15085
|
console.log("[Sphere] Existing binding found, skipping re-publish");
|
|
14851
15086
|
return;
|
|
14852
15087
|
}
|
|
@@ -15335,6 +15570,7 @@ function formatAmount(amount, options = {}) {
|
|
|
15335
15570
|
init_bech32();
|
|
15336
15571
|
|
|
15337
15572
|
// core/network-health.ts
|
|
15573
|
+
init_constants();
|
|
15338
15574
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
15339
15575
|
async function checkNetworkHealth(network = "testnet", options) {
|
|
15340
15576
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -15520,6 +15756,9 @@ async function runCustomCheck(name, checkFn, timeoutMs) {
|
|
|
15520
15756
|
}
|
|
15521
15757
|
}
|
|
15522
15758
|
|
|
15759
|
+
// index.ts
|
|
15760
|
+
init_constants();
|
|
15761
|
+
|
|
15523
15762
|
// types/payment-session.ts
|
|
15524
15763
|
function createPaymentSession(params) {
|
|
15525
15764
|
const now = Date.now();
|
|
@@ -15591,6 +15830,9 @@ var SphereError = class extends Error {
|
|
|
15591
15830
|
}
|
|
15592
15831
|
};
|
|
15593
15832
|
|
|
15833
|
+
// index.ts
|
|
15834
|
+
init_constants();
|
|
15835
|
+
|
|
15594
15836
|
// validation/token-validator.ts
|
|
15595
15837
|
var TokenValidator = class {
|
|
15596
15838
|
aggregatorClient = null;
|
|
@@ -15924,6 +16166,7 @@ import {
|
|
|
15924
16166
|
} from "@unicitylabs/nostr-js-sdk";
|
|
15925
16167
|
|
|
15926
16168
|
// price/CoinGeckoPriceProvider.ts
|
|
16169
|
+
init_constants();
|
|
15927
16170
|
var CoinGeckoPriceProvider = class {
|
|
15928
16171
|
platform = "coingecko";
|
|
15929
16172
|
cache = /* @__PURE__ */ new Map();
|