@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.cjs
CHANGED
|
@@ -30,6 +30,228 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
|
|
|
30
30
|
));
|
|
31
31
|
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
32
32
|
|
|
33
|
+
// constants.ts
|
|
34
|
+
function getAddressStorageKey(addressId, key) {
|
|
35
|
+
return `${addressId}_${key}`;
|
|
36
|
+
}
|
|
37
|
+
function getAddressId(directAddress) {
|
|
38
|
+
let hash = directAddress;
|
|
39
|
+
if (hash.startsWith("DIRECT://")) {
|
|
40
|
+
hash = hash.slice(9);
|
|
41
|
+
} else if (hash.startsWith("DIRECT:")) {
|
|
42
|
+
hash = hash.slice(7);
|
|
43
|
+
}
|
|
44
|
+
const first = hash.slice(0, 6).toLowerCase();
|
|
45
|
+
const last = hash.slice(-6).toLowerCase();
|
|
46
|
+
return `DIRECT_${first}_${last}`;
|
|
47
|
+
}
|
|
48
|
+
var STORAGE_PREFIX, DEFAULT_ENCRYPTION_KEY, STORAGE_KEYS_GLOBAL, STORAGE_KEYS_ADDRESS, STORAGE_KEYS, DEFAULT_NOSTR_RELAYS, NOSTR_EVENT_KINDS, NIP29_KINDS, DEFAULT_AGGREGATOR_URL, DEV_AGGREGATOR_URL, TEST_AGGREGATOR_URL, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_IPFS_GATEWAYS, DEFAULT_IPFS_BOOTSTRAP_PEERS, DEFAULT_BASE_PATH, DEFAULT_DERIVATION_PATH, COIN_TYPES, DEFAULT_ELECTRUM_URL, TEST_ELECTRUM_URL, TOKEN_REGISTRY_URL, TOKEN_REGISTRY_REFRESH_INTERVAL, TEST_NOSTR_RELAYS, DEFAULT_GROUP_RELAYS, NETWORKS, TIMEOUTS, LIMITS;
|
|
49
|
+
var init_constants = __esm({
|
|
50
|
+
"constants.ts"() {
|
|
51
|
+
"use strict";
|
|
52
|
+
STORAGE_PREFIX = "sphere_";
|
|
53
|
+
DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
|
|
54
|
+
STORAGE_KEYS_GLOBAL = {
|
|
55
|
+
/** Encrypted BIP39 mnemonic */
|
|
56
|
+
MNEMONIC: "mnemonic",
|
|
57
|
+
/** Encrypted master private key */
|
|
58
|
+
MASTER_KEY: "master_key",
|
|
59
|
+
/** BIP32 chain code */
|
|
60
|
+
CHAIN_CODE: "chain_code",
|
|
61
|
+
/** HD derivation path (full path like m/44'/0'/0'/0/0) */
|
|
62
|
+
DERIVATION_PATH: "derivation_path",
|
|
63
|
+
/** Base derivation path (like m/44'/0'/0' without chain/index) */
|
|
64
|
+
BASE_PATH: "base_path",
|
|
65
|
+
/** Derivation mode: bip32, wif_hmac, legacy_hmac */
|
|
66
|
+
DERIVATION_MODE: "derivation_mode",
|
|
67
|
+
/** Wallet source: mnemonic, file, unknown */
|
|
68
|
+
WALLET_SOURCE: "wallet_source",
|
|
69
|
+
/** Wallet existence flag */
|
|
70
|
+
WALLET_EXISTS: "wallet_exists",
|
|
71
|
+
/** Current active address index */
|
|
72
|
+
CURRENT_ADDRESS_INDEX: "current_address_index",
|
|
73
|
+
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
74
|
+
ADDRESS_NAMETAGS: "address_nametags",
|
|
75
|
+
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
76
|
+
TRACKED_ADDRESSES: "tracked_addresses",
|
|
77
|
+
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
78
|
+
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
79
|
+
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
80
|
+
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
81
|
+
/** Cached token registry JSON (fetched from remote) */
|
|
82
|
+
TOKEN_REGISTRY_CACHE: "token_registry_cache",
|
|
83
|
+
/** Timestamp of last token registry cache update (ms since epoch) */
|
|
84
|
+
TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
|
|
85
|
+
/** Cached price data JSON (from CoinGecko or other provider) */
|
|
86
|
+
PRICE_CACHE: "price_cache",
|
|
87
|
+
/** Timestamp of last price cache update (ms since epoch) */
|
|
88
|
+
PRICE_CACHE_TS: "price_cache_ts"
|
|
89
|
+
};
|
|
90
|
+
STORAGE_KEYS_ADDRESS = {
|
|
91
|
+
/** Pending transfers for this address */
|
|
92
|
+
PENDING_TRANSFERS: "pending_transfers",
|
|
93
|
+
/** Transfer outbox for this address */
|
|
94
|
+
OUTBOX: "outbox",
|
|
95
|
+
/** Conversations for this address */
|
|
96
|
+
CONVERSATIONS: "conversations",
|
|
97
|
+
/** Messages for this address */
|
|
98
|
+
MESSAGES: "messages",
|
|
99
|
+
/** Transaction history for this address */
|
|
100
|
+
TRANSACTION_HISTORY: "transaction_history",
|
|
101
|
+
/** Pending V5 finalization tokens (unconfirmed instant split tokens) */
|
|
102
|
+
PENDING_V5_TOKENS: "pending_v5_tokens",
|
|
103
|
+
/** Group chat: joined groups for this address */
|
|
104
|
+
GROUP_CHAT_GROUPS: "group_chat_groups",
|
|
105
|
+
/** Group chat: messages for this address */
|
|
106
|
+
GROUP_CHAT_MESSAGES: "group_chat_messages",
|
|
107
|
+
/** Group chat: members for this address */
|
|
108
|
+
GROUP_CHAT_MEMBERS: "group_chat_members",
|
|
109
|
+
/** Group chat: processed event IDs for deduplication */
|
|
110
|
+
GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
|
|
111
|
+
};
|
|
112
|
+
STORAGE_KEYS = {
|
|
113
|
+
...STORAGE_KEYS_GLOBAL,
|
|
114
|
+
...STORAGE_KEYS_ADDRESS
|
|
115
|
+
};
|
|
116
|
+
DEFAULT_NOSTR_RELAYS = [
|
|
117
|
+
"wss://relay.unicity.network",
|
|
118
|
+
"wss://relay.damus.io",
|
|
119
|
+
"wss://nos.lol",
|
|
120
|
+
"wss://relay.nostr.band"
|
|
121
|
+
];
|
|
122
|
+
NOSTR_EVENT_KINDS = {
|
|
123
|
+
/** NIP-04 encrypted direct message */
|
|
124
|
+
DIRECT_MESSAGE: 4,
|
|
125
|
+
/** Token transfer (Unicity custom - 31113) */
|
|
126
|
+
TOKEN_TRANSFER: 31113,
|
|
127
|
+
/** Payment request (Unicity custom - 31115) */
|
|
128
|
+
PAYMENT_REQUEST: 31115,
|
|
129
|
+
/** Payment request response (Unicity custom - 31116) */
|
|
130
|
+
PAYMENT_REQUEST_RESPONSE: 31116,
|
|
131
|
+
/** Nametag binding (NIP-78 app-specific data) */
|
|
132
|
+
NAMETAG_BINDING: 30078,
|
|
133
|
+
/** Public broadcast */
|
|
134
|
+
BROADCAST: 1
|
|
135
|
+
};
|
|
136
|
+
NIP29_KINDS = {
|
|
137
|
+
/** Chat message sent to group */
|
|
138
|
+
CHAT_MESSAGE: 9,
|
|
139
|
+
/** Thread root message */
|
|
140
|
+
THREAD_ROOT: 11,
|
|
141
|
+
/** Thread reply message */
|
|
142
|
+
THREAD_REPLY: 12,
|
|
143
|
+
/** User join request */
|
|
144
|
+
JOIN_REQUEST: 9021,
|
|
145
|
+
/** User leave request */
|
|
146
|
+
LEAVE_REQUEST: 9022,
|
|
147
|
+
/** Admin: add/update user */
|
|
148
|
+
PUT_USER: 9e3,
|
|
149
|
+
/** Admin: remove user */
|
|
150
|
+
REMOVE_USER: 9001,
|
|
151
|
+
/** Admin: edit group metadata */
|
|
152
|
+
EDIT_METADATA: 9002,
|
|
153
|
+
/** Admin: delete event */
|
|
154
|
+
DELETE_EVENT: 9005,
|
|
155
|
+
/** Admin: create group */
|
|
156
|
+
CREATE_GROUP: 9007,
|
|
157
|
+
/** Admin: delete group */
|
|
158
|
+
DELETE_GROUP: 9008,
|
|
159
|
+
/** Admin: create invite code */
|
|
160
|
+
CREATE_INVITE: 9009,
|
|
161
|
+
/** Relay-signed group metadata */
|
|
162
|
+
GROUP_METADATA: 39e3,
|
|
163
|
+
/** Relay-signed group admins */
|
|
164
|
+
GROUP_ADMINS: 39001,
|
|
165
|
+
/** Relay-signed group members */
|
|
166
|
+
GROUP_MEMBERS: 39002,
|
|
167
|
+
/** Relay-signed group roles */
|
|
168
|
+
GROUP_ROLES: 39003
|
|
169
|
+
};
|
|
170
|
+
DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
|
|
171
|
+
DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
|
|
172
|
+
TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
|
|
173
|
+
DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
|
|
174
|
+
DEFAULT_IPFS_GATEWAYS = [
|
|
175
|
+
"https://unicity-ipfs1.dyndns.org"
|
|
176
|
+
];
|
|
177
|
+
DEFAULT_IPFS_BOOTSTRAP_PEERS = [
|
|
178
|
+
"/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
|
|
179
|
+
"/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
|
|
180
|
+
"/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
|
|
181
|
+
"/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
|
|
182
|
+
];
|
|
183
|
+
DEFAULT_BASE_PATH = "m/44'/0'/0'";
|
|
184
|
+
DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
|
|
185
|
+
COIN_TYPES = {
|
|
186
|
+
/** ALPHA token (L1 blockchain) */
|
|
187
|
+
ALPHA: "ALPHA",
|
|
188
|
+
/** Test token */
|
|
189
|
+
TEST: "TEST"
|
|
190
|
+
};
|
|
191
|
+
DEFAULT_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
|
|
192
|
+
TEST_ELECTRUM_URL = "wss://fulcrum.unicity.network:50004";
|
|
193
|
+
TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
194
|
+
TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
|
|
195
|
+
TEST_NOSTR_RELAYS = [
|
|
196
|
+
"wss://nostr-relay.testnet.unicity.network"
|
|
197
|
+
];
|
|
198
|
+
DEFAULT_GROUP_RELAYS = [
|
|
199
|
+
"wss://sphere-relay.unicity.network"
|
|
200
|
+
];
|
|
201
|
+
NETWORKS = {
|
|
202
|
+
mainnet: {
|
|
203
|
+
name: "Mainnet",
|
|
204
|
+
aggregatorUrl: DEFAULT_AGGREGATOR_URL,
|
|
205
|
+
nostrRelays: DEFAULT_NOSTR_RELAYS,
|
|
206
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
207
|
+
electrumUrl: DEFAULT_ELECTRUM_URL,
|
|
208
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
209
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
210
|
+
},
|
|
211
|
+
testnet: {
|
|
212
|
+
name: "Testnet",
|
|
213
|
+
aggregatorUrl: TEST_AGGREGATOR_URL,
|
|
214
|
+
nostrRelays: TEST_NOSTR_RELAYS,
|
|
215
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
216
|
+
electrumUrl: TEST_ELECTRUM_URL,
|
|
217
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
218
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
219
|
+
},
|
|
220
|
+
dev: {
|
|
221
|
+
name: "Development",
|
|
222
|
+
aggregatorUrl: DEV_AGGREGATOR_URL,
|
|
223
|
+
nostrRelays: TEST_NOSTR_RELAYS,
|
|
224
|
+
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
225
|
+
electrumUrl: TEST_ELECTRUM_URL,
|
|
226
|
+
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
227
|
+
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
TIMEOUTS = {
|
|
231
|
+
/** WebSocket connection timeout */
|
|
232
|
+
WEBSOCKET_CONNECT: 1e4,
|
|
233
|
+
/** Nostr relay reconnect delay */
|
|
234
|
+
NOSTR_RECONNECT_DELAY: 3e3,
|
|
235
|
+
/** Max reconnect attempts */
|
|
236
|
+
MAX_RECONNECT_ATTEMPTS: 5,
|
|
237
|
+
/** Proof polling interval */
|
|
238
|
+
PROOF_POLL_INTERVAL: 1e3,
|
|
239
|
+
/** Sync interval */
|
|
240
|
+
SYNC_INTERVAL: 6e4
|
|
241
|
+
};
|
|
242
|
+
LIMITS = {
|
|
243
|
+
/** Min nametag length */
|
|
244
|
+
NAMETAG_MIN_LENGTH: 3,
|
|
245
|
+
/** Max nametag length */
|
|
246
|
+
NAMETAG_MAX_LENGTH: 20,
|
|
247
|
+
/** Max memo length */
|
|
248
|
+
MEMO_MAX_LENGTH: 500,
|
|
249
|
+
/** Max message length */
|
|
250
|
+
MESSAGE_MAX_LENGTH: 1e4
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
33
255
|
// core/bech32.ts
|
|
34
256
|
function convertBits(data, fromBits, toBits, pad) {
|
|
35
257
|
let acc = 0;
|
|
@@ -447,7 +669,8 @@ var init_network = __esm({
|
|
|
447
669
|
"l1/network.ts"() {
|
|
448
670
|
"use strict";
|
|
449
671
|
init_addressToScriptHash();
|
|
450
|
-
|
|
672
|
+
init_constants();
|
|
673
|
+
DEFAULT_ENDPOINT = DEFAULT_ELECTRUM_URL;
|
|
451
674
|
ws = null;
|
|
452
675
|
isConnected = false;
|
|
453
676
|
isConnecting = false;
|
|
@@ -611,6 +834,9 @@ __export(index_exports, {
|
|
|
611
834
|
});
|
|
612
835
|
module.exports = __toCommonJS(index_exports);
|
|
613
836
|
|
|
837
|
+
// modules/payments/L1PaymentsModule.ts
|
|
838
|
+
init_constants();
|
|
839
|
+
|
|
614
840
|
// l1/index.ts
|
|
615
841
|
var l1_exports = {};
|
|
616
842
|
__export(l1_exports, {
|
|
@@ -1796,7 +2022,7 @@ var L1PaymentsModule = class {
|
|
|
1796
2022
|
_transport;
|
|
1797
2023
|
constructor(config) {
|
|
1798
2024
|
this._config = {
|
|
1799
|
-
electrumUrl: config?.electrumUrl ??
|
|
2025
|
+
electrumUrl: config?.electrumUrl ?? DEFAULT_ELECTRUM_URL,
|
|
1800
2026
|
network: config?.network ?? "mainnet",
|
|
1801
2027
|
defaultFeeRate: config?.defaultFeeRate ?? 10,
|
|
1802
2028
|
enableVesting: config?.enableVesting ?? true
|
|
@@ -2636,221 +2862,8 @@ var NametagMinter = class {
|
|
|
2636
2862
|
}
|
|
2637
2863
|
};
|
|
2638
2864
|
|
|
2639
|
-
//
|
|
2640
|
-
|
|
2641
|
-
var DEFAULT_ENCRYPTION_KEY = "sphere-default-key";
|
|
2642
|
-
var STORAGE_KEYS_GLOBAL = {
|
|
2643
|
-
/** Encrypted BIP39 mnemonic */
|
|
2644
|
-
MNEMONIC: "mnemonic",
|
|
2645
|
-
/** Encrypted master private key */
|
|
2646
|
-
MASTER_KEY: "master_key",
|
|
2647
|
-
/** BIP32 chain code */
|
|
2648
|
-
CHAIN_CODE: "chain_code",
|
|
2649
|
-
/** HD derivation path (full path like m/44'/0'/0'/0/0) */
|
|
2650
|
-
DERIVATION_PATH: "derivation_path",
|
|
2651
|
-
/** Base derivation path (like m/44'/0'/0' without chain/index) */
|
|
2652
|
-
BASE_PATH: "base_path",
|
|
2653
|
-
/** Derivation mode: bip32, wif_hmac, legacy_hmac */
|
|
2654
|
-
DERIVATION_MODE: "derivation_mode",
|
|
2655
|
-
/** Wallet source: mnemonic, file, unknown */
|
|
2656
|
-
WALLET_SOURCE: "wallet_source",
|
|
2657
|
-
/** Wallet existence flag */
|
|
2658
|
-
WALLET_EXISTS: "wallet_exists",
|
|
2659
|
-
/** Current active address index */
|
|
2660
|
-
CURRENT_ADDRESS_INDEX: "current_address_index",
|
|
2661
|
-
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
2662
|
-
ADDRESS_NAMETAGS: "address_nametags",
|
|
2663
|
-
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
2664
|
-
TRACKED_ADDRESSES: "tracked_addresses",
|
|
2665
|
-
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
2666
|
-
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
2667
|
-
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
2668
|
-
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
2669
|
-
/** Cached token registry JSON (fetched from remote) */
|
|
2670
|
-
TOKEN_REGISTRY_CACHE: "token_registry_cache",
|
|
2671
|
-
/** Timestamp of last token registry cache update (ms since epoch) */
|
|
2672
|
-
TOKEN_REGISTRY_CACHE_TS: "token_registry_cache_ts",
|
|
2673
|
-
/** Cached price data JSON (from CoinGecko or other provider) */
|
|
2674
|
-
PRICE_CACHE: "price_cache",
|
|
2675
|
-
/** Timestamp of last price cache update (ms since epoch) */
|
|
2676
|
-
PRICE_CACHE_TS: "price_cache_ts"
|
|
2677
|
-
};
|
|
2678
|
-
var STORAGE_KEYS_ADDRESS = {
|
|
2679
|
-
/** Pending transfers for this address */
|
|
2680
|
-
PENDING_TRANSFERS: "pending_transfers",
|
|
2681
|
-
/** Transfer outbox for this address */
|
|
2682
|
-
OUTBOX: "outbox",
|
|
2683
|
-
/** Conversations for this address */
|
|
2684
|
-
CONVERSATIONS: "conversations",
|
|
2685
|
-
/** Messages for this address */
|
|
2686
|
-
MESSAGES: "messages",
|
|
2687
|
-
/** Transaction history for this address */
|
|
2688
|
-
TRANSACTION_HISTORY: "transaction_history",
|
|
2689
|
-
/** Pending V5 finalization tokens (unconfirmed instant split tokens) */
|
|
2690
|
-
PENDING_V5_TOKENS: "pending_v5_tokens",
|
|
2691
|
-
/** Group chat: joined groups for this address */
|
|
2692
|
-
GROUP_CHAT_GROUPS: "group_chat_groups",
|
|
2693
|
-
/** Group chat: messages for this address */
|
|
2694
|
-
GROUP_CHAT_MESSAGES: "group_chat_messages",
|
|
2695
|
-
/** Group chat: members for this address */
|
|
2696
|
-
GROUP_CHAT_MEMBERS: "group_chat_members",
|
|
2697
|
-
/** Group chat: processed event IDs for deduplication */
|
|
2698
|
-
GROUP_CHAT_PROCESSED_EVENTS: "group_chat_processed_events"
|
|
2699
|
-
};
|
|
2700
|
-
var STORAGE_KEYS = {
|
|
2701
|
-
...STORAGE_KEYS_GLOBAL,
|
|
2702
|
-
...STORAGE_KEYS_ADDRESS
|
|
2703
|
-
};
|
|
2704
|
-
function getAddressStorageKey(addressId, key) {
|
|
2705
|
-
return `${addressId}_${key}`;
|
|
2706
|
-
}
|
|
2707
|
-
function getAddressId(directAddress) {
|
|
2708
|
-
let hash = directAddress;
|
|
2709
|
-
if (hash.startsWith("DIRECT://")) {
|
|
2710
|
-
hash = hash.slice(9);
|
|
2711
|
-
} else if (hash.startsWith("DIRECT:")) {
|
|
2712
|
-
hash = hash.slice(7);
|
|
2713
|
-
}
|
|
2714
|
-
const first = hash.slice(0, 6).toLowerCase();
|
|
2715
|
-
const last = hash.slice(-6).toLowerCase();
|
|
2716
|
-
return `DIRECT_${first}_${last}`;
|
|
2717
|
-
}
|
|
2718
|
-
var DEFAULT_NOSTR_RELAYS = [
|
|
2719
|
-
"wss://relay.unicity.network",
|
|
2720
|
-
"wss://relay.damus.io",
|
|
2721
|
-
"wss://nos.lol",
|
|
2722
|
-
"wss://relay.nostr.band"
|
|
2723
|
-
];
|
|
2724
|
-
var NOSTR_EVENT_KINDS = {
|
|
2725
|
-
/** NIP-04 encrypted direct message */
|
|
2726
|
-
DIRECT_MESSAGE: 4,
|
|
2727
|
-
/** Token transfer (Unicity custom - 31113) */
|
|
2728
|
-
TOKEN_TRANSFER: 31113,
|
|
2729
|
-
/** Payment request (Unicity custom - 31115) */
|
|
2730
|
-
PAYMENT_REQUEST: 31115,
|
|
2731
|
-
/** Payment request response (Unicity custom - 31116) */
|
|
2732
|
-
PAYMENT_REQUEST_RESPONSE: 31116,
|
|
2733
|
-
/** Nametag binding (NIP-78 app-specific data) */
|
|
2734
|
-
NAMETAG_BINDING: 30078,
|
|
2735
|
-
/** Public broadcast */
|
|
2736
|
-
BROADCAST: 1
|
|
2737
|
-
};
|
|
2738
|
-
var NIP29_KINDS = {
|
|
2739
|
-
/** Chat message sent to group */
|
|
2740
|
-
CHAT_MESSAGE: 9,
|
|
2741
|
-
/** Thread root message */
|
|
2742
|
-
THREAD_ROOT: 11,
|
|
2743
|
-
/** Thread reply message */
|
|
2744
|
-
THREAD_REPLY: 12,
|
|
2745
|
-
/** User join request */
|
|
2746
|
-
JOIN_REQUEST: 9021,
|
|
2747
|
-
/** User leave request */
|
|
2748
|
-
LEAVE_REQUEST: 9022,
|
|
2749
|
-
/** Admin: add/update user */
|
|
2750
|
-
PUT_USER: 9e3,
|
|
2751
|
-
/** Admin: remove user */
|
|
2752
|
-
REMOVE_USER: 9001,
|
|
2753
|
-
/** Admin: edit group metadata */
|
|
2754
|
-
EDIT_METADATA: 9002,
|
|
2755
|
-
/** Admin: delete event */
|
|
2756
|
-
DELETE_EVENT: 9005,
|
|
2757
|
-
/** Admin: create group */
|
|
2758
|
-
CREATE_GROUP: 9007,
|
|
2759
|
-
/** Admin: delete group */
|
|
2760
|
-
DELETE_GROUP: 9008,
|
|
2761
|
-
/** Admin: create invite code */
|
|
2762
|
-
CREATE_INVITE: 9009,
|
|
2763
|
-
/** Relay-signed group metadata */
|
|
2764
|
-
GROUP_METADATA: 39e3,
|
|
2765
|
-
/** Relay-signed group admins */
|
|
2766
|
-
GROUP_ADMINS: 39001,
|
|
2767
|
-
/** Relay-signed group members */
|
|
2768
|
-
GROUP_MEMBERS: 39002,
|
|
2769
|
-
/** Relay-signed group roles */
|
|
2770
|
-
GROUP_ROLES: 39003
|
|
2771
|
-
};
|
|
2772
|
-
var DEFAULT_AGGREGATOR_URL = "https://aggregator.unicity.network/rpc";
|
|
2773
|
-
var DEV_AGGREGATOR_URL = "https://dev-aggregator.dyndns.org/rpc";
|
|
2774
|
-
var TEST_AGGREGATOR_URL = "https://goggregator-test.unicity.network";
|
|
2775
|
-
var DEFAULT_AGGREGATOR_TIMEOUT = 3e4;
|
|
2776
|
-
var DEFAULT_IPFS_GATEWAYS = [
|
|
2777
|
-
"https://unicity-ipfs1.dyndns.org"
|
|
2778
|
-
];
|
|
2779
|
-
var DEFAULT_IPFS_BOOTSTRAP_PEERS = [
|
|
2780
|
-
"/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh",
|
|
2781
|
-
"/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6",
|
|
2782
|
-
"/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1",
|
|
2783
|
-
"/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv"
|
|
2784
|
-
];
|
|
2785
|
-
var DEFAULT_BASE_PATH = "m/44'/0'/0'";
|
|
2786
|
-
var DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0`;
|
|
2787
|
-
var COIN_TYPES = {
|
|
2788
|
-
/** ALPHA token (L1 blockchain) */
|
|
2789
|
-
ALPHA: "ALPHA",
|
|
2790
|
-
/** Test token */
|
|
2791
|
-
TEST: "TEST"
|
|
2792
|
-
};
|
|
2793
|
-
var DEFAULT_ELECTRUM_URL = "wss://fulcrum.alpha.unicity.network:50004";
|
|
2794
|
-
var TEST_ELECTRUM_URL = "wss://fulcrum.alpha.testnet.unicity.network:50004";
|
|
2795
|
-
var TOKEN_REGISTRY_URL = "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
2796
|
-
var TOKEN_REGISTRY_REFRESH_INTERVAL = 36e5;
|
|
2797
|
-
var TEST_NOSTR_RELAYS = [
|
|
2798
|
-
"wss://nostr-relay.testnet.unicity.network"
|
|
2799
|
-
];
|
|
2800
|
-
var DEFAULT_GROUP_RELAYS = [
|
|
2801
|
-
"wss://sphere-relay.unicity.network"
|
|
2802
|
-
];
|
|
2803
|
-
var NETWORKS = {
|
|
2804
|
-
mainnet: {
|
|
2805
|
-
name: "Mainnet",
|
|
2806
|
-
aggregatorUrl: DEFAULT_AGGREGATOR_URL,
|
|
2807
|
-
nostrRelays: DEFAULT_NOSTR_RELAYS,
|
|
2808
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2809
|
-
electrumUrl: DEFAULT_ELECTRUM_URL,
|
|
2810
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2811
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2812
|
-
},
|
|
2813
|
-
testnet: {
|
|
2814
|
-
name: "Testnet",
|
|
2815
|
-
aggregatorUrl: TEST_AGGREGATOR_URL,
|
|
2816
|
-
nostrRelays: TEST_NOSTR_RELAYS,
|
|
2817
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2818
|
-
electrumUrl: TEST_ELECTRUM_URL,
|
|
2819
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2820
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2821
|
-
},
|
|
2822
|
-
dev: {
|
|
2823
|
-
name: "Development",
|
|
2824
|
-
aggregatorUrl: DEV_AGGREGATOR_URL,
|
|
2825
|
-
nostrRelays: TEST_NOSTR_RELAYS,
|
|
2826
|
-
ipfsGateways: DEFAULT_IPFS_GATEWAYS,
|
|
2827
|
-
electrumUrl: TEST_ELECTRUM_URL,
|
|
2828
|
-
groupRelays: DEFAULT_GROUP_RELAYS,
|
|
2829
|
-
tokenRegistryUrl: TOKEN_REGISTRY_URL
|
|
2830
|
-
}
|
|
2831
|
-
};
|
|
2832
|
-
var TIMEOUTS = {
|
|
2833
|
-
/** WebSocket connection timeout */
|
|
2834
|
-
WEBSOCKET_CONNECT: 1e4,
|
|
2835
|
-
/** Nostr relay reconnect delay */
|
|
2836
|
-
NOSTR_RECONNECT_DELAY: 3e3,
|
|
2837
|
-
/** Max reconnect attempts */
|
|
2838
|
-
MAX_RECONNECT_ATTEMPTS: 5,
|
|
2839
|
-
/** Proof polling interval */
|
|
2840
|
-
PROOF_POLL_INTERVAL: 1e3,
|
|
2841
|
-
/** Sync interval */
|
|
2842
|
-
SYNC_INTERVAL: 6e4
|
|
2843
|
-
};
|
|
2844
|
-
var LIMITS = {
|
|
2845
|
-
/** Min nametag length */
|
|
2846
|
-
NAMETAG_MIN_LENGTH: 3,
|
|
2847
|
-
/** Max nametag length */
|
|
2848
|
-
NAMETAG_MAX_LENGTH: 20,
|
|
2849
|
-
/** Max memo length */
|
|
2850
|
-
MEMO_MAX_LENGTH: 500,
|
|
2851
|
-
/** Max message length */
|
|
2852
|
-
MESSAGE_MAX_LENGTH: 1e4
|
|
2853
|
-
};
|
|
2865
|
+
// modules/payments/PaymentsModule.ts
|
|
2866
|
+
init_constants();
|
|
2854
2867
|
|
|
2855
2868
|
// types/txf.ts
|
|
2856
2869
|
var ARCHIVED_PREFIX = "archived-";
|
|
@@ -2895,6 +2908,7 @@ function isValidTokenId(tokenId) {
|
|
|
2895
2908
|
}
|
|
2896
2909
|
|
|
2897
2910
|
// registry/TokenRegistry.ts
|
|
2911
|
+
init_constants();
|
|
2898
2912
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
2899
2913
|
var TokenRegistry = class _TokenRegistry {
|
|
2900
2914
|
static instance = null;
|
|
@@ -7792,6 +7806,7 @@ var import_HashAlgorithm6 = require("@unicitylabs/state-transition-sdk/lib/hash/
|
|
|
7792
7806
|
var import_UnmaskedPredicate6 = require("@unicitylabs/state-transition-sdk/lib/predicate/embedded/UnmaskedPredicate");
|
|
7793
7807
|
|
|
7794
7808
|
// modules/communications/CommunicationsModule.ts
|
|
7809
|
+
init_constants();
|
|
7795
7810
|
var CommunicationsModule = class {
|
|
7796
7811
|
config;
|
|
7797
7812
|
deps = null;
|
|
@@ -8267,6 +8282,7 @@ function createCommunicationsModule(config) {
|
|
|
8267
8282
|
|
|
8268
8283
|
// modules/groupchat/GroupChatModule.ts
|
|
8269
8284
|
var import_nostr_js_sdk2 = require("@unicitylabs/nostr-js-sdk");
|
|
8285
|
+
init_constants();
|
|
8270
8286
|
|
|
8271
8287
|
// modules/groupchat/types.ts
|
|
8272
8288
|
var GroupRole = {
|
|
@@ -8517,10 +8533,12 @@ var GroupChatModule = class {
|
|
|
8517
8533
|
if (!this.client) return;
|
|
8518
8534
|
const groupIds = Array.from(this.groups.keys());
|
|
8519
8535
|
if (groupIds.length === 0) return;
|
|
8536
|
+
const latestTimestamp = this.getLatestMessageTimestamp(groupIds);
|
|
8520
8537
|
this.trackSubscription(
|
|
8521
8538
|
createNip29Filter({
|
|
8522
8539
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
8523
|
-
"#h": groupIds
|
|
8540
|
+
"#h": groupIds,
|
|
8541
|
+
...latestTimestamp ? { since: latestTimestamp } : {}
|
|
8524
8542
|
}),
|
|
8525
8543
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
8526
8544
|
);
|
|
@@ -8541,10 +8559,12 @@ var GroupChatModule = class {
|
|
|
8541
8559
|
}
|
|
8542
8560
|
subscribeToGroup(groupId) {
|
|
8543
8561
|
if (!this.client) return;
|
|
8562
|
+
const latestTimestamp = this.getLatestMessageTimestamp([groupId]);
|
|
8544
8563
|
this.trackSubscription(
|
|
8545
8564
|
createNip29Filter({
|
|
8546
8565
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
8547
|
-
"#h": [groupId]
|
|
8566
|
+
"#h": [groupId],
|
|
8567
|
+
...latestTimestamp ? { since: latestTimestamp } : {}
|
|
8548
8568
|
}),
|
|
8549
8569
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
8550
8570
|
);
|
|
@@ -9236,6 +9256,23 @@ var GroupChatModule = class {
|
|
|
9236
9256
|
getMyPublicKey() {
|
|
9237
9257
|
return this.keyManager?.getPublicKeyHex() || null;
|
|
9238
9258
|
}
|
|
9259
|
+
/**
|
|
9260
|
+
* Returns the latest message timestamp (in Nostr seconds) across the given groups,
|
|
9261
|
+
* or 0 if no messages exist. Used to set `since` on subscriptions so the relay
|
|
9262
|
+
* only sends events we don't already have.
|
|
9263
|
+
*/
|
|
9264
|
+
getLatestMessageTimestamp(groupIds) {
|
|
9265
|
+
let latest = 0;
|
|
9266
|
+
for (const gid of groupIds) {
|
|
9267
|
+
const msgs = this.messages.get(gid);
|
|
9268
|
+
if (!msgs) continue;
|
|
9269
|
+
for (const m of msgs) {
|
|
9270
|
+
const ts = Math.floor(m.timestamp / 1e3);
|
|
9271
|
+
if (ts > latest) latest = ts;
|
|
9272
|
+
}
|
|
9273
|
+
}
|
|
9274
|
+
return latest;
|
|
9275
|
+
}
|
|
9239
9276
|
// ===========================================================================
|
|
9240
9277
|
// Private — Relay Admin
|
|
9241
9278
|
// ===========================================================================
|
|
@@ -12090,6 +12127,9 @@ function createMarketModule(config) {
|
|
|
12090
12127
|
return new MarketModule(config);
|
|
12091
12128
|
}
|
|
12092
12129
|
|
|
12130
|
+
// core/Sphere.ts
|
|
12131
|
+
init_constants();
|
|
12132
|
+
|
|
12093
12133
|
// core/encryption.ts
|
|
12094
12134
|
var import_crypto_js6 = __toESM(require("crypto-js"), 1);
|
|
12095
12135
|
function encryptSimple(plaintext, password) {
|
|
@@ -12193,6 +12233,72 @@ async function scanAddressesImpl(deriveAddress, options = {}) {
|
|
|
12193
12233
|
};
|
|
12194
12234
|
}
|
|
12195
12235
|
|
|
12236
|
+
// core/discover.ts
|
|
12237
|
+
async function discoverAddressesImpl(deriveTransportPubkey, batchResolve, options = {}) {
|
|
12238
|
+
const maxAddresses = options.maxAddresses ?? 50;
|
|
12239
|
+
const gapLimit = options.gapLimit ?? 20;
|
|
12240
|
+
const batchSize = options.batchSize ?? 20;
|
|
12241
|
+
const { onProgress, signal } = options;
|
|
12242
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
12243
|
+
let consecutiveEmpty = 0;
|
|
12244
|
+
let scanned = 0;
|
|
12245
|
+
const totalBatches = Math.ceil(maxAddresses / batchSize);
|
|
12246
|
+
for (let batchStart = 0; batchStart < maxAddresses; batchStart += batchSize) {
|
|
12247
|
+
if (signal?.aborted) break;
|
|
12248
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12249
|
+
const batchEnd = Math.min(batchStart + batchSize, maxAddresses);
|
|
12250
|
+
const batchIndices = [];
|
|
12251
|
+
const pubkeyToIndex = /* @__PURE__ */ new Map();
|
|
12252
|
+
const pubkeyToInfo = /* @__PURE__ */ new Map();
|
|
12253
|
+
for (let i = batchStart; i < batchEnd; i++) {
|
|
12254
|
+
const info = deriveTransportPubkey(i);
|
|
12255
|
+
batchIndices.push(i);
|
|
12256
|
+
pubkeyToIndex.set(info.transportPubkey, i);
|
|
12257
|
+
pubkeyToInfo.set(info.transportPubkey, info);
|
|
12258
|
+
}
|
|
12259
|
+
const batchPubkeys = Array.from(pubkeyToIndex.keys());
|
|
12260
|
+
onProgress?.({
|
|
12261
|
+
currentBatch: Math.floor(batchStart / batchSize) + 1,
|
|
12262
|
+
totalBatches,
|
|
12263
|
+
discoveredCount: discovered.size,
|
|
12264
|
+
currentGap: consecutiveEmpty,
|
|
12265
|
+
phase: "transport"
|
|
12266
|
+
});
|
|
12267
|
+
const peerInfos = await batchResolve(batchPubkeys);
|
|
12268
|
+
const foundInBatch = /* @__PURE__ */ new Set();
|
|
12269
|
+
for (const peer of peerInfos) {
|
|
12270
|
+
const index = pubkeyToIndex.get(peer.transportPubkey);
|
|
12271
|
+
if (index !== void 0) {
|
|
12272
|
+
foundInBatch.add(index);
|
|
12273
|
+
const derived = pubkeyToInfo.get(peer.transportPubkey);
|
|
12274
|
+
discovered.set(index, {
|
|
12275
|
+
index,
|
|
12276
|
+
l1Address: peer.l1Address || derived.l1Address,
|
|
12277
|
+
directAddress: peer.directAddress || derived.directAddress,
|
|
12278
|
+
chainPubkey: peer.chainPubkey || derived.chainPubkey,
|
|
12279
|
+
nametag: peer.nametag,
|
|
12280
|
+
l1Balance: 0,
|
|
12281
|
+
source: "transport"
|
|
12282
|
+
});
|
|
12283
|
+
}
|
|
12284
|
+
}
|
|
12285
|
+
for (const idx of batchIndices) {
|
|
12286
|
+
scanned++;
|
|
12287
|
+
if (foundInBatch.has(idx)) {
|
|
12288
|
+
consecutiveEmpty = 0;
|
|
12289
|
+
} else {
|
|
12290
|
+
consecutiveEmpty++;
|
|
12291
|
+
if (consecutiveEmpty >= gapLimit) break;
|
|
12292
|
+
}
|
|
12293
|
+
}
|
|
12294
|
+
}
|
|
12295
|
+
return {
|
|
12296
|
+
addresses: Array.from(discovered.values()).sort((a, b) => a.index - b.index),
|
|
12297
|
+
scannedCount: scanned,
|
|
12298
|
+
aborted: signal?.aborted ?? false
|
|
12299
|
+
};
|
|
12300
|
+
}
|
|
12301
|
+
|
|
12196
12302
|
// core/Sphere.ts
|
|
12197
12303
|
init_network();
|
|
12198
12304
|
|
|
@@ -13015,7 +13121,9 @@ var Sphere = class _Sphere {
|
|
|
13015
13121
|
price: options.price,
|
|
13016
13122
|
groupChat,
|
|
13017
13123
|
market,
|
|
13018
|
-
password: options.password
|
|
13124
|
+
password: options.password,
|
|
13125
|
+
discoverAddresses: options.discoverAddresses,
|
|
13126
|
+
onProgress: options.onProgress
|
|
13019
13127
|
});
|
|
13020
13128
|
return { sphere: sphere2, created: false };
|
|
13021
13129
|
}
|
|
@@ -13043,7 +13151,9 @@ var Sphere = class _Sphere {
|
|
|
13043
13151
|
price: options.price,
|
|
13044
13152
|
groupChat,
|
|
13045
13153
|
market,
|
|
13046
|
-
password: options.password
|
|
13154
|
+
password: options.password,
|
|
13155
|
+
discoverAddresses: options.discoverAddresses,
|
|
13156
|
+
onProgress: options.onProgress
|
|
13047
13157
|
});
|
|
13048
13158
|
return { sphere, created: true, generatedMnemonic };
|
|
13049
13159
|
}
|
|
@@ -13104,6 +13214,7 @@ var Sphere = class _Sphere {
|
|
|
13104
13214
|
if (await _Sphere.exists(options.storage)) {
|
|
13105
13215
|
throw new Error("Wallet already exists. Use Sphere.load() or Sphere.clear() first.");
|
|
13106
13216
|
}
|
|
13217
|
+
const progress = options.onProgress;
|
|
13107
13218
|
if (!options.storage.isConnected()) {
|
|
13108
13219
|
await options.storage.connect();
|
|
13109
13220
|
}
|
|
@@ -13121,20 +13232,39 @@ var Sphere = class _Sphere {
|
|
|
13121
13232
|
marketConfig
|
|
13122
13233
|
);
|
|
13123
13234
|
sphere._password = options.password ?? null;
|
|
13235
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
13124
13236
|
await sphere.storeMnemonic(options.mnemonic, options.derivationPath);
|
|
13125
13237
|
await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
|
|
13238
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13126
13239
|
await sphere.initializeProviders();
|
|
13127
13240
|
await sphere.initializeModules();
|
|
13241
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
13128
13242
|
await sphere.finalizeWalletCreation();
|
|
13129
13243
|
sphere._initialized = true;
|
|
13130
13244
|
_Sphere.instance = sphere;
|
|
13131
13245
|
await sphere.ensureAddressTracked(0);
|
|
13132
13246
|
if (options.nametag) {
|
|
13247
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
13133
13248
|
await sphere.registerNametag(options.nametag);
|
|
13134
13249
|
} else {
|
|
13250
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
13135
13251
|
await sphere.recoverNametagFromTransport();
|
|
13252
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13136
13253
|
await sphere.syncIdentityWithTransport();
|
|
13137
13254
|
}
|
|
13255
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13256
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13257
|
+
try {
|
|
13258
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13259
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13260
|
+
if (result.addresses.length > 0) {
|
|
13261
|
+
console.log(`[Sphere.create] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13262
|
+
}
|
|
13263
|
+
} catch (err) {
|
|
13264
|
+
console.warn("[Sphere.create] Address discovery failed (non-fatal):", err);
|
|
13265
|
+
}
|
|
13266
|
+
}
|
|
13267
|
+
progress?.({ step: "complete", message: "Wallet created" });
|
|
13138
13268
|
return sphere;
|
|
13139
13269
|
}
|
|
13140
13270
|
/**
|
|
@@ -13144,6 +13274,7 @@ var Sphere = class _Sphere {
|
|
|
13144
13274
|
if (!await _Sphere.exists(options.storage)) {
|
|
13145
13275
|
throw new Error("No wallet found. Use Sphere.create() to create a new wallet.");
|
|
13146
13276
|
}
|
|
13277
|
+
const progress = options.onProgress;
|
|
13147
13278
|
_Sphere.configureTokenRegistry(options.storage, options.network);
|
|
13148
13279
|
const groupChatConfig = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
|
|
13149
13280
|
const marketConfig = _Sphere.resolveMarketConfig(options.market);
|
|
@@ -13161,13 +13292,17 @@ var Sphere = class _Sphere {
|
|
|
13161
13292
|
if (!options.storage.isConnected()) {
|
|
13162
13293
|
await options.storage.connect();
|
|
13163
13294
|
}
|
|
13295
|
+
progress?.({ step: "storing_keys", message: "Loading wallet keys..." });
|
|
13164
13296
|
await sphere.loadIdentityFromStorage();
|
|
13297
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13165
13298
|
await sphere.initializeProviders();
|
|
13166
13299
|
await sphere.initializeModules();
|
|
13300
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13167
13301
|
await sphere.syncIdentityWithTransport();
|
|
13168
13302
|
sphere._initialized = true;
|
|
13169
13303
|
_Sphere.instance = sphere;
|
|
13170
13304
|
if (sphere._identity?.nametag && !sphere._payments.hasNametag()) {
|
|
13305
|
+
progress?.({ step: "registering_nametag", message: "Restoring nametag token..." });
|
|
13171
13306
|
console.log(`[Sphere] Nametag @${sphere._identity.nametag} has no token, attempting to mint...`);
|
|
13172
13307
|
try {
|
|
13173
13308
|
const result = await sphere.mintNametag(sphere._identity.nametag);
|
|
@@ -13180,6 +13315,19 @@ var Sphere = class _Sphere {
|
|
|
13180
13315
|
console.warn(`[Sphere] Nametag token mint failed:`, err);
|
|
13181
13316
|
}
|
|
13182
13317
|
}
|
|
13318
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses && sphere._masterKey) {
|
|
13319
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13320
|
+
try {
|
|
13321
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13322
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13323
|
+
if (result.addresses.length > 0) {
|
|
13324
|
+
console.log(`[Sphere.load] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13325
|
+
}
|
|
13326
|
+
} catch (err) {
|
|
13327
|
+
console.warn("[Sphere.load] Address discovery failed (non-fatal):", err);
|
|
13328
|
+
}
|
|
13329
|
+
}
|
|
13330
|
+
progress?.({ step: "complete", message: "Wallet loaded" });
|
|
13183
13331
|
return sphere;
|
|
13184
13332
|
}
|
|
13185
13333
|
/**
|
|
@@ -13189,9 +13337,11 @@ var Sphere = class _Sphere {
|
|
|
13189
13337
|
if (!options.mnemonic && !options.masterKey) {
|
|
13190
13338
|
throw new Error("Either mnemonic or masterKey is required");
|
|
13191
13339
|
}
|
|
13340
|
+
const progress = options.onProgress;
|
|
13192
13341
|
console.log("[Sphere.import] Starting import...");
|
|
13193
13342
|
const needsClear = _Sphere.instance !== null || await _Sphere.exists(options.storage);
|
|
13194
13343
|
if (needsClear) {
|
|
13344
|
+
progress?.({ step: "clearing", message: "Clearing previous wallet data..." });
|
|
13195
13345
|
console.log("[Sphere.import] Clearing existing wallet data...");
|
|
13196
13346
|
await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
|
|
13197
13347
|
console.log("[Sphere.import] Clear done");
|
|
@@ -13216,6 +13366,7 @@ var Sphere = class _Sphere {
|
|
|
13216
13366
|
marketConfig
|
|
13217
13367
|
);
|
|
13218
13368
|
sphere._password = options.password ?? null;
|
|
13369
|
+
progress?.({ step: "storing_keys", message: "Storing wallet keys..." });
|
|
13219
13370
|
if (options.mnemonic) {
|
|
13220
13371
|
if (!_Sphere.validateMnemonic(options.mnemonic)) {
|
|
13221
13372
|
throw new Error("Invalid mnemonic");
|
|
@@ -13240,17 +13391,21 @@ var Sphere = class _Sphere {
|
|
|
13240
13391
|
options.derivationPath
|
|
13241
13392
|
);
|
|
13242
13393
|
}
|
|
13394
|
+
progress?.({ step: "initializing", message: "Initializing wallet..." });
|
|
13243
13395
|
console.log("[Sphere.import] Initializing providers...");
|
|
13244
13396
|
await sphere.initializeProviders();
|
|
13245
13397
|
console.log("[Sphere.import] Providers initialized. Initializing modules...");
|
|
13246
13398
|
await sphere.initializeModules();
|
|
13247
13399
|
console.log("[Sphere.import] Modules initialized");
|
|
13248
13400
|
if (!options.nametag) {
|
|
13401
|
+
progress?.({ step: "recovering_nametag", message: "Recovering nametag..." });
|
|
13249
13402
|
console.log("[Sphere.import] Recovering nametag from transport...");
|
|
13250
13403
|
await sphere.recoverNametagFromTransport();
|
|
13251
13404
|
console.log("[Sphere.import] Nametag recovery done");
|
|
13405
|
+
progress?.({ step: "syncing_identity", message: "Publishing identity..." });
|
|
13252
13406
|
await sphere.syncIdentityWithTransport();
|
|
13253
13407
|
}
|
|
13408
|
+
progress?.({ step: "finalizing", message: "Finalizing wallet..." });
|
|
13254
13409
|
console.log("[Sphere.import] Finalizing wallet creation...");
|
|
13255
13410
|
await sphere.finalizeWalletCreation();
|
|
13256
13411
|
sphere._initialized = true;
|
|
@@ -13258,10 +13413,12 @@ var Sphere = class _Sphere {
|
|
|
13258
13413
|
console.log("[Sphere.import] Tracking address 0...");
|
|
13259
13414
|
await sphere.ensureAddressTracked(0);
|
|
13260
13415
|
if (options.nametag) {
|
|
13416
|
+
progress?.({ step: "registering_nametag", message: "Registering nametag..." });
|
|
13261
13417
|
console.log("[Sphere.import] Registering nametag...");
|
|
13262
13418
|
await sphere.registerNametag(options.nametag);
|
|
13263
13419
|
}
|
|
13264
13420
|
if (sphere._tokenStorageProviders.size > 0) {
|
|
13421
|
+
progress?.({ step: "syncing_tokens", message: "Syncing tokens..." });
|
|
13265
13422
|
try {
|
|
13266
13423
|
const syncResult = await sphere._payments.sync();
|
|
13267
13424
|
console.log(`[Sphere.import] Auto-sync: +${syncResult.added} -${syncResult.removed}`);
|
|
@@ -13269,6 +13426,19 @@ var Sphere = class _Sphere {
|
|
|
13269
13426
|
console.warn("[Sphere.import] Auto-sync failed (non-fatal):", err);
|
|
13270
13427
|
}
|
|
13271
13428
|
}
|
|
13429
|
+
if (options.discoverAddresses !== false && sphere._transport.discoverAddresses) {
|
|
13430
|
+
progress?.({ step: "discovering_addresses", message: "Discovering addresses..." });
|
|
13431
|
+
try {
|
|
13432
|
+
const discoverOpts = typeof options.discoverAddresses === "object" ? { ...options.discoverAddresses, autoTrack: options.discoverAddresses.autoTrack ?? true } : { autoTrack: true };
|
|
13433
|
+
const result = await sphere.discoverAddresses(discoverOpts);
|
|
13434
|
+
if (result.addresses.length > 0) {
|
|
13435
|
+
console.log(`[Sphere.import] Address discovery: found ${result.addresses.length} address(es)`);
|
|
13436
|
+
}
|
|
13437
|
+
} catch (err) {
|
|
13438
|
+
console.warn("[Sphere.import] Address discovery failed (non-fatal):", err);
|
|
13439
|
+
}
|
|
13440
|
+
}
|
|
13441
|
+
progress?.({ step: "complete", message: "Import complete" });
|
|
13272
13442
|
console.log("[Sphere.import] Import complete");
|
|
13273
13443
|
return sphere;
|
|
13274
13444
|
}
|
|
@@ -13682,55 +13852,44 @@ var Sphere = class _Sphere {
|
|
|
13682
13852
|
* ```
|
|
13683
13853
|
*/
|
|
13684
13854
|
static async importFromJSON(options) {
|
|
13855
|
+
const { jsonContent, password, ...baseOptions } = options;
|
|
13685
13856
|
try {
|
|
13686
|
-
const data = JSON.parse(
|
|
13857
|
+
const data = JSON.parse(jsonContent);
|
|
13687
13858
|
if (data.version !== "1.0" || data.type !== "sphere-wallet") {
|
|
13688
13859
|
return { success: false, error: "Invalid wallet format" };
|
|
13689
13860
|
}
|
|
13690
13861
|
let mnemonic = data.mnemonic;
|
|
13691
13862
|
let masterKey = data.wallet.masterPrivateKey;
|
|
13692
|
-
if (data.encrypted &&
|
|
13863
|
+
if (data.encrypted && password) {
|
|
13693
13864
|
if (mnemonic) {
|
|
13694
|
-
const decrypted = decryptSimple(mnemonic,
|
|
13865
|
+
const decrypted = decryptSimple(mnemonic, password);
|
|
13695
13866
|
if (!decrypted) {
|
|
13696
13867
|
return { success: false, error: "Failed to decrypt mnemonic - wrong password?" };
|
|
13697
13868
|
}
|
|
13698
13869
|
mnemonic = decrypted;
|
|
13699
13870
|
}
|
|
13700
13871
|
if (masterKey) {
|
|
13701
|
-
const decrypted = decryptSimple(masterKey,
|
|
13872
|
+
const decrypted = decryptSimple(masterKey, password);
|
|
13702
13873
|
if (!decrypted) {
|
|
13703
13874
|
return { success: false, error: "Failed to decrypt master key - wrong password?" };
|
|
13704
13875
|
}
|
|
13705
13876
|
masterKey = decrypted;
|
|
13706
13877
|
}
|
|
13707
|
-
} else if (data.encrypted && !
|
|
13878
|
+
} else if (data.encrypted && !password) {
|
|
13708
13879
|
return { success: false, error: "Password required for encrypted wallet" };
|
|
13709
13880
|
}
|
|
13710
13881
|
const basePath = data.wallet.descriptorPath ? `m/${data.wallet.descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13711
13882
|
if (mnemonic) {
|
|
13712
|
-
await _Sphere.import({
|
|
13713
|
-
mnemonic,
|
|
13714
|
-
basePath,
|
|
13715
|
-
storage: options.storage,
|
|
13716
|
-
transport: options.transport,
|
|
13717
|
-
oracle: options.oracle,
|
|
13718
|
-
tokenStorage: options.tokenStorage,
|
|
13719
|
-
l1: options.l1
|
|
13720
|
-
});
|
|
13883
|
+
await _Sphere.import({ ...baseOptions, mnemonic, basePath });
|
|
13721
13884
|
return { success: true, mnemonic };
|
|
13722
13885
|
}
|
|
13723
13886
|
if (masterKey) {
|
|
13724
13887
|
await _Sphere.import({
|
|
13888
|
+
...baseOptions,
|
|
13725
13889
|
masterKey,
|
|
13726
13890
|
chainCode: data.wallet.chainCode,
|
|
13727
13891
|
basePath,
|
|
13728
|
-
derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
|
|
13729
|
-
storage: options.storage,
|
|
13730
|
-
transport: options.transport,
|
|
13731
|
-
oracle: options.oracle,
|
|
13732
|
-
tokenStorage: options.tokenStorage,
|
|
13733
|
-
l1: options.l1
|
|
13892
|
+
derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
|
|
13734
13893
|
});
|
|
13735
13894
|
return { success: true };
|
|
13736
13895
|
}
|
|
@@ -13773,7 +13932,7 @@ var Sphere = class _Sphere {
|
|
|
13773
13932
|
* ```
|
|
13774
13933
|
*/
|
|
13775
13934
|
static async importFromLegacyFile(options) {
|
|
13776
|
-
const { fileContent, fileName, password, onDecryptProgress } = options;
|
|
13935
|
+
const { fileContent, fileName, password, onDecryptProgress, ...baseOptions } = options;
|
|
13777
13936
|
const fileType = _Sphere.detectLegacyFileType(fileName, fileContent);
|
|
13778
13937
|
if (fileType === "unknown") {
|
|
13779
13938
|
return { success: false, error: "Unknown file format" };
|
|
@@ -13783,15 +13942,7 @@ var Sphere = class _Sphere {
|
|
|
13783
13942
|
if (!_Sphere.validateMnemonic(mnemonic)) {
|
|
13784
13943
|
return { success: false, error: "Invalid mnemonic phrase" };
|
|
13785
13944
|
}
|
|
13786
|
-
const sphere = await _Sphere.import({
|
|
13787
|
-
mnemonic,
|
|
13788
|
-
storage: options.storage,
|
|
13789
|
-
transport: options.transport,
|
|
13790
|
-
oracle: options.oracle,
|
|
13791
|
-
tokenStorage: options.tokenStorage,
|
|
13792
|
-
nametag: options.nametag,
|
|
13793
|
-
l1: options.l1
|
|
13794
|
-
});
|
|
13945
|
+
const sphere = await _Sphere.import({ ...baseOptions, mnemonic });
|
|
13795
13946
|
return { success: true, sphere, mnemonic };
|
|
13796
13947
|
}
|
|
13797
13948
|
if (fileType === "dat") {
|
|
@@ -13811,16 +13962,11 @@ var Sphere = class _Sphere {
|
|
|
13811
13962
|
const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
|
|
13812
13963
|
const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13813
13964
|
const sphere = await _Sphere.import({
|
|
13965
|
+
...baseOptions,
|
|
13814
13966
|
masterKey,
|
|
13815
13967
|
chainCode,
|
|
13816
13968
|
basePath,
|
|
13817
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13818
|
-
storage: options.storage,
|
|
13819
|
-
transport: options.transport,
|
|
13820
|
-
oracle: options.oracle,
|
|
13821
|
-
tokenStorage: options.tokenStorage,
|
|
13822
|
-
nametag: options.nametag,
|
|
13823
|
-
l1: options.l1
|
|
13969
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13824
13970
|
});
|
|
13825
13971
|
return { success: true, sphere };
|
|
13826
13972
|
}
|
|
@@ -13843,16 +13989,11 @@ var Sphere = class _Sphere {
|
|
|
13843
13989
|
const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
|
|
13844
13990
|
const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
|
|
13845
13991
|
const sphere = await _Sphere.import({
|
|
13992
|
+
...baseOptions,
|
|
13846
13993
|
masterKey,
|
|
13847
13994
|
chainCode,
|
|
13848
13995
|
basePath,
|
|
13849
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13850
|
-
storage: options.storage,
|
|
13851
|
-
transport: options.transport,
|
|
13852
|
-
oracle: options.oracle,
|
|
13853
|
-
tokenStorage: options.tokenStorage,
|
|
13854
|
-
nametag: options.nametag,
|
|
13855
|
-
l1: options.l1
|
|
13996
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13856
13997
|
});
|
|
13857
13998
|
return { success: true, sphere };
|
|
13858
13999
|
}
|
|
@@ -13866,13 +14007,9 @@ var Sphere = class _Sphere {
|
|
|
13866
14007
|
}
|
|
13867
14008
|
if (parsed.type === "sphere-wallet") {
|
|
13868
14009
|
const result = await _Sphere.importFromJSON({
|
|
14010
|
+
...baseOptions,
|
|
13869
14011
|
jsonContent: content,
|
|
13870
|
-
password
|
|
13871
|
-
storage: options.storage,
|
|
13872
|
-
transport: options.transport,
|
|
13873
|
-
oracle: options.oracle,
|
|
13874
|
-
tokenStorage: options.tokenStorage,
|
|
13875
|
-
l1: options.l1
|
|
14012
|
+
password
|
|
13876
14013
|
});
|
|
13877
14014
|
if (result.success) {
|
|
13878
14015
|
const sphere2 = _Sphere.getInstance();
|
|
@@ -13914,29 +14051,15 @@ var Sphere = class _Sphere {
|
|
|
13914
14051
|
const isBIP32 = derivationMode === "bip32" || !!chainCode;
|
|
13915
14052
|
const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
|
|
13916
14053
|
if (mnemonic) {
|
|
13917
|
-
const sphere2 = await _Sphere.import({
|
|
13918
|
-
mnemonic,
|
|
13919
|
-
basePath,
|
|
13920
|
-
storage: options.storage,
|
|
13921
|
-
transport: options.transport,
|
|
13922
|
-
oracle: options.oracle,
|
|
13923
|
-
tokenStorage: options.tokenStorage,
|
|
13924
|
-
nametag: options.nametag,
|
|
13925
|
-
l1: options.l1
|
|
13926
|
-
});
|
|
14054
|
+
const sphere2 = await _Sphere.import({ ...baseOptions, mnemonic, basePath });
|
|
13927
14055
|
return { success: true, sphere: sphere2, mnemonic };
|
|
13928
14056
|
}
|
|
13929
14057
|
const sphere = await _Sphere.import({
|
|
14058
|
+
...baseOptions,
|
|
13930
14059
|
masterKey,
|
|
13931
14060
|
chainCode,
|
|
13932
14061
|
basePath,
|
|
13933
|
-
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13934
|
-
storage: options.storage,
|
|
13935
|
-
transport: options.transport,
|
|
13936
|
-
oracle: options.oracle,
|
|
13937
|
-
tokenStorage: options.tokenStorage,
|
|
13938
|
-
nametag: options.nametag,
|
|
13939
|
-
l1: options.l1
|
|
14062
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
|
|
13940
14063
|
});
|
|
13941
14064
|
return { success: true, sphere };
|
|
13942
14065
|
}
|
|
@@ -14184,6 +14307,23 @@ var Sphere = class _Sphere {
|
|
|
14184
14307
|
await provider.initialize();
|
|
14185
14308
|
}
|
|
14186
14309
|
await this.reinitializeModulesForNewAddress();
|
|
14310
|
+
this.emitEvent("identity:changed", {
|
|
14311
|
+
l1Address: this._identity.l1Address,
|
|
14312
|
+
directAddress: this._identity.directAddress,
|
|
14313
|
+
chainPubkey: this._identity.chainPubkey,
|
|
14314
|
+
nametag: this._identity.nametag,
|
|
14315
|
+
addressIndex: index
|
|
14316
|
+
});
|
|
14317
|
+
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14318
|
+
this.postSwitchSync(index, newNametag).catch((err) => {
|
|
14319
|
+
console.warn(`[Sphere] Post-switch sync failed for address ${index}:`, err);
|
|
14320
|
+
});
|
|
14321
|
+
}
|
|
14322
|
+
/**
|
|
14323
|
+
* Background transport sync and nametag operations after address switch.
|
|
14324
|
+
* Runs after switchToAddress returns so L1/L3 queries can start immediately.
|
|
14325
|
+
*/
|
|
14326
|
+
async postSwitchSync(index, newNametag) {
|
|
14187
14327
|
if (!newNametag) {
|
|
14188
14328
|
await this.syncIdentityWithTransport();
|
|
14189
14329
|
}
|
|
@@ -14206,7 +14346,7 @@ var Sphere = class _Sphere {
|
|
|
14206
14346
|
nametag: newNametag,
|
|
14207
14347
|
addressIndex: index
|
|
14208
14348
|
});
|
|
14209
|
-
} else if (this._identity
|
|
14349
|
+
} else if (this._identity?.nametag && !this._payments.hasNametag()) {
|
|
14210
14350
|
console.log(`[Sphere] Nametag @${this._identity.nametag} has no token after switch, minting...`);
|
|
14211
14351
|
try {
|
|
14212
14352
|
const result = await this.mintNametag(this._identity.nametag);
|
|
@@ -14219,14 +14359,6 @@ var Sphere = class _Sphere {
|
|
|
14219
14359
|
console.warn(`[Sphere] Nametag token mint failed after switch:`, err);
|
|
14220
14360
|
}
|
|
14221
14361
|
}
|
|
14222
|
-
this.emitEvent("identity:changed", {
|
|
14223
|
-
l1Address: this._identity.l1Address,
|
|
14224
|
-
directAddress: this._identity.directAddress,
|
|
14225
|
-
chainPubkey: this._identity.chainPubkey,
|
|
14226
|
-
nametag: this._identity.nametag,
|
|
14227
|
-
addressIndex: index
|
|
14228
|
-
});
|
|
14229
|
-
console.log(`[Sphere] Switched to address ${index}:`, this._identity.l1Address);
|
|
14230
14362
|
}
|
|
14231
14363
|
/**
|
|
14232
14364
|
* Re-initialize modules after address switch
|
|
@@ -14433,6 +14565,98 @@ var Sphere = class _Sphere {
|
|
|
14433
14565
|
await this.persistTrackedAddresses();
|
|
14434
14566
|
await this.persistAddressNametags();
|
|
14435
14567
|
}
|
|
14568
|
+
/**
|
|
14569
|
+
* Discover previously used HD addresses.
|
|
14570
|
+
*
|
|
14571
|
+
* Primary: queries Nostr relay for identity binding events (fast, single batch query).
|
|
14572
|
+
* Secondary: runs L1 balance scan to find legacy addresses with no binding event.
|
|
14573
|
+
*
|
|
14574
|
+
* @example
|
|
14575
|
+
* ```ts
|
|
14576
|
+
* const result = await sphere.discoverAddresses();
|
|
14577
|
+
* console.log(`Found ${result.addresses.length} addresses`);
|
|
14578
|
+
*
|
|
14579
|
+
* // With auto-tracking
|
|
14580
|
+
* await sphere.discoverAddresses({ autoTrack: true });
|
|
14581
|
+
* ```
|
|
14582
|
+
*/
|
|
14583
|
+
async discoverAddresses(options = {}) {
|
|
14584
|
+
this.ensureReady();
|
|
14585
|
+
if (!this._masterKey) {
|
|
14586
|
+
throw new Error("Address discovery requires HD master key");
|
|
14587
|
+
}
|
|
14588
|
+
if (!this._transport.discoverAddresses) {
|
|
14589
|
+
throw new Error("Transport provider does not support address discovery");
|
|
14590
|
+
}
|
|
14591
|
+
const includeL1Scan = options.includeL1Scan ?? true;
|
|
14592
|
+
const transportResult = await discoverAddressesImpl(
|
|
14593
|
+
(index) => {
|
|
14594
|
+
const addrInfo = this._deriveAddressInternal(index, false);
|
|
14595
|
+
return {
|
|
14596
|
+
transportPubkey: addrInfo.publicKey.slice(2),
|
|
14597
|
+
// x-only 32 bytes
|
|
14598
|
+
chainPubkey: addrInfo.publicKey,
|
|
14599
|
+
l1Address: addrInfo.address,
|
|
14600
|
+
directAddress: ""
|
|
14601
|
+
// not needed for discovery query
|
|
14602
|
+
};
|
|
14603
|
+
},
|
|
14604
|
+
(pubkeys) => this._transport.discoverAddresses(pubkeys),
|
|
14605
|
+
options
|
|
14606
|
+
);
|
|
14607
|
+
if (includeL1Scan) {
|
|
14608
|
+
try {
|
|
14609
|
+
const l1Result = await this.scanAddresses({
|
|
14610
|
+
maxAddresses: options.maxAddresses,
|
|
14611
|
+
gapLimit: options.gapLimit,
|
|
14612
|
+
signal: options.signal,
|
|
14613
|
+
onProgress: options.onProgress ? (p) => options.onProgress({
|
|
14614
|
+
currentBatch: 0,
|
|
14615
|
+
totalBatches: 0,
|
|
14616
|
+
discoveredCount: p.foundCount,
|
|
14617
|
+
currentGap: p.currentGap,
|
|
14618
|
+
phase: "l1"
|
|
14619
|
+
}) : void 0
|
|
14620
|
+
});
|
|
14621
|
+
for (const l1Addr of l1Result.addresses) {
|
|
14622
|
+
if (l1Addr.isChange) continue;
|
|
14623
|
+
const existing = transportResult.addresses.find((a) => a.index === l1Addr.index);
|
|
14624
|
+
if (existing) {
|
|
14625
|
+
existing.l1Balance = l1Addr.balance;
|
|
14626
|
+
existing.source = "both";
|
|
14627
|
+
if (!existing.nametag && l1Addr.nametag) {
|
|
14628
|
+
existing.nametag = l1Addr.nametag;
|
|
14629
|
+
}
|
|
14630
|
+
} else {
|
|
14631
|
+
const addrInfo = this._deriveAddressInternal(l1Addr.index, false);
|
|
14632
|
+
transportResult.addresses.push({
|
|
14633
|
+
index: l1Addr.index,
|
|
14634
|
+
l1Address: l1Addr.address,
|
|
14635
|
+
directAddress: "",
|
|
14636
|
+
chainPubkey: addrInfo.publicKey,
|
|
14637
|
+
nametag: l1Addr.nametag,
|
|
14638
|
+
l1Balance: l1Addr.balance,
|
|
14639
|
+
source: "l1"
|
|
14640
|
+
});
|
|
14641
|
+
}
|
|
14642
|
+
}
|
|
14643
|
+
transportResult.addresses.sort((a, b) => a.index - b.index);
|
|
14644
|
+
} catch (err) {
|
|
14645
|
+
console.warn("[Sphere] L1 scan failed during discovery (non-fatal):", err);
|
|
14646
|
+
}
|
|
14647
|
+
}
|
|
14648
|
+
if (options.autoTrack && transportResult.addresses.length > 0) {
|
|
14649
|
+
await this.trackScannedAddresses(
|
|
14650
|
+
transportResult.addresses.map((a) => ({
|
|
14651
|
+
index: a.index,
|
|
14652
|
+
// Preserve existing hidden state; default to false for newly discovered
|
|
14653
|
+
hidden: this._trackedAddresses.get(a.index)?.hidden ?? false,
|
|
14654
|
+
nametag: a.nametag
|
|
14655
|
+
}))
|
|
14656
|
+
);
|
|
14657
|
+
}
|
|
14658
|
+
return transportResult;
|
|
14659
|
+
}
|
|
14436
14660
|
// ===========================================================================
|
|
14437
14661
|
// Public Methods - Status
|
|
14438
14662
|
// ===========================================================================
|
|
@@ -15004,6 +15228,17 @@ var Sphere = class _Sphere {
|
|
|
15004
15228
|
return;
|
|
15005
15229
|
}
|
|
15006
15230
|
}
|
|
15231
|
+
const needsUpdate = !existing.directAddress || !existing.l1Address || !existing.chainPubkey || this._identity?.nametag && !existing.nametag;
|
|
15232
|
+
if (needsUpdate) {
|
|
15233
|
+
console.log("[Sphere] Existing binding incomplete, re-publishing with full data");
|
|
15234
|
+
await this._transport.publishIdentityBinding(
|
|
15235
|
+
this._identity.chainPubkey,
|
|
15236
|
+
this._identity.l1Address,
|
|
15237
|
+
this._identity.directAddress || "",
|
|
15238
|
+
this._identity?.nametag || existing.nametag || void 0
|
|
15239
|
+
);
|
|
15240
|
+
return;
|
|
15241
|
+
}
|
|
15007
15242
|
console.log("[Sphere] Existing binding found, skipping re-publish");
|
|
15008
15243
|
return;
|
|
15009
15244
|
}
|
|
@@ -15492,6 +15727,7 @@ function formatAmount(amount, options = {}) {
|
|
|
15492
15727
|
init_bech32();
|
|
15493
15728
|
|
|
15494
15729
|
// core/network-health.ts
|
|
15730
|
+
init_constants();
|
|
15495
15731
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
15496
15732
|
async function checkNetworkHealth(network = "testnet", options) {
|
|
15497
15733
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -15677,6 +15913,9 @@ async function runCustomCheck(name, checkFn, timeoutMs) {
|
|
|
15677
15913
|
}
|
|
15678
15914
|
}
|
|
15679
15915
|
|
|
15916
|
+
// index.ts
|
|
15917
|
+
init_constants();
|
|
15918
|
+
|
|
15680
15919
|
// types/payment-session.ts
|
|
15681
15920
|
function createPaymentSession(params) {
|
|
15682
15921
|
const now = Date.now();
|
|
@@ -15748,6 +15987,9 @@ var SphereError = class extends Error {
|
|
|
15748
15987
|
}
|
|
15749
15988
|
};
|
|
15750
15989
|
|
|
15990
|
+
// index.ts
|
|
15991
|
+
init_constants();
|
|
15992
|
+
|
|
15751
15993
|
// validation/token-validator.ts
|
|
15752
15994
|
var TokenValidator = class {
|
|
15753
15995
|
aggregatorClient = null;
|
|
@@ -16076,6 +16318,7 @@ function createTokenValidator(options) {
|
|
|
16076
16318
|
var import_nostr_js_sdk4 = require("@unicitylabs/nostr-js-sdk");
|
|
16077
16319
|
|
|
16078
16320
|
// price/CoinGeckoPriceProvider.ts
|
|
16321
|
+
init_constants();
|
|
16079
16322
|
var CoinGeckoPriceProvider = class {
|
|
16080
16323
|
platform = "coingecko";
|
|
16081
16324
|
cache = /* @__PURE__ */ new Map();
|