@unicitylabs/sphere-sdk 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +443 -177
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +163 -4
- package/dist/core/index.d.ts +163 -4
- package/dist/core/index.js +442 -177
- 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 +499 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -6
- package/dist/index.d.ts +147 -6
- package/dist/index.js +499 -228
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +70 -1
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +70 -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;
|
|
@@ -424,13 +646,16 @@ function disconnect() {
|
|
|
424
646
|
if (cb.timeoutId) clearTimeout(cb.timeoutId);
|
|
425
647
|
});
|
|
426
648
|
connectionCallbacks.length = 0;
|
|
649
|
+
blockSubscribers.length = 0;
|
|
650
|
+
lastBlockHeader = null;
|
|
427
651
|
}
|
|
428
652
|
var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT;
|
|
429
653
|
var init_network = __esm({
|
|
430
654
|
"l1/network.ts"() {
|
|
431
655
|
"use strict";
|
|
432
656
|
init_addressToScriptHash();
|
|
433
|
-
|
|
657
|
+
init_constants();
|
|
658
|
+
DEFAULT_ENDPOINT = DEFAULT_ELECTRUM_URL;
|
|
434
659
|
ws = null;
|
|
435
660
|
isConnected = false;
|
|
436
661
|
isConnecting = false;
|
|
@@ -450,6 +675,9 @@ var init_network = __esm({
|
|
|
450
675
|
}
|
|
451
676
|
});
|
|
452
677
|
|
|
678
|
+
// modules/payments/L1PaymentsModule.ts
|
|
679
|
+
init_constants();
|
|
680
|
+
|
|
453
681
|
// l1/index.ts
|
|
454
682
|
var l1_exports = {};
|
|
455
683
|
__export(l1_exports, {
|
|
@@ -1635,7 +1863,7 @@ var L1PaymentsModule = class {
|
|
|
1635
1863
|
_transport;
|
|
1636
1864
|
constructor(config) {
|
|
1637
1865
|
this._config = {
|
|
1638
|
-
electrumUrl: config?.electrumUrl ??
|
|
1866
|
+
electrumUrl: config?.electrumUrl ?? DEFAULT_ELECTRUM_URL,
|
|
1639
1867
|
network: config?.network ?? "mainnet",
|
|
1640
1868
|
defaultFeeRate: config?.defaultFeeRate ?? 10,
|
|
1641
1869
|
enableVesting: config?.enableVesting ?? true
|
|
@@ -2475,221 +2703,8 @@ var NametagMinter = class {
|
|
|
2475
2703
|
}
|
|
2476
2704
|
};
|
|
2477
2705
|
|
|
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
|
-
};
|
|
2706
|
+
// modules/payments/PaymentsModule.ts
|
|
2707
|
+
init_constants();
|
|
2693
2708
|
|
|
2694
2709
|
// types/txf.ts
|
|
2695
2710
|
var ARCHIVED_PREFIX = "archived-";
|
|
@@ -2734,6 +2749,7 @@ function isValidTokenId(tokenId) {
|
|
|
2734
2749
|
}
|
|
2735
2750
|
|
|
2736
2751
|
// registry/TokenRegistry.ts
|
|
2752
|
+
init_constants();
|
|
2737
2753
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
2738
2754
|
var TokenRegistry = class _TokenRegistry {
|
|
2739
2755
|
static instance = null;
|
|
@@ -7631,6 +7647,7 @@ import { HashAlgorithm as HashAlgorithm6 } from "@unicitylabs/state-transition-s
|
|
|
7631
7647
|
import { UnmaskedPredicate as UnmaskedPredicate6 } from "@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate";
|
|
7632
7648
|
|
|
7633
7649
|
// modules/communications/CommunicationsModule.ts
|
|
7650
|
+
init_constants();
|
|
7634
7651
|
var CommunicationsModule = class {
|
|
7635
7652
|
config;
|
|
7636
7653
|
deps = null;
|
|
@@ -8105,6 +8122,7 @@ function createCommunicationsModule(config) {
|
|
|
8105
8122
|
}
|
|
8106
8123
|
|
|
8107
8124
|
// modules/groupchat/GroupChatModule.ts
|
|
8125
|
+
init_constants();
|
|
8108
8126
|
import {
|
|
8109
8127
|
NostrClient,
|
|
8110
8128
|
NostrKeyManager,
|
|
@@ -11954,6 +11972,9 @@ function createMarketModule(config) {
|
|
|
11954
11972
|
return new MarketModule(config);
|
|
11955
11973
|
}
|
|
11956
11974
|
|
|
11975
|
+
// core/Sphere.ts
|
|
11976
|
+
init_constants();
|
|
11977
|
+
|
|
11957
11978
|
// core/encryption.ts
|
|
11958
11979
|
import CryptoJS6 from "crypto-js";
|
|
11959
11980
|
function encryptSimple(plaintext, password) {
|
|
@@ -12057,6 +12078,72 @@ async function scanAddressesImpl(deriveAddress, options = {}) {
|
|
|
12057
12078
|
};
|
|
12058
12079
|
}
|
|
12059
12080
|
|
|
12081
|
+
// core/discover.ts
|
|
12082
|
+
async function discoverAddressesImpl(deriveTransportPubkey, batchResolve, options = {}) {
|
|
12083
|
+
const maxAddresses = options.maxAddresses ?? 50;
|
|
12084
|
+
const gapLimit = options.gapLimit ?? 20;
|
|
12085
|
+
const batchSize = options.batchSize ?? 20;
|
|
12086
|
+
const { onProgress, signal } = options;
|
|
12087
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
12088
|
+
let consecutiveEmpty = 0;
|
|
12089
|
+
let scanned = 0;
|
|
12090
|
+
const totalBatches = Math.ceil(maxAddresses / batchSize);
|
|
12091
|
+
for (let batchStart = 0; batchStart < maxAddresses; batchStart += batchSize) {
|
|
12092
|
+
if (signal?.aborted) break;
|
|
12093
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12094
|
+
const batchEnd = Math.min(batchStart + batchSize, maxAddresses);
|
|
12095
|
+
const batchIndices = [];
|
|
12096
|
+
const pubkeyToIndex = /* @__PURE__ */ new Map();
|
|
12097
|
+
const pubkeyToInfo = /* @__PURE__ */ new Map();
|
|
12098
|
+
for (let i = batchStart; i < batchEnd; i++) {
|
|
12099
|
+
const info = deriveTransportPubkey(i);
|
|
12100
|
+
batchIndices.push(i);
|
|
12101
|
+
pubkeyToIndex.set(info.transportPubkey, i);
|
|
12102
|
+
pubkeyToInfo.set(info.transportPubkey, info);
|
|
12103
|
+
}
|
|
12104
|
+
const batchPubkeys = Array.from(pubkeyToIndex.keys());
|
|
12105
|
+
onProgress?.({
|
|
12106
|
+
currentBatch: Math.floor(batchStart / batchSize) + 1,
|
|
12107
|
+
totalBatches,
|
|
12108
|
+
discoveredCount: discovered.size,
|
|
12109
|
+
currentGap: consecutiveEmpty,
|
|
12110
|
+
phase: "transport"
|
|
12111
|
+
});
|
|
12112
|
+
const peerInfos = await batchResolve(batchPubkeys);
|
|
12113
|
+
const foundInBatch = /* @__PURE__ */ new Set();
|
|
12114
|
+
for (const peer of peerInfos) {
|
|
12115
|
+
const index = pubkeyToIndex.get(peer.transportPubkey);
|
|
12116
|
+
if (index !== void 0) {
|
|
12117
|
+
foundInBatch.add(index);
|
|
12118
|
+
const derived = pubkeyToInfo.get(peer.transportPubkey);
|
|
12119
|
+
discovered.set(index, {
|
|
12120
|
+
index,
|
|
12121
|
+
l1Address: peer.l1Address || derived.l1Address,
|
|
12122
|
+
directAddress: peer.directAddress || derived.directAddress,
|
|
12123
|
+
chainPubkey: peer.chainPubkey || derived.chainPubkey,
|
|
12124
|
+
nametag: peer.nametag,
|
|
12125
|
+
l1Balance: 0,
|
|
12126
|
+
source: "transport"
|
|
12127
|
+
});
|
|
12128
|
+
}
|
|
12129
|
+
}
|
|
12130
|
+
for (const idx of batchIndices) {
|
|
12131
|
+
scanned++;
|
|
12132
|
+
if (foundInBatch.has(idx)) {
|
|
12133
|
+
consecutiveEmpty = 0;
|
|
12134
|
+
} else {
|
|
12135
|
+
consecutiveEmpty++;
|
|
12136
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12137
|
+
}
|
|
12138
|
+
}
|
|
12139
|
+
}
|
|
12140
|
+
return {
|
|
12141
|
+
addresses: Array.from(discovered.values()).sort((a, b) => a.index - b.index),
|
|
12142
|
+
scannedCount: scanned,
|
|
12143
|
+
aborted: signal?.aborted ?? false
|
|
12144
|
+
};
|
|
12145
|
+
}
|
|
12146
|
+
|
|
12060
12147
|
// core/Sphere.ts
|
|
12061
12148
|
init_network();
|
|
12062
12149
|
|
|
@@ -12879,7 +12966,9 @@ var Sphere = class _Sphere {
|
|
|
12879
12966
|
price: options.price,
|
|
12880
12967
|
groupChat,
|
|
12881
12968
|
market,
|
|
12882
|
-
password: options.password
|
|
12969
|
+
password: options.password,
|
|
12970
|
+
discoverAddresses: options.discoverAddresses,
|
|
12971
|
+
onProgress: options.onProgress
|
|
12883
12972
|
});
|
|
12884
12973
|
return { sphere: sphere2, created: false };
|
|
12885
12974
|
}
|
|
@@ -12907,7 +12996,9 @@ var Sphere = class _Sphere {
|
|
|
12907
12996
|
price: options.price,
|
|
12908
12997
|
groupChat,
|
|
12909
12998
|
market,
|
|
12910
|
-
password: options.password
|
|
12999
|
+
password: options.password,
|
|
13000
|
+
discoverAddresses: options.discoverAddresses,
|
|
13001
|
+
onProgress: options.onProgress
|
|
12911
13002
|
});
|
|
12912
13003
|
return { sphere, created: true, generatedMnemonic };
|
|
12913
13004
|
}
|
|
@@ -12968,6 +13059,7 @@ var Sphere = class _Sphere {
|
|
|
12968
13059
|
if (await _Sphere.exists(options.storage)) {
|
|
12969
13060
|
throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
|
|
12970
13061
|
}
|
|
13062
|
+
const progress = options.onProgress;
|
|
12971
13063
|
if (!options.storage.isConnected()) {
|
|
12972
13064
|
await options.storage.connect();
|
|
12973
13065
|
}
|
|
@@ -12985,20 +13077,39 @@ var Sphere = class _Sphere {
|
|
|
12985
13077
|
marketConfig
|
|
12986
13078
|
);
|
|
12987
13079
|
sphere._password = options.password ?? null;
|
|
13080
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
12988
13081
|
await sphere.storeMnemonic(options.mnemonic, options.derivationPath);
|
|
12989
13082
|
await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
|
|
13083
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
12990
13084
|
await sphere.initializeProviders();
|
|
12991
13085
|
await sphere.initializeModules();
|
|
13086
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
12992
13087
|
await sphere.finalizeWalletCreation();
|
|
12993
13088
|
sphere._initialized = true;
|
|
12994
13089
|
_Sphere.instance = sphere;
|
|
12995
13090
|
await sphere.ensureAddressTracked(0);
|
|
12996
13091
|
if (options.nametag) {
|
|
13092
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
12997
13093
|
await sphere.registerNametag(options.nametag);
|
|
12998
13094
|
} else {
|
|
13095
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
12999
13096
|
await sphere.recoverNametagFromTransport();
|
|
13097
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13000
13098
|
await sphere.syncIdentityWithTransport();
|
|
13001
13099
|
}
|
|
13100
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13101
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13102
|
+
try {
|
|
13103
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13104
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13105
|
+
if (result.addresses.length > 0) {
|
|
13106
|
+
console.log(`[Sphere.create] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13107
|
+
}
|
|
13108
|
+
} catch (err) {
|
|
13109
|
+
console.warn("[Sphere.create] Address discovery failed (non-fatal):", err);
|
|
13110
|
+
}
|
|
13111
|
+
}
|
|
13112
|
+
progress?.({ step: "complete", message: "Wallet created" });
|
|
13002
13113
|
return sphere;
|
|
13003
13114
|
}
|
|
13004
13115
|
/**
|
|
@@ -13008,6 +13119,7 @@ var Sphere = class _Sphere {
|
|
|
13008
13119
|
if (!await _Sphere.exists(options.storage)) {
|
|
13009
13120
|
throw new Error("No wallet found. Use Sphere.create() to create a new wallet.");
|
|
13010
13121
|
}
|
|
13122
|
+
const progress = options.onProgress;
|
|
13011
13123
|
_Sphere.configureTokenRegistry(options.storage, options.network);
|
|
13012
13124
|
const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
|
|
13013
13125
|
const marketConfig = _Sphere.resolveMarketConfig(options.market);
|
|
@@ -13025,13 +13137,17 @@ var Sphere = class _Sphere {
|
|
|
13025
13137
|
if (!options.storage.isConnected()) {
|
|
13026
13138
|
await options.storage.connect();
|
|
13027
13139
|
}
|
|
13140
|
+
progress?.({ step: "storing_keys", message: "Loading wallet keys..." });
|
|
13028
13141
|
await sphere.loadIdentityFromStorage();
|
|
13142
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13029
13143
|
await sphere.initializeProviders();
|
|
13030
13144
|
await sphere.initializeModules();
|
|
13145
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13031
13146
|
await sphere.syncIdentityWithTransport();
|
|
13032
13147
|
sphere._initialized = true;
|
|
13033
13148
|
_Sphere.instance = sphere;
|
|
13034
13149
|
if (sphere._identity?.nametag && !sphere._payments.hasNametag()) {
|
|
13150
|
+
progress?.({ step: "registering_nametag", message: "Restoring nametag token..." });
|
|
13035
13151
|
console.log(`[Sphere] Nametag @${sphere._identity.nametag} has no token, attempting to mint...`);
|
|
13036
13152
|
try {
|
|
13037
13153
|
const result = await sphere.mintNametag(sphere._identity.nametag);
|
|
@@ -13044,6 +13160,19 @@ var Sphere = class _Sphere {
|
|
|
13044
13160
|
console.warn(`[Sphere] Nametag token mint failed:`, err);
|
|
13045
13161
|
}
|
|
13046
13162
|
}
|
|
13163
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses && sphere._masterKey) {
|
|
13164
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13165
|
+
try {
|
|
13166
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13167
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13168
|
+
if (result.addresses.length > 0) {
|
|
13169
|
+
console.log(`[Sphere.load] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13170
|
+
}
|
|
13171
|
+
} catch (err) {
|
|
13172
|
+
console.warn("[Sphere.load] Address discovery failed (non-fatal):", err);
|
|
13173
|
+
}
|
|
13174
|
+
}
|
|
13175
|
+
progress?.({ step: "complete", message: "Wallet loaded" });
|
|
13047
13176
|
return sphere;
|
|
13048
13177
|
}
|
|
13049
13178
|
/**
|
|
@@ -13053,9 +13182,11 @@ var Sphere = class _Sphere {
|
|
|
13053
13182
|
if (!options.mnemonic && !options.masterKey) {
|
|
13054
13183
|
throw new Error("Either mnemonic or masterKey is required");
|
|
13055
13184
|
}
|
|
13185
|
+
const progress = options.onProgress;
|
|
13056
13186
|
console.log("[Sphere.import] Starting import...");
|
|
13057
13187
|
const needsClear = _Sphere.instance !== null || await _Sphere.exists(options.storage);
|
|
13058
13188
|
if (needsClear) {
|
|
13189
|
+
progress?.({ step: "clearing", message: "Clearing previous wallet data..." });
|
|
13059
13190
|
console.log("[Sphere.import] Clearing existing wallet data...");
|
|
13060
13191
|
await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
|
|
13061
13192
|
console.log("[Sphere.import] Clear done");
|
|
@@ -13080,6 +13211,7 @@ var Sphere = class _Sphere {
|
|
|
13080
13211
|
marketConfig
|
|
13081
13212
|
);
|
|
13082
13213
|
sphere._password = options.password ?? null;
|
|
13214
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
13083
13215
|
if (options.mnemonic) {
|
|
13084
13216
|
if (!_Sphere.validateMnemonic(options.mnemonic)) {
|
|
13085
13217
|
throw new Error("Invalid mnemonic");
|
|
@@ -13104,17 +13236,21 @@ var Sphere = class _Sphere {
|
|
|
13104
13236
|
options.derivationPath
|
|
13105
13237
|
);
|
|
13106
13238
|
}
|
|
13239
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13107
13240
|
console.log("[Sphere.import] Initializing providers...");
|
|
13108
13241
|
await sphere.initializeProviders();
|
|
13109
13242
|
console.log("[Sphere.import] Providers initialized. Initializing modules...");
|
|
13110
13243
|
await sphere.initializeModules();
|
|
13111
13244
|
console.log("[Sphere.import] Modules initialized");
|
|
13112
13245
|
if (!options.nametag) {
|
|
13246
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
13113
13247
|
console.log("[Sphere.import] Recovering nametag from transport...");
|
|
13114
13248
|
await sphere.recoverNametagFromTransport();
|
|
13115
13249
|
console.log("[Sphere.import] Nametag recovery done");
|
|
13250
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13116
13251
|
await sphere.syncIdentityWithTransport();
|
|
13117
13252
|
}
|
|
13253
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
13118
13254
|
console.log("[Sphere.import] Finalizing wallet creation...");
|
|
13119
13255
|
await sphere.finalizeWalletCreation();
|
|
13120
13256
|
sphere._initialized = true;
|
|
@@ -13122,10 +13258,12 @@ var Sphere = class _Sphere {
|
|
|
13122
13258
|
console.log("[Sphere.import] Tracking address 0...");
|
|
13123
13259
|
await sphere.ensureAddressTracked(0);
|
|
13124
13260
|
if (options.nametag) {
|
|
13261
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
13125
13262
|
console.log("[Sphere.import] Registering nametag...");
|
|
13126
13263
|
await sphere.registerNametag(options.nametag);
|
|
13127
13264
|
}
|
|
13128
13265
|
if (sphere._tokenStorageProviders.size > 0) {
|
|
13266
|
+
progress?.({ step: "syncing_tokens", message: "Syncing tokens..." });
|
|
13129
13267
|
try {
|
|
13130
13268
|
const syncResult = await sphere._payments.sync();
|
|
13131
13269
|
console.log(`[Sphere.import] Auto-sync: +${syncResult.added} -${syncResult.removed}`);
|
|
@@ -13133,6 +13271,19 @@ var Sphere = class _Sphere {
|
|
|
13133
13271
|
console.warn("[Sphere.import] Auto-sync failed (non-fatal):", err);
|
|
13134
13272
|
}
|
|
13135
13273
|
}
|
|
13274
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13275
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13276
|
+
try {
|
|
13277
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13278
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13279
|
+
if (result.addresses.length > 0) {
|
|
13280
|
+
console.log(`[Sphere.import] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13281
|
+
}
|
|
13282
|
+
} catch (err) {
|
|
13283
|
+
console.warn("[Sphere.import] Address discovery failed (non-fatal):", err);
|
|
13284
|
+
}
|
|
13285
|
+
}
|
|
13286
|
+
progress?.({ step: "complete", message: "Import complete" });
|
|
13136
13287
|
console.log("[Sphere.import] Import complete");
|
|
13137
13288
|
return sphere;
|
|
13138
13289
|
}
|
|
@@ -14001,6 +14152,23 @@ var Sphere = class _Sphere {
|
|
|
14001
14152
|
await provider.initialize();
|
|
14002
14153
|
}
|
|
14003
14154
|
await this.reinitializeModulesForNewAddress();
|
|
14155
|
+
this.emitEvent("identity:changed", {
|
|
14156
|
+
l1Address: this._identity.l1Address,
|
|
14157
|
+
directAddress: this._identity.directAddress,
|
|
14158
|
+
chainPubkey: this._identity.chainPubkey,
|
|
14159
|
+
nametag: this._identity.nametag,
|
|
14160
|
+
addressIndex: index
|
|
14161
|
+
});
|
|
14162
|
+
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14163
|
+
this.postSwitchSync(index, newNametag).catch((err) => {
|
|
14164
|
+
console.warn(`[Sphere] Post-switch sync failed for address ${index}:`, err);
|
|
14165
|
+
});
|
|
14166
|
+
}
|
|
14167
|
+
/**
|
|
14168
|
+
* Background transport sync and nametag operations after address switch.
|
|
14169
|
+
* Runs after switchToAddress returns so L1/L3 queries can start immediately.
|
|
14170
|
+
*/
|
|
14171
|
+
async postSwitchSync(index, newNametag) {
|
|
14004
14172
|
if (!newNametag) {
|
|
14005
14173
|
await this.syncIdentityWithTransport();
|
|
14006
14174
|
}
|
|
@@ -14023,7 +14191,7 @@ var Sphere = class _Sphere {
|
|
|
14023
14191
|
nametag: newNametag,
|
|
14024
14192
|
addressIndex: index
|
|
14025
14193
|
});
|
|
14026
|
-
} else if (this._identity
|
|
14194
|
+
} else if (this._identity?.nametag && !this._payments.hasNametag()) {
|
|
14027
14195
|
console.log(`[Sphere] Nametag @${this._identity.nametag} has no token after switch, minting...`);
|
|
14028
14196
|
try {
|
|
14029
14197
|
const result = await this.mintNametag(this._identity.nametag);
|
|
@@ -14036,14 +14204,6 @@ var Sphere = class _Sphere {
|
|
|
14036
14204
|
console.warn(`[Sphere] Nametag token mint failed after switch:`, err);
|
|
14037
14205
|
}
|
|
14038
14206
|
}
|
|
14039
|
-
this.emitEvent("identity:changed", {
|
|
14040
|
-
l1Address: this._identity.l1Address,
|
|
14041
|
-
directAddress: this._identity.directAddress,
|
|
14042
|
-
chainPubkey: this._identity.chainPubkey,
|
|
14043
|
-
nametag: this._identity.nametag,
|
|
14044
|
-
addressIndex: index
|
|
14045
|
-
});
|
|
14046
|
-
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14047
14207
|
}
|
|
14048
14208
|
/**
|
|
14049
14209
|
* Re-initialize modules after address switch
|
|
@@ -14250,6 +14410,98 @@ var Sphere = class _Sphere {
|
|
|
14250
14410
|
await this.persistTrackedAddresses();
|
|
14251
14411
|
await this.persistAddressNametags();
|
|
14252
14412
|
}
|
|
14413
|
+
/**
|
|
14414
|
+
* Discover previously used HD addresses.
|
|
14415
|
+
*
|
|
14416
|
+
* Primary: queries Nostr relay for identity binding events (fast, single batch query).
|
|
14417
|
+
* Secondary: runs L1 balance scan to find legacy addresses with no binding event.
|
|
14418
|
+
*
|
|
14419
|
+
* @example
|
|
14420
|
+
* ```ts
|
|
14421
|
+
* const result = await sphere.discoverAddresses();
|
|
14422
|
+
* console.log(`Found ${result.addresses.length} addresses`);
|
|
14423
|
+
*
|
|
14424
|
+
* // With auto-tracking
|
|
14425
|
+
* await sphere.discoverAddresses({ autoTrack: true });
|
|
14426
|
+
* ```
|
|
14427
|
+
*/
|
|
14428
|
+
async discoverAddresses(options = {}) {
|
|
14429
|
+
this.ensureReady();
|
|
14430
|
+
if (!this._masterKey) {
|
|
14431
|
+
throw new Error("Address discovery requires HD master key");
|
|
14432
|
+
}
|
|
14433
|
+
if (!this._transport.discoverAddresses) {
|
|
14434
|
+
throw new Error("Transport provider does not support address discovery");
|
|
14435
|
+
}
|
|
14436
|
+
const includeL1Scan = options.includeL1Scan ?? true;
|
|
14437
|
+
const transportResult = await discoverAddressesImpl(
|
|
14438
|
+
(index) => {
|
|
14439
|
+
const addrInfo = this._deriveAddressInternal(index, false);
|
|
14440
|
+
return {
|
|
14441
|
+
transportPubkey: addrInfo.publicKey.slice(2),
|
|
14442
|
+
// x-only 32 bytes
|
|
14443
|
+
chainPubkey: addrInfo.publicKey,
|
|
14444
|
+
l1Address: addrInfo.address,
|
|
14445
|
+
directAddress: ""
|
|
14446
|
+
// not needed for discovery query
|
|
14447
|
+
};
|
|
14448
|
+
},
|
|
14449
|
+
(pubkeys) => this._transport.discoverAddresses(pubkeys),
|
|
14450
|
+
options
|
|
14451
|
+
);
|
|
14452
|
+
if (includeL1Scan) {
|
|
14453
|
+
try {
|
|
14454
|
+
const l1Result = await this.scanAddresses({
|
|
14455
|
+
maxAddresses: options.maxAddresses,
|
|
14456
|
+
gapLimit: options.gapLimit,
|
|
14457
|
+
signal: options.signal,
|
|
14458
|
+
onProgress: options.onProgress ? (p) => options.onProgress({
|
|
14459
|
+
currentBatch: 0,
|
|
14460
|
+
totalBatches: 0,
|
|
14461
|
+
discoveredCount: p.foundCount,
|
|
14462
|
+
currentGap: p.currentGap,
|
|
14463
|
+
phase: "l1"
|
|
14464
|
+
}) : void 0
|
|
14465
|
+
});
|
|
14466
|
+
for (const l1Addr of l1Result.addresses) {
|
|
14467
|
+
if (l1Addr.isChange) continue;
|
|
14468
|
+
const existing = transportResult.addresses.find((a) => a.index === l1Addr.index);
|
|
14469
|
+
if (existing) {
|
|
14470
|
+
existing.l1Balance = l1Addr.balance;
|
|
14471
|
+
existing.source = "both";
|
|
14472
|
+
if (!existing.nametag && l1Addr.nametag) {
|
|
14473
|
+
existing.nametag = l1Addr.nametag;
|
|
14474
|
+
}
|
|
14475
|
+
} else {
|
|
14476
|
+
const addrInfo = this._deriveAddressInternal(l1Addr.index, false);
|
|
14477
|
+
transportResult.addresses.push({
|
|
14478
|
+
index: l1Addr.index,
|
|
14479
|
+
l1Address: l1Addr.address,
|
|
14480
|
+
directAddress: "",
|
|
14481
|
+
chainPubkey: addrInfo.publicKey,
|
|
14482
|
+
nametag: l1Addr.nametag,
|
|
14483
|
+
l1Balance: l1Addr.balance,
|
|
14484
|
+
source: "l1"
|
|
14485
|
+
});
|
|
14486
|
+
}
|
|
14487
|
+
}
|
|
14488
|
+
transportResult.addresses.sort((a, b) => a.index - b.index);
|
|
14489
|
+
} catch (err) {
|
|
14490
|
+
console.warn("[Sphere] L1 scan failed during discovery (non-fatal):", err);
|
|
14491
|
+
}
|
|
14492
|
+
}
|
|
14493
|
+
if (options.autoTrack && transportResult.addresses.length > 0) {
|
|
14494
|
+
await this.trackScannedAddresses(
|
|
14495
|
+
transportResult.addresses.map((a) => ({
|
|
14496
|
+
index: a.index,
|
|
14497
|
+
// Preserve existing hidden state; default to false for newly discovered
|
|
14498
|
+
hidden: this._trackedAddresses.get(a.index)?.hidden ?? false,
|
|
14499
|
+
nametag: a.nametag
|
|
14500
|
+
}))
|
|
14501
|
+
);
|
|
14502
|
+
}
|
|
14503
|
+
return transportResult;
|
|
14504
|
+
}
|
|
14253
14505
|
// ===========================================================================
|
|
14254
14506
|
// Public Methods - Status
|
|
14255
14507
|
// ===========================================================================
|
|
@@ -14821,6 +15073,17 @@ var Sphere = class _Sphere {
|
|
|
14821
15073
|
return;
|
|
14822
15074
|
}
|
|
14823
15075
|
}
|
|
15076
|
+
const needsUpdate = !existing.directAddress || !existing.l1Address || !existing.chainPubkey || this._identity?.nametag && !existing.nametag;
|
|
15077
|
+
if (needsUpdate) {
|
|
15078
|
+
console.log("[Sphere] Existing binding incomplete, re-publishing with full data");
|
|
15079
|
+
await this._transport.publishIdentityBinding(
|
|
15080
|
+
this._identity.chainPubkey,
|
|
15081
|
+
this._identity.l1Address,
|
|
15082
|
+
this._identity.directAddress || "",
|
|
15083
|
+
this._identity?.nametag || existing.nametag || void 0
|
|
15084
|
+
);
|
|
15085
|
+
return;
|
|
15086
|
+
}
|
|
14824
15087
|
console.log("[Sphere] Existing binding found, skipping re-publish");
|
|
14825
15088
|
return;
|
|
14826
15089
|
}
|
|
@@ -15309,6 +15572,7 @@ function formatAmount(amount, options = {}) {
|
|
|
15309
15572
|
init_bech32();
|
|
15310
15573
|
|
|
15311
15574
|
// core/network-health.ts
|
|
15575
|
+
init_constants();
|
|
15312
15576
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
15313
15577
|
async function checkNetworkHealth(network = "testnet", options) {
|
|
15314
15578
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -15494,6 +15758,9 @@ async function runCustomCheck(name, checkFn, timeoutMs) {
|
|
|
15494
15758
|
}
|
|
15495
15759
|
}
|
|
15496
15760
|
|
|
15761
|
+
// index.ts
|
|
15762
|
+
init_constants();
|
|
15763
|
+
|
|
15497
15764
|
// types/payment-session.ts
|
|
15498
15765
|
function createPaymentSession(params) {
|
|
15499
15766
|
const now = Date.now();
|
|
@@ -15565,6 +15832,9 @@ var SphereError = class extends Error {
|
|
|
15565
15832
|
}
|
|
15566
15833
|
};
|
|
15567
15834
|
|
|
15835
|
+
// index.ts
|
|
15836
|
+
init_constants();
|
|
15837
|
+
|
|
15568
15838
|
// validation/token-validator.ts
|
|
15569
15839
|
var TokenValidator = class {
|
|
15570
15840
|
aggregatorClient = null;
|
|
@@ -15898,6 +16168,7 @@ import {
|
|
|
15898
16168
|
} from "@unicitylabs/nostr-js-sdk";
|
|
15899
16169
|
|
|
15900
16170
|
// price/CoinGeckoPriceProvider.ts
|
|
16171
|
+
init_constants();
|
|
15901
16172
|
var CoinGeckoPriceProvider = class {
|
|
15902
16173
|
platform = "coingecko";
|
|
15903
16174
|
cache = /* @__PURE__ */ new Map();
|