@unicitylabs/sphere-sdk 0.2.1 → 0.2.3
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/README.md +22 -69
- package/dist/core/index.cjs +944 -465
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +127 -6
- package/dist/core/index.d.ts +127 -6
- package/dist/core/index.js +833 -351
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +115 -19
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +115 -19
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +3 -1
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +3 -1
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +85 -17
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +22 -0
- package/dist/impl/nodejs/index.d.ts +22 -0
- package/dist/impl/nodejs/index.js +85 -17
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +1083 -644
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -6
- package/dist/index.d.ts +118 -6
- package/dist/index.js +993 -554
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +18 -0
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.d.cts +4 -0
- package/dist/l1/index.d.ts +4 -0
- package/dist/l1/index.js +18 -0
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
1
3
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
4
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
5
|
}) : x)(function(x) {
|
|
4
6
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
8
|
});
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
7
16
|
|
|
8
17
|
// core/bech32.ts
|
|
9
|
-
var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
10
|
-
var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
11
18
|
function convertBits(data, fromBits, toBits, pad) {
|
|
12
19
|
let acc = 0;
|
|
13
20
|
let bits = 0;
|
|
@@ -114,7 +121,15 @@ function getAddressHrp(addr) {
|
|
|
114
121
|
const result = decodeBech32(addr);
|
|
115
122
|
return result?.hrp ?? null;
|
|
116
123
|
}
|
|
117
|
-
var
|
|
124
|
+
var CHARSET, GENERATOR, createBech32;
|
|
125
|
+
var init_bech32 = __esm({
|
|
126
|
+
"core/bech32.ts"() {
|
|
127
|
+
"use strict";
|
|
128
|
+
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
129
|
+
GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
130
|
+
createBech32 = encodeBech32;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
118
133
|
|
|
119
134
|
// l1/addressToScriptHash.ts
|
|
120
135
|
import CryptoJS from "crypto-js";
|
|
@@ -128,224 +143,30 @@ function addressToScriptHash(address) {
|
|
|
128
143
|
const sha = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(scriptHex)).toString();
|
|
129
144
|
return sha.match(/../g).reverse().join("");
|
|
130
145
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
import elliptic from "elliptic";
|
|
136
|
-
var ec = new elliptic.ec("secp256k1");
|
|
137
|
-
var CURVE_ORDER = BigInt(
|
|
138
|
-
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
|
|
139
|
-
);
|
|
140
|
-
var DEFAULT_DERIVATION_PATH = "m/44'/0'/0'";
|
|
141
|
-
function generateMnemonic2(strength = 128) {
|
|
142
|
-
return bip39.generateMnemonic(strength);
|
|
143
|
-
}
|
|
144
|
-
function validateMnemonic2(mnemonic) {
|
|
145
|
-
return bip39.validateMnemonic(mnemonic);
|
|
146
|
-
}
|
|
147
|
-
async function mnemonicToSeed2(mnemonic, passphrase = "") {
|
|
148
|
-
const seedBuffer = await bip39.mnemonicToSeed(mnemonic, passphrase);
|
|
149
|
-
return Buffer.from(seedBuffer).toString("hex");
|
|
150
|
-
}
|
|
151
|
-
function mnemonicToSeedSync2(mnemonic, passphrase = "") {
|
|
152
|
-
const seedBuffer = bip39.mnemonicToSeedSync(mnemonic, passphrase);
|
|
153
|
-
return Buffer.from(seedBuffer).toString("hex");
|
|
154
|
-
}
|
|
155
|
-
function mnemonicToEntropy2(mnemonic) {
|
|
156
|
-
return bip39.mnemonicToEntropy(mnemonic);
|
|
157
|
-
}
|
|
158
|
-
function entropyToMnemonic2(entropy) {
|
|
159
|
-
return bip39.entropyToMnemonic(entropy);
|
|
160
|
-
}
|
|
161
|
-
function generateMasterKey(seedHex) {
|
|
162
|
-
const I = CryptoJS2.HmacSHA512(
|
|
163
|
-
CryptoJS2.enc.Hex.parse(seedHex),
|
|
164
|
-
CryptoJS2.enc.Utf8.parse("Bitcoin seed")
|
|
165
|
-
).toString();
|
|
166
|
-
const IL = I.substring(0, 64);
|
|
167
|
-
const IR = I.substring(64);
|
|
168
|
-
const masterKeyBigInt = BigInt("0x" + IL);
|
|
169
|
-
if (masterKeyBigInt === 0n || masterKeyBigInt >= CURVE_ORDER) {
|
|
170
|
-
throw new Error("Invalid master key generated");
|
|
171
|
-
}
|
|
172
|
-
return {
|
|
173
|
-
privateKey: IL,
|
|
174
|
-
chainCode: IR
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function deriveChildKey(parentPrivKey, parentChainCode, index) {
|
|
178
|
-
const isHardened = index >= 2147483648;
|
|
179
|
-
let data;
|
|
180
|
-
if (isHardened) {
|
|
181
|
-
const indexHex = index.toString(16).padStart(8, "0");
|
|
182
|
-
data = "00" + parentPrivKey + indexHex;
|
|
183
|
-
} else {
|
|
184
|
-
const keyPair = ec.keyFromPrivate(parentPrivKey, "hex");
|
|
185
|
-
const compressedPubKey = keyPair.getPublic(true, "hex");
|
|
186
|
-
const indexHex = index.toString(16).padStart(8, "0");
|
|
187
|
-
data = compressedPubKey + indexHex;
|
|
188
|
-
}
|
|
189
|
-
const I = CryptoJS2.HmacSHA512(
|
|
190
|
-
CryptoJS2.enc.Hex.parse(data),
|
|
191
|
-
CryptoJS2.enc.Hex.parse(parentChainCode)
|
|
192
|
-
).toString();
|
|
193
|
-
const IL = I.substring(0, 64);
|
|
194
|
-
const IR = I.substring(64);
|
|
195
|
-
const ilBigInt = BigInt("0x" + IL);
|
|
196
|
-
const parentKeyBigInt = BigInt("0x" + parentPrivKey);
|
|
197
|
-
if (ilBigInt >= CURVE_ORDER) {
|
|
198
|
-
throw new Error("Invalid key: IL >= curve order");
|
|
199
|
-
}
|
|
200
|
-
const childKeyBigInt = (ilBigInt + parentKeyBigInt) % CURVE_ORDER;
|
|
201
|
-
if (childKeyBigInt === 0n) {
|
|
202
|
-
throw new Error("Invalid key: child key is zero");
|
|
203
|
-
}
|
|
204
|
-
const childPrivKey = childKeyBigInt.toString(16).padStart(64, "0");
|
|
205
|
-
return {
|
|
206
|
-
privateKey: childPrivKey,
|
|
207
|
-
chainCode: IR
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
function deriveKeyAtPath(masterPrivKey, masterChainCode, path) {
|
|
211
|
-
const pathParts = path.replace("m/", "").split("/");
|
|
212
|
-
let currentKey = masterPrivKey;
|
|
213
|
-
let currentChainCode = masterChainCode;
|
|
214
|
-
for (const part of pathParts) {
|
|
215
|
-
const isHardened = part.endsWith("'") || part.endsWith("h");
|
|
216
|
-
const indexStr = part.replace(/['h]$/, "");
|
|
217
|
-
let index = parseInt(indexStr, 10);
|
|
218
|
-
if (isHardened) {
|
|
219
|
-
index += 2147483648;
|
|
220
|
-
}
|
|
221
|
-
const derived = deriveChildKey(currentKey, currentChainCode, index);
|
|
222
|
-
currentKey = derived.privateKey;
|
|
223
|
-
currentChainCode = derived.chainCode;
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
privateKey: currentKey,
|
|
227
|
-
chainCode: currentChainCode
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
function getPublicKey(privateKey, compressed = true) {
|
|
231
|
-
const keyPair = ec.keyFromPrivate(privateKey, "hex");
|
|
232
|
-
return keyPair.getPublic(compressed, "hex");
|
|
233
|
-
}
|
|
234
|
-
function createKeyPair(privateKey) {
|
|
235
|
-
return {
|
|
236
|
-
privateKey,
|
|
237
|
-
publicKey: getPublicKey(privateKey)
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
function sha256(data, inputEncoding = "hex") {
|
|
241
|
-
const parsed = inputEncoding === "hex" ? CryptoJS2.enc.Hex.parse(data) : CryptoJS2.enc.Utf8.parse(data);
|
|
242
|
-
return CryptoJS2.SHA256(parsed).toString();
|
|
243
|
-
}
|
|
244
|
-
function ripemd160(data, inputEncoding = "hex") {
|
|
245
|
-
const parsed = inputEncoding === "hex" ? CryptoJS2.enc.Hex.parse(data) : CryptoJS2.enc.Utf8.parse(data);
|
|
246
|
-
return CryptoJS2.RIPEMD160(parsed).toString();
|
|
247
|
-
}
|
|
248
|
-
function hash160(data) {
|
|
249
|
-
const sha = sha256(data, "hex");
|
|
250
|
-
return ripemd160(sha, "hex");
|
|
251
|
-
}
|
|
252
|
-
function doubleSha256(data, inputEncoding = "hex") {
|
|
253
|
-
const first = sha256(data, inputEncoding);
|
|
254
|
-
return sha256(first, "hex");
|
|
255
|
-
}
|
|
256
|
-
var computeHash160 = hash160;
|
|
257
|
-
function hash160ToBytes(hash160Hex) {
|
|
258
|
-
const matches = hash160Hex.match(/../g);
|
|
259
|
-
if (!matches) return new Uint8Array(0);
|
|
260
|
-
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
261
|
-
}
|
|
262
|
-
function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
263
|
-
const pubKeyHash = hash160(publicKey);
|
|
264
|
-
const programBytes = hash160ToBytes(pubKeyHash);
|
|
265
|
-
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
266
|
-
}
|
|
267
|
-
function privateKeyToAddressInfo(privateKey, prefix = "alpha") {
|
|
268
|
-
const publicKey = getPublicKey(privateKey);
|
|
269
|
-
const address = publicKeyToAddress(publicKey, prefix);
|
|
270
|
-
return { address, publicKey };
|
|
271
|
-
}
|
|
272
|
-
function hexToBytes(hex) {
|
|
273
|
-
const matches = hex.match(/../g);
|
|
274
|
-
if (!matches) {
|
|
275
|
-
return new Uint8Array(0);
|
|
276
|
-
}
|
|
277
|
-
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
278
|
-
}
|
|
279
|
-
function bytesToHex2(bytes) {
|
|
280
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
281
|
-
}
|
|
282
|
-
function randomBytes(length) {
|
|
283
|
-
const words = CryptoJS2.lib.WordArray.random(length);
|
|
284
|
-
return words.toString(CryptoJS2.enc.Hex);
|
|
285
|
-
}
|
|
286
|
-
async function identityFromMnemonic(mnemonic, passphrase = "") {
|
|
287
|
-
if (!validateMnemonic2(mnemonic)) {
|
|
288
|
-
throw new Error("Invalid mnemonic phrase");
|
|
146
|
+
var init_addressToScriptHash = __esm({
|
|
147
|
+
"l1/addressToScriptHash.ts"() {
|
|
148
|
+
"use strict";
|
|
149
|
+
init_bech32();
|
|
289
150
|
}
|
|
290
|
-
|
|
291
|
-
return generateMasterKey(seedHex);
|
|
292
|
-
}
|
|
293
|
-
function identityFromMnemonicSync(mnemonic, passphrase = "") {
|
|
294
|
-
if (!validateMnemonic2(mnemonic)) {
|
|
295
|
-
throw new Error("Invalid mnemonic phrase");
|
|
296
|
-
}
|
|
297
|
-
const seedHex = mnemonicToSeedSync2(mnemonic, passphrase);
|
|
298
|
-
return generateMasterKey(seedHex);
|
|
299
|
-
}
|
|
300
|
-
function deriveAddressInfo(masterKey, basePath, index, isChange = false, prefix = "alpha") {
|
|
301
|
-
const chain = isChange ? 1 : 0;
|
|
302
|
-
const fullPath = `${basePath}/${chain}/${index}`;
|
|
303
|
-
const derived = deriveKeyAtPath(masterKey.privateKey, masterKey.chainCode, fullPath);
|
|
304
|
-
const publicKey = getPublicKey(derived.privateKey);
|
|
305
|
-
const address = publicKeyToAddress(publicKey, prefix);
|
|
306
|
-
return {
|
|
307
|
-
privateKey: derived.privateKey,
|
|
308
|
-
publicKey,
|
|
309
|
-
address,
|
|
310
|
-
path: fullPath,
|
|
311
|
-
index
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
function generateAddressInfo(privateKey, index, path, prefix = "alpha") {
|
|
315
|
-
const { address, publicKey } = privateKeyToAddressInfo(privateKey, prefix);
|
|
316
|
-
return {
|
|
317
|
-
privateKey,
|
|
318
|
-
publicKey,
|
|
319
|
-
address,
|
|
320
|
-
path,
|
|
321
|
-
index
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// l1/crypto.ts
|
|
326
|
-
import CryptoJS3 from "crypto-js";
|
|
327
|
-
|
|
328
|
-
// l1/address.ts
|
|
329
|
-
import CryptoJS4 from "crypto-js";
|
|
151
|
+
});
|
|
330
152
|
|
|
331
153
|
// l1/network.ts
|
|
332
|
-
var
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
var CONNECTION_TIMEOUT = 3e4;
|
|
154
|
+
var network_exports = {};
|
|
155
|
+
__export(network_exports, {
|
|
156
|
+
broadcast: () => broadcast,
|
|
157
|
+
connect: () => connect,
|
|
158
|
+
disconnect: () => disconnect,
|
|
159
|
+
getBalance: () => getBalance,
|
|
160
|
+
getBlockHeader: () => getBlockHeader,
|
|
161
|
+
getCurrentBlockHeight: () => getCurrentBlockHeight,
|
|
162
|
+
getTransaction: () => getTransaction,
|
|
163
|
+
getTransactionHistory: () => getTransactionHistory,
|
|
164
|
+
getUtxo: () => getUtxo,
|
|
165
|
+
isWebSocketConnected: () => isWebSocketConnected,
|
|
166
|
+
rpc: () => rpc,
|
|
167
|
+
subscribeBlocks: () => subscribeBlocks,
|
|
168
|
+
waitForConnection: () => waitForConnection
|
|
169
|
+
});
|
|
349
170
|
function isWebSocketConnected() {
|
|
350
171
|
return isConnected && ws !== null && ws.readyState === WebSocket.OPEN;
|
|
351
172
|
}
|
|
@@ -536,6 +357,31 @@ async function getBalance(address) {
|
|
|
536
357
|
async function broadcast(rawHex) {
|
|
537
358
|
return await rpc("blockchain.transaction.broadcast", [rawHex]);
|
|
538
359
|
}
|
|
360
|
+
async function subscribeBlocks(cb) {
|
|
361
|
+
if (!isConnected && !isConnecting) {
|
|
362
|
+
await connect();
|
|
363
|
+
}
|
|
364
|
+
if (!isWebSocketConnected()) {
|
|
365
|
+
await waitForConnection();
|
|
366
|
+
}
|
|
367
|
+
blockSubscribers.push(cb);
|
|
368
|
+
if (!isBlockSubscribed) {
|
|
369
|
+
isBlockSubscribed = true;
|
|
370
|
+
const header = await rpc("blockchain.headers.subscribe", []);
|
|
371
|
+
if (header) {
|
|
372
|
+
lastBlockHeader = header;
|
|
373
|
+
blockSubscribers.forEach((subscriber) => subscriber(header));
|
|
374
|
+
}
|
|
375
|
+
} else if (lastBlockHeader) {
|
|
376
|
+
cb(lastBlockHeader);
|
|
377
|
+
}
|
|
378
|
+
return () => {
|
|
379
|
+
const index = blockSubscribers.indexOf(cb);
|
|
380
|
+
if (index > -1) {
|
|
381
|
+
blockSubscribers.splice(index, 1);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
539
385
|
async function getTransactionHistory(address) {
|
|
540
386
|
const scriptHash = addressToScriptHash(address);
|
|
541
387
|
const result = await rpc("blockchain.scripthash.get_history", [scriptHash]);
|
|
@@ -543,45 +389,290 @@ async function getTransactionHistory(address) {
|
|
|
543
389
|
console.warn("get_history returned non-array:", result);
|
|
544
390
|
return [];
|
|
545
391
|
}
|
|
546
|
-
return result;
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
async function getTransaction(txid) {
|
|
395
|
+
return await rpc("blockchain.transaction.get", [txid, true]);
|
|
396
|
+
}
|
|
397
|
+
async function getBlockHeader(height) {
|
|
398
|
+
return await rpc("blockchain.block.header", [height, height]);
|
|
399
|
+
}
|
|
400
|
+
async function getCurrentBlockHeight() {
|
|
401
|
+
try {
|
|
402
|
+
const header = await rpc("blockchain.headers.subscribe", []);
|
|
403
|
+
return header?.height || 0;
|
|
404
|
+
} catch (err) {
|
|
405
|
+
console.error("Error getting current block height:", err);
|
|
406
|
+
return 0;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function disconnect() {
|
|
410
|
+
if (ws) {
|
|
411
|
+
intentionalClose = true;
|
|
412
|
+
ws.close();
|
|
413
|
+
ws = null;
|
|
414
|
+
}
|
|
415
|
+
isConnected = false;
|
|
416
|
+
isConnecting = false;
|
|
417
|
+
reconnectAttempts = 0;
|
|
418
|
+
isBlockSubscribed = false;
|
|
419
|
+
Object.values(pending).forEach((req) => {
|
|
420
|
+
if (req.timeoutId) clearTimeout(req.timeoutId);
|
|
421
|
+
});
|
|
422
|
+
Object.keys(pending).forEach((key) => delete pending[Number(key)]);
|
|
423
|
+
connectionCallbacks.forEach((cb) => {
|
|
424
|
+
if (cb.timeoutId) clearTimeout(cb.timeoutId);
|
|
425
|
+
});
|
|
426
|
+
connectionCallbacks.length = 0;
|
|
427
|
+
}
|
|
428
|
+
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
|
+
var init_network = __esm({
|
|
430
|
+
"l1/network.ts"() {
|
|
431
|
+
"use strict";
|
|
432
|
+
init_addressToScriptHash();
|
|
433
|
+
DEFAULT_ENDPOINT = "wss://fulcrum.unicity.network:50004";
|
|
434
|
+
ws = null;
|
|
435
|
+
isConnected = false;
|
|
436
|
+
isConnecting = false;
|
|
437
|
+
requestId = 0;
|
|
438
|
+
intentionalClose = false;
|
|
439
|
+
reconnectAttempts = 0;
|
|
440
|
+
isBlockSubscribed = false;
|
|
441
|
+
lastBlockHeader = null;
|
|
442
|
+
pending = {};
|
|
443
|
+
blockSubscribers = [];
|
|
444
|
+
connectionCallbacks = [];
|
|
445
|
+
MAX_RECONNECT_ATTEMPTS = 10;
|
|
446
|
+
BASE_DELAY = 2e3;
|
|
447
|
+
MAX_DELAY = 6e4;
|
|
448
|
+
RPC_TIMEOUT = 3e4;
|
|
449
|
+
CONNECTION_TIMEOUT = 3e4;
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// l1/index.ts
|
|
454
|
+
init_bech32();
|
|
455
|
+
init_addressToScriptHash();
|
|
456
|
+
|
|
457
|
+
// core/crypto.ts
|
|
458
|
+
init_bech32();
|
|
459
|
+
import * as bip39 from "bip39";
|
|
460
|
+
import CryptoJS2 from "crypto-js";
|
|
461
|
+
import elliptic from "elliptic";
|
|
462
|
+
var ec = new elliptic.ec("secp256k1");
|
|
463
|
+
var CURVE_ORDER = BigInt(
|
|
464
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
|
|
465
|
+
);
|
|
466
|
+
var DEFAULT_DERIVATION_PATH = "m/44'/0'/0'";
|
|
467
|
+
function generateMnemonic2(strength = 128) {
|
|
468
|
+
return bip39.generateMnemonic(strength);
|
|
469
|
+
}
|
|
470
|
+
function validateMnemonic2(mnemonic) {
|
|
471
|
+
return bip39.validateMnemonic(mnemonic);
|
|
472
|
+
}
|
|
473
|
+
async function mnemonicToSeed2(mnemonic, passphrase = "") {
|
|
474
|
+
const seedBuffer = await bip39.mnemonicToSeed(mnemonic, passphrase);
|
|
475
|
+
return Buffer.from(seedBuffer).toString("hex");
|
|
476
|
+
}
|
|
477
|
+
function mnemonicToSeedSync2(mnemonic, passphrase = "") {
|
|
478
|
+
const seedBuffer = bip39.mnemonicToSeedSync(mnemonic, passphrase);
|
|
479
|
+
return Buffer.from(seedBuffer).toString("hex");
|
|
480
|
+
}
|
|
481
|
+
function mnemonicToEntropy2(mnemonic) {
|
|
482
|
+
return bip39.mnemonicToEntropy(mnemonic);
|
|
483
|
+
}
|
|
484
|
+
function entropyToMnemonic2(entropy) {
|
|
485
|
+
return bip39.entropyToMnemonic(entropy);
|
|
486
|
+
}
|
|
487
|
+
function generateMasterKey(seedHex) {
|
|
488
|
+
const I = CryptoJS2.HmacSHA512(
|
|
489
|
+
CryptoJS2.enc.Hex.parse(seedHex),
|
|
490
|
+
CryptoJS2.enc.Utf8.parse("Bitcoin seed")
|
|
491
|
+
).toString();
|
|
492
|
+
const IL = I.substring(0, 64);
|
|
493
|
+
const IR = I.substring(64);
|
|
494
|
+
const masterKeyBigInt = BigInt("0x" + IL);
|
|
495
|
+
if (masterKeyBigInt === 0n || masterKeyBigInt >= CURVE_ORDER) {
|
|
496
|
+
throw new Error("Invalid master key generated");
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
privateKey: IL,
|
|
500
|
+
chainCode: IR
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function deriveChildKey(parentPrivKey, parentChainCode, index) {
|
|
504
|
+
const isHardened = index >= 2147483648;
|
|
505
|
+
let data;
|
|
506
|
+
if (isHardened) {
|
|
507
|
+
const indexHex = index.toString(16).padStart(8, "0");
|
|
508
|
+
data = "00" + parentPrivKey + indexHex;
|
|
509
|
+
} else {
|
|
510
|
+
const keyPair = ec.keyFromPrivate(parentPrivKey, "hex");
|
|
511
|
+
const compressedPubKey = keyPair.getPublic(true, "hex");
|
|
512
|
+
const indexHex = index.toString(16).padStart(8, "0");
|
|
513
|
+
data = compressedPubKey + indexHex;
|
|
514
|
+
}
|
|
515
|
+
const I = CryptoJS2.HmacSHA512(
|
|
516
|
+
CryptoJS2.enc.Hex.parse(data),
|
|
517
|
+
CryptoJS2.enc.Hex.parse(parentChainCode)
|
|
518
|
+
).toString();
|
|
519
|
+
const IL = I.substring(0, 64);
|
|
520
|
+
const IR = I.substring(64);
|
|
521
|
+
const ilBigInt = BigInt("0x" + IL);
|
|
522
|
+
const parentKeyBigInt = BigInt("0x" + parentPrivKey);
|
|
523
|
+
if (ilBigInt >= CURVE_ORDER) {
|
|
524
|
+
throw new Error("Invalid key: IL >= curve order");
|
|
525
|
+
}
|
|
526
|
+
const childKeyBigInt = (ilBigInt + parentKeyBigInt) % CURVE_ORDER;
|
|
527
|
+
if (childKeyBigInt === 0n) {
|
|
528
|
+
throw new Error("Invalid key: child key is zero");
|
|
529
|
+
}
|
|
530
|
+
const childPrivKey = childKeyBigInt.toString(16).padStart(64, "0");
|
|
531
|
+
return {
|
|
532
|
+
privateKey: childPrivKey,
|
|
533
|
+
chainCode: IR
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
function deriveKeyAtPath(masterPrivKey, masterChainCode, path) {
|
|
537
|
+
const pathParts = path.replace("m/", "").split("/");
|
|
538
|
+
let currentKey = masterPrivKey;
|
|
539
|
+
let currentChainCode = masterChainCode;
|
|
540
|
+
for (const part of pathParts) {
|
|
541
|
+
const isHardened = part.endsWith("'") || part.endsWith("h");
|
|
542
|
+
const indexStr = part.replace(/['h]$/, "");
|
|
543
|
+
let index = parseInt(indexStr, 10);
|
|
544
|
+
if (isHardened) {
|
|
545
|
+
index += 2147483648;
|
|
546
|
+
}
|
|
547
|
+
const derived = deriveChildKey(currentKey, currentChainCode, index);
|
|
548
|
+
currentKey = derived.privateKey;
|
|
549
|
+
currentChainCode = derived.chainCode;
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
privateKey: currentKey,
|
|
553
|
+
chainCode: currentChainCode
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function getPublicKey(privateKey, compressed = true) {
|
|
557
|
+
const keyPair = ec.keyFromPrivate(privateKey, "hex");
|
|
558
|
+
return keyPair.getPublic(compressed, "hex");
|
|
559
|
+
}
|
|
560
|
+
function createKeyPair(privateKey) {
|
|
561
|
+
return {
|
|
562
|
+
privateKey,
|
|
563
|
+
publicKey: getPublicKey(privateKey)
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function sha256(data, inputEncoding = "hex") {
|
|
567
|
+
const parsed = inputEncoding === "hex" ? CryptoJS2.enc.Hex.parse(data) : CryptoJS2.enc.Utf8.parse(data);
|
|
568
|
+
return CryptoJS2.SHA256(parsed).toString();
|
|
569
|
+
}
|
|
570
|
+
function ripemd160(data, inputEncoding = "hex") {
|
|
571
|
+
const parsed = inputEncoding === "hex" ? CryptoJS2.enc.Hex.parse(data) : CryptoJS2.enc.Utf8.parse(data);
|
|
572
|
+
return CryptoJS2.RIPEMD160(parsed).toString();
|
|
573
|
+
}
|
|
574
|
+
function hash160(data) {
|
|
575
|
+
const sha = sha256(data, "hex");
|
|
576
|
+
return ripemd160(sha, "hex");
|
|
577
|
+
}
|
|
578
|
+
function doubleSha256(data, inputEncoding = "hex") {
|
|
579
|
+
const first = sha256(data, inputEncoding);
|
|
580
|
+
return sha256(first, "hex");
|
|
581
|
+
}
|
|
582
|
+
var computeHash160 = hash160;
|
|
583
|
+
function hash160ToBytes(hash160Hex) {
|
|
584
|
+
const matches = hash160Hex.match(/../g);
|
|
585
|
+
if (!matches) return new Uint8Array(0);
|
|
586
|
+
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
587
|
+
}
|
|
588
|
+
function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
589
|
+
const pubKeyHash = hash160(publicKey);
|
|
590
|
+
const programBytes = hash160ToBytes(pubKeyHash);
|
|
591
|
+
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
592
|
+
}
|
|
593
|
+
function privateKeyToAddressInfo(privateKey, prefix = "alpha") {
|
|
594
|
+
const publicKey = getPublicKey(privateKey);
|
|
595
|
+
const address = publicKeyToAddress(publicKey, prefix);
|
|
596
|
+
return { address, publicKey };
|
|
597
|
+
}
|
|
598
|
+
function hexToBytes(hex) {
|
|
599
|
+
const matches = hex.match(/../g);
|
|
600
|
+
if (!matches) {
|
|
601
|
+
return new Uint8Array(0);
|
|
602
|
+
}
|
|
603
|
+
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
547
604
|
}
|
|
548
|
-
|
|
549
|
-
return
|
|
605
|
+
function bytesToHex2(bytes) {
|
|
606
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
550
607
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
608
|
+
function randomBytes(length) {
|
|
609
|
+
const words = CryptoJS2.lib.WordArray.random(length);
|
|
610
|
+
return words.toString(CryptoJS2.enc.Hex);
|
|
611
|
+
}
|
|
612
|
+
async function identityFromMnemonic(mnemonic, passphrase = "") {
|
|
613
|
+
if (!validateMnemonic2(mnemonic)) {
|
|
614
|
+
throw new Error("Invalid mnemonic phrase");
|
|
558
615
|
}
|
|
616
|
+
const seedHex = await mnemonicToSeed2(mnemonic, passphrase);
|
|
617
|
+
return generateMasterKey(seedHex);
|
|
559
618
|
}
|
|
560
|
-
function
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
ws.close();
|
|
564
|
-
ws = null;
|
|
619
|
+
function identityFromMnemonicSync(mnemonic, passphrase = "") {
|
|
620
|
+
if (!validateMnemonic2(mnemonic)) {
|
|
621
|
+
throw new Error("Invalid mnemonic phrase");
|
|
565
622
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
623
|
+
const seedHex = mnemonicToSeedSync2(mnemonic, passphrase);
|
|
624
|
+
return generateMasterKey(seedHex);
|
|
625
|
+
}
|
|
626
|
+
function deriveAddressInfo(masterKey, basePath, index, isChange = false, prefix = "alpha") {
|
|
627
|
+
const chain = isChange ? 1 : 0;
|
|
628
|
+
const fullPath = `${basePath}/${chain}/${index}`;
|
|
629
|
+
const derived = deriveKeyAtPath(masterKey.privateKey, masterKey.chainCode, fullPath);
|
|
630
|
+
const publicKey = getPublicKey(derived.privateKey);
|
|
631
|
+
const address = publicKeyToAddress(publicKey, prefix);
|
|
632
|
+
return {
|
|
633
|
+
privateKey: derived.privateKey,
|
|
634
|
+
publicKey,
|
|
635
|
+
address,
|
|
636
|
+
path: fullPath,
|
|
637
|
+
index
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
function generateAddressInfo(privateKey, index, path, prefix = "alpha") {
|
|
641
|
+
const { address, publicKey } = privateKeyToAddressInfo(privateKey, prefix);
|
|
642
|
+
return {
|
|
643
|
+
privateKey,
|
|
644
|
+
publicKey,
|
|
645
|
+
address,
|
|
646
|
+
path,
|
|
647
|
+
index
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// l1/crypto.ts
|
|
652
|
+
import CryptoJS3 from "crypto-js";
|
|
653
|
+
|
|
654
|
+
// l1/address.ts
|
|
655
|
+
import CryptoJS4 from "crypto-js";
|
|
656
|
+
function generateAddressFromMasterKey(masterPrivateKey, index) {
|
|
657
|
+
const derivationPath = `m/44'/0'/${index}'`;
|
|
658
|
+
const hmacInput = CryptoJS4.enc.Hex.parse(masterPrivateKey);
|
|
659
|
+
const hmacKey = CryptoJS4.enc.Utf8.parse(derivationPath);
|
|
660
|
+
const hmacOutput = CryptoJS4.HmacSHA512(hmacInput, hmacKey).toString();
|
|
661
|
+
const childPrivateKey = hmacOutput.substring(0, 64);
|
|
662
|
+
return generateAddressInfo(childPrivateKey, index, derivationPath);
|
|
578
663
|
}
|
|
579
664
|
|
|
665
|
+
// l1/index.ts
|
|
666
|
+
init_network();
|
|
667
|
+
|
|
580
668
|
// l1/tx.ts
|
|
669
|
+
init_network();
|
|
670
|
+
init_bech32();
|
|
581
671
|
import CryptoJS5 from "crypto-js";
|
|
582
672
|
import elliptic2 from "elliptic";
|
|
583
673
|
|
|
584
674
|
// l1/vesting.ts
|
|
675
|
+
init_network();
|
|
585
676
|
var VESTING_THRESHOLD = 28e4;
|
|
586
677
|
var currentBlockHeight = null;
|
|
587
678
|
var VestingClassifier = class {
|
|
@@ -800,6 +891,24 @@ var VestingClassifier = class {
|
|
|
800
891
|
tx.objectStore(this.storeName).clear();
|
|
801
892
|
}
|
|
802
893
|
}
|
|
894
|
+
/**
|
|
895
|
+
* Destroy caches and delete the IndexedDB database entirely.
|
|
896
|
+
*/
|
|
897
|
+
async destroy() {
|
|
898
|
+
this.memoryCache.clear();
|
|
899
|
+
if (this.db) {
|
|
900
|
+
this.db.close();
|
|
901
|
+
this.db = null;
|
|
902
|
+
}
|
|
903
|
+
if (typeof indexedDB !== "undefined") {
|
|
904
|
+
await new Promise((resolve) => {
|
|
905
|
+
const req = indexedDB.deleteDatabase(this.dbName);
|
|
906
|
+
req.onsuccess = () => resolve();
|
|
907
|
+
req.onerror = () => resolve();
|
|
908
|
+
req.onblocked = () => resolve();
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
}
|
|
803
912
|
};
|
|
804
913
|
var vestingClassifier = new VestingClassifier();
|
|
805
914
|
|
|
@@ -1352,7 +1461,7 @@ var L1PaymentsModule = class {
|
|
|
1352
1461
|
_transport;
|
|
1353
1462
|
constructor(config) {
|
|
1354
1463
|
this._config = {
|
|
1355
|
-
electrumUrl: config?.electrumUrl ?? "wss://fulcrum.
|
|
1464
|
+
electrumUrl: config?.electrumUrl ?? "wss://fulcrum.unicity.network:50004",
|
|
1356
1465
|
network: config?.network ?? "mainnet",
|
|
1357
1466
|
defaultFeeRate: config?.defaultFeeRate ?? 10,
|
|
1358
1467
|
enableVesting: config?.enableVesting ?? true
|
|
@@ -1384,10 +1493,17 @@ var L1PaymentsModule = class {
|
|
|
1384
1493
|
});
|
|
1385
1494
|
}
|
|
1386
1495
|
}
|
|
1387
|
-
|
|
1496
|
+
this._initialized = true;
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Ensure the Fulcrum WebSocket is connected. Called lazily before any
|
|
1500
|
+
* operation that needs the network. If the singleton is already connected
|
|
1501
|
+
* (e.g. by the address scanner), this is a no-op.
|
|
1502
|
+
*/
|
|
1503
|
+
async ensureConnected() {
|
|
1504
|
+
if (!isWebSocketConnected() && this._config.electrumUrl) {
|
|
1388
1505
|
await connect(this._config.electrumUrl);
|
|
1389
1506
|
}
|
|
1390
|
-
this._initialized = true;
|
|
1391
1507
|
}
|
|
1392
1508
|
destroy() {
|
|
1393
1509
|
if (isWebSocketConnected()) {
|
|
@@ -1445,6 +1561,7 @@ var L1PaymentsModule = class {
|
|
|
1445
1561
|
}
|
|
1446
1562
|
async send(request) {
|
|
1447
1563
|
this.ensureInitialized();
|
|
1564
|
+
await this.ensureConnected();
|
|
1448
1565
|
if (!this._wallet || !this._identity) {
|
|
1449
1566
|
return { success: false, error: "No wallet available" };
|
|
1450
1567
|
}
|
|
@@ -1479,6 +1596,7 @@ var L1PaymentsModule = class {
|
|
|
1479
1596
|
}
|
|
1480
1597
|
async getBalance() {
|
|
1481
1598
|
this.ensureInitialized();
|
|
1599
|
+
await this.ensureConnected();
|
|
1482
1600
|
const addresses = this._getWatchedAddresses();
|
|
1483
1601
|
let totalAlpha = 0;
|
|
1484
1602
|
let vestedSats = BigInt(0);
|
|
@@ -1510,6 +1628,7 @@ var L1PaymentsModule = class {
|
|
|
1510
1628
|
}
|
|
1511
1629
|
async getUtxos() {
|
|
1512
1630
|
this.ensureInitialized();
|
|
1631
|
+
await this.ensureConnected();
|
|
1513
1632
|
const result = [];
|
|
1514
1633
|
const currentHeight = await getCurrentBlockHeight();
|
|
1515
1634
|
const allUtxos = await this._getAllUtxos();
|
|
@@ -1545,42 +1664,73 @@ var L1PaymentsModule = class {
|
|
|
1545
1664
|
return result;
|
|
1546
1665
|
}
|
|
1547
1666
|
async getHistory(limit) {
|
|
1667
|
+
await this.ensureConnected();
|
|
1548
1668
|
this.ensureInitialized();
|
|
1549
1669
|
const addresses = this._getWatchedAddresses();
|
|
1550
1670
|
const transactions = [];
|
|
1551
1671
|
const seenTxids = /* @__PURE__ */ new Set();
|
|
1552
1672
|
const currentHeight = await getCurrentBlockHeight();
|
|
1673
|
+
const txCache = /* @__PURE__ */ new Map();
|
|
1674
|
+
const fetchTx = async (txid) => {
|
|
1675
|
+
if (txCache.has(txid)) return txCache.get(txid);
|
|
1676
|
+
const detail = await getTransaction(txid);
|
|
1677
|
+
txCache.set(txid, detail);
|
|
1678
|
+
return detail;
|
|
1679
|
+
};
|
|
1680
|
+
const addressSet = new Set(addresses.map((a) => a.toLowerCase()));
|
|
1553
1681
|
for (const address of addresses) {
|
|
1554
1682
|
const history = await getTransactionHistory(address);
|
|
1555
1683
|
for (const item of history) {
|
|
1556
1684
|
if (seenTxids.has(item.tx_hash)) continue;
|
|
1557
1685
|
seenTxids.add(item.tx_hash);
|
|
1558
|
-
const tx = await
|
|
1686
|
+
const tx = await fetchTx(item.tx_hash);
|
|
1559
1687
|
if (!tx) continue;
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1688
|
+
let isSend = false;
|
|
1689
|
+
for (const vin of tx.vin ?? []) {
|
|
1690
|
+
if (!vin.txid) continue;
|
|
1691
|
+
const prevTx = await fetchTx(vin.txid);
|
|
1692
|
+
if (prevTx?.vout?.[vin.vout]) {
|
|
1693
|
+
const prevOut = prevTx.vout[vin.vout];
|
|
1694
|
+
const prevAddrs = [
|
|
1695
|
+
...prevOut.scriptPubKey?.addresses ?? [],
|
|
1696
|
+
...prevOut.scriptPubKey?.address ? [prevOut.scriptPubKey.address] : []
|
|
1697
|
+
];
|
|
1698
|
+
if (prevAddrs.some((a) => addressSet.has(a.toLowerCase()))) {
|
|
1699
|
+
isSend = true;
|
|
1700
|
+
break;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
let amountToUs = 0;
|
|
1705
|
+
let amountToOthers = 0;
|
|
1564
1706
|
let txAddress = address;
|
|
1707
|
+
let externalAddress = "";
|
|
1565
1708
|
if (tx.vout) {
|
|
1566
1709
|
for (const vout of tx.vout) {
|
|
1567
|
-
const voutAddresses =
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1710
|
+
const voutAddresses = [
|
|
1711
|
+
...vout.scriptPubKey?.addresses ?? [],
|
|
1712
|
+
...vout.scriptPubKey?.address ? [vout.scriptPubKey.address] : []
|
|
1713
|
+
];
|
|
1714
|
+
const isOurs = voutAddresses.some((a) => addressSet.has(a.toLowerCase()));
|
|
1715
|
+
const valueSats = Math.floor((vout.value ?? 0) * 1e8);
|
|
1716
|
+
if (isOurs) {
|
|
1717
|
+
amountToUs += valueSats;
|
|
1718
|
+
if (!txAddress) txAddress = voutAddresses[0];
|
|
1719
|
+
} else {
|
|
1720
|
+
amountToOthers += valueSats;
|
|
1721
|
+
if (!externalAddress && voutAddresses.length > 0) {
|
|
1722
|
+
externalAddress = voutAddresses[0];
|
|
1723
|
+
}
|
|
1576
1724
|
}
|
|
1577
1725
|
}
|
|
1578
1726
|
}
|
|
1727
|
+
const amount = isSend ? amountToOthers.toString() : amountToUs.toString();
|
|
1728
|
+
const displayAddress = isSend ? externalAddress || txAddress : txAddress;
|
|
1579
1729
|
transactions.push({
|
|
1580
1730
|
txid: item.tx_hash,
|
|
1581
1731
|
type: isSend ? "send" : "receive",
|
|
1582
1732
|
amount,
|
|
1583
|
-
address:
|
|
1733
|
+
address: displayAddress,
|
|
1584
1734
|
confirmations: item.height > 0 ? currentHeight - item.height : 0,
|
|
1585
1735
|
timestamp: tx.time ? tx.time * 1e3 : Date.now(),
|
|
1586
1736
|
blockHeight: item.height > 0 ? item.height : void 0
|
|
@@ -1592,6 +1742,7 @@ var L1PaymentsModule = class {
|
|
|
1592
1742
|
}
|
|
1593
1743
|
async getTransaction(txid) {
|
|
1594
1744
|
this.ensureInitialized();
|
|
1745
|
+
await this.ensureConnected();
|
|
1595
1746
|
const tx = await getTransaction(txid);
|
|
1596
1747
|
if (!tx) return null;
|
|
1597
1748
|
const addresses = this._getWatchedAddresses();
|
|
@@ -1627,6 +1778,7 @@ var L1PaymentsModule = class {
|
|
|
1627
1778
|
}
|
|
1628
1779
|
async estimateFee(to, amount) {
|
|
1629
1780
|
this.ensureInitialized();
|
|
1781
|
+
await this.ensureConnected();
|
|
1630
1782
|
if (!this._wallet) {
|
|
1631
1783
|
return { fee: "0", feeRate: this._config.defaultFeeRate ?? 10 };
|
|
1632
1784
|
}
|
|
@@ -2146,7 +2298,9 @@ var STORAGE_KEYS_GLOBAL = {
|
|
|
2146
2298
|
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
2147
2299
|
ADDRESS_NAMETAGS: "address_nametags",
|
|
2148
2300
|
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
2149
|
-
TRACKED_ADDRESSES: "tracked_addresses"
|
|
2301
|
+
TRACKED_ADDRESSES: "tracked_addresses",
|
|
2302
|
+
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
2303
|
+
LAST_WALLET_EVENT_TS: "last_wallet_event_ts"
|
|
2150
2304
|
};
|
|
2151
2305
|
var STORAGE_KEYS_ADDRESS = {
|
|
2152
2306
|
/** Pending transfers for this address */
|
|
@@ -3550,7 +3704,7 @@ async function parseTokenInfo(tokenData) {
|
|
|
3550
3704
|
try {
|
|
3551
3705
|
const sdkToken = await SdkToken2.fromJSON(data);
|
|
3552
3706
|
if (sdkToken.id) {
|
|
3553
|
-
defaultInfo.tokenId = sdkToken.id.
|
|
3707
|
+
defaultInfo.tokenId = sdkToken.id.toJSON();
|
|
3554
3708
|
}
|
|
3555
3709
|
if (sdkToken.coins && sdkToken.coins.coins) {
|
|
3556
3710
|
const rawCoins = sdkToken.coins.coins;
|
|
@@ -3841,8 +3995,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
3841
3995
|
maxRetries: config?.maxRetries ?? 3,
|
|
3842
3996
|
debug: config?.debug ?? false
|
|
3843
3997
|
};
|
|
3844
|
-
|
|
3845
|
-
this.l1 = l1Enabled ? new L1PaymentsModule(config?.l1) : null;
|
|
3998
|
+
this.l1 = config?.l1 === null ? null : new L1PaymentsModule(config?.l1);
|
|
3846
3999
|
}
|
|
3847
4000
|
/** Get module configuration */
|
|
3848
4001
|
getConfig() {
|
|
@@ -4044,7 +4197,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4044
4197
|
memo: request.memo
|
|
4045
4198
|
});
|
|
4046
4199
|
console.log(`[Payments] Split token sent successfully`);
|
|
4047
|
-
await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag);
|
|
4200
|
+
await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag, true);
|
|
4048
4201
|
result.txHash = "split-" + Date.now().toString(16);
|
|
4049
4202
|
this.log(`Split transfer completed`);
|
|
4050
4203
|
}
|
|
@@ -4070,7 +4223,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4070
4223
|
});
|
|
4071
4224
|
console.log(`[Payments] Direct token sent successfully`);
|
|
4072
4225
|
this.log(`Token ${token.id} transferred, txHash: ${result.txHash}`);
|
|
4073
|
-
await this.removeToken(token.id, recipientNametag);
|
|
4226
|
+
await this.removeToken(token.id, recipientNametag, true);
|
|
4074
4227
|
}
|
|
4075
4228
|
result.status = "delivered";
|
|
4076
4229
|
await this.save();
|
|
@@ -4219,7 +4372,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4219
4372
|
);
|
|
4220
4373
|
if (result.success) {
|
|
4221
4374
|
const recipientNametag = request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0;
|
|
4222
|
-
await this.removeToken(tokenToSplit.id, recipientNametag);
|
|
4375
|
+
await this.removeToken(tokenToSplit.id, recipientNametag, true);
|
|
4223
4376
|
await this.addToHistory({
|
|
4224
4377
|
type: "SENT",
|
|
4225
4378
|
amount: request.amount,
|
|
@@ -4504,13 +4657,16 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4504
4657
|
if (this.paymentRequests.find((r) => r.id === transportRequest.id)) {
|
|
4505
4658
|
return;
|
|
4506
4659
|
}
|
|
4660
|
+
const coinId = transportRequest.request.coinId;
|
|
4661
|
+
const registry = TokenRegistry.getInstance();
|
|
4662
|
+
const coinDef = registry.getDefinition(coinId);
|
|
4507
4663
|
const request = {
|
|
4508
4664
|
id: transportRequest.id,
|
|
4509
4665
|
senderPubkey: transportRequest.senderTransportPubkey,
|
|
4666
|
+
senderNametag: transportRequest.senderNametag,
|
|
4510
4667
|
amount: transportRequest.request.amount,
|
|
4511
|
-
coinId
|
|
4512
|
-
symbol:
|
|
4513
|
-
// Use coinId as symbol for now
|
|
4668
|
+
coinId,
|
|
4669
|
+
symbol: coinDef?.symbol || coinId.slice(0, 8),
|
|
4514
4670
|
message: transportRequest.request.message,
|
|
4515
4671
|
recipientNametag: transportRequest.request.recipientNametag,
|
|
4516
4672
|
requestId: transportRequest.request.requestId,
|
|
@@ -4725,35 +4881,39 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4725
4881
|
const rawAssets = Array.from(assetsMap.values());
|
|
4726
4882
|
let priceMap = null;
|
|
4727
4883
|
if (this.priceProvider && rawAssets.length > 0) {
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
const
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
existing
|
|
4736
|
-
|
|
4737
|
-
|
|
4884
|
+
try {
|
|
4885
|
+
const registry = TokenRegistry.getInstance();
|
|
4886
|
+
const nameToCoins = /* @__PURE__ */ new Map();
|
|
4887
|
+
for (const asset of rawAssets) {
|
|
4888
|
+
const def = registry.getDefinition(asset.coinId);
|
|
4889
|
+
if (def?.name) {
|
|
4890
|
+
const existing = nameToCoins.get(def.name);
|
|
4891
|
+
if (existing) {
|
|
4892
|
+
existing.push(asset.coinId);
|
|
4893
|
+
} else {
|
|
4894
|
+
nameToCoins.set(def.name, [asset.coinId]);
|
|
4895
|
+
}
|
|
4738
4896
|
}
|
|
4739
4897
|
}
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
}
|
|
4898
|
+
if (nameToCoins.size > 0) {
|
|
4899
|
+
const tokenNames = Array.from(nameToCoins.keys());
|
|
4900
|
+
const prices = await this.priceProvider.getPrices(tokenNames);
|
|
4901
|
+
priceMap = /* @__PURE__ */ new Map();
|
|
4902
|
+
for (const [name, coinIds] of nameToCoins) {
|
|
4903
|
+
const price = prices.get(name);
|
|
4904
|
+
if (price) {
|
|
4905
|
+
for (const cid of coinIds) {
|
|
4906
|
+
priceMap.set(cid, {
|
|
4907
|
+
priceUsd: price.priceUsd,
|
|
4908
|
+
priceEur: price.priceEur,
|
|
4909
|
+
change24h: price.change24h
|
|
4910
|
+
});
|
|
4911
|
+
}
|
|
4754
4912
|
}
|
|
4755
4913
|
}
|
|
4756
4914
|
}
|
|
4915
|
+
} catch (error) {
|
|
4916
|
+
console.warn("[Payments] Failed to fetch prices, returning assets without price data:", error);
|
|
4757
4917
|
}
|
|
4758
4918
|
}
|
|
4759
4919
|
return rawAssets.map((raw) => {
|
|
@@ -4956,6 +5116,12 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4956
5116
|
updatedAt: Date.now(),
|
|
4957
5117
|
sdkData: typeof tokenJson === "string" ? tokenJson : JSON.stringify(tokenJson)
|
|
4958
5118
|
};
|
|
5119
|
+
const loadedTokenId = extractTokenIdFromSdkData(token.sdkData);
|
|
5120
|
+
const loadedStateHash = extractStateHashFromSdkData(token.sdkData);
|
|
5121
|
+
if (loadedTokenId && loadedStateHash && this.isStateTombstoned(loadedTokenId, loadedStateHash)) {
|
|
5122
|
+
this.log(`Skipping tombstoned token file ${tokenId} (${loadedTokenId.slice(0, 8)}...)`);
|
|
5123
|
+
continue;
|
|
5124
|
+
}
|
|
4959
5125
|
this.tokens.set(token.id, token);
|
|
4960
5126
|
this.log(`Loaded token from file: ${tokenId}`);
|
|
4961
5127
|
} catch (tokenError) {
|
|
@@ -5013,6 +5179,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5013
5179
|
this.log(`Warning: Could not create tombstone for token ${tokenId.slice(0, 8)}... (missing tokenId or stateHash)`);
|
|
5014
5180
|
}
|
|
5015
5181
|
this.tokens.delete(tokenId);
|
|
5182
|
+
await this.deleteTokenFiles(token);
|
|
5016
5183
|
if (!skipHistory && token.coinId && token.amount) {
|
|
5017
5184
|
await this.addToHistory({
|
|
5018
5185
|
type: "SENT",
|
|
@@ -5025,6 +5192,31 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5025
5192
|
}
|
|
5026
5193
|
await this.save();
|
|
5027
5194
|
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Delete physical token file(s) from all storage providers.
|
|
5197
|
+
* Finds files by matching the SDK token ID prefix in the filename.
|
|
5198
|
+
*/
|
|
5199
|
+
async deleteTokenFiles(token) {
|
|
5200
|
+
const sdkTokenId = extractTokenIdFromSdkData(token.sdkData);
|
|
5201
|
+
if (!sdkTokenId) return;
|
|
5202
|
+
const tokenIdPrefix = sdkTokenId.slice(0, 16);
|
|
5203
|
+
const providers = this.getTokenStorageProviders();
|
|
5204
|
+
for (const [providerId, provider] of providers) {
|
|
5205
|
+
if (!provider.listTokenIds || !provider.deleteToken) continue;
|
|
5206
|
+
try {
|
|
5207
|
+
const allIds = await provider.listTokenIds();
|
|
5208
|
+
const matchingFiles = allIds.filter(
|
|
5209
|
+
(id) => id.startsWith(`token-${tokenIdPrefix}`)
|
|
5210
|
+
);
|
|
5211
|
+
for (const fileId of matchingFiles) {
|
|
5212
|
+
await provider.deleteToken(fileId);
|
|
5213
|
+
this.log(`Deleted token file ${fileId} from ${providerId}`);
|
|
5214
|
+
}
|
|
5215
|
+
} catch (error) {
|
|
5216
|
+
console.warn(`[Payments] Failed to delete token files from ${providerId}:`, error);
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5028
5220
|
// ===========================================================================
|
|
5029
5221
|
// Public API - Tombstones
|
|
5030
5222
|
// ===========================================================================
|
|
@@ -6529,6 +6721,20 @@ function decryptSimple(ciphertext, password) {
|
|
|
6529
6721
|
}
|
|
6530
6722
|
return result;
|
|
6531
6723
|
}
|
|
6724
|
+
function decryptWithSalt(ciphertext, password, salt) {
|
|
6725
|
+
try {
|
|
6726
|
+
const key = CryptoJS6.PBKDF2(password, salt, {
|
|
6727
|
+
keySize: 256 / 32,
|
|
6728
|
+
iterations: 1e5,
|
|
6729
|
+
hasher: CryptoJS6.algo.SHA256
|
|
6730
|
+
}).toString();
|
|
6731
|
+
const decrypted = CryptoJS6.AES.decrypt(ciphertext, key);
|
|
6732
|
+
const result = decrypted.toString(CryptoJS6.enc.Utf8);
|
|
6733
|
+
return result || null;
|
|
6734
|
+
} catch {
|
|
6735
|
+
return null;
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6532
6738
|
function encryptMnemonic(mnemonic, password) {
|
|
6533
6739
|
return encryptSimple(mnemonic, password);
|
|
6534
6740
|
}
|
|
@@ -6556,6 +6762,81 @@ function generateRandomKey(bytes = 32) {
|
|
|
6556
6762
|
return CryptoJS6.lib.WordArray.random(bytes).toString(CryptoJS6.enc.Hex);
|
|
6557
6763
|
}
|
|
6558
6764
|
|
|
6765
|
+
// core/scan.ts
|
|
6766
|
+
async function scanAddressesImpl(deriveAddress, options = {}) {
|
|
6767
|
+
const maxAddresses = options.maxAddresses ?? 50;
|
|
6768
|
+
const gapLimit = options.gapLimit ?? 20;
|
|
6769
|
+
const includeChange = options.includeChange ?? true;
|
|
6770
|
+
const { onProgress, signal, resolveNametag } = options;
|
|
6771
|
+
const { connect: connect2, getBalance: getBalance2 } = await Promise.resolve().then(() => (init_network(), network_exports));
|
|
6772
|
+
await connect2();
|
|
6773
|
+
const foundAddresses = [];
|
|
6774
|
+
let totalBalance = 0;
|
|
6775
|
+
let totalScanned = 0;
|
|
6776
|
+
let nametagsFoundCount = 0;
|
|
6777
|
+
const chains = includeChange ? [false, true] : [false];
|
|
6778
|
+
const totalToScan = maxAddresses * chains.length;
|
|
6779
|
+
for (const isChange of chains) {
|
|
6780
|
+
let consecutiveEmpty = 0;
|
|
6781
|
+
for (let index = 0; index < maxAddresses; index++) {
|
|
6782
|
+
if (signal?.aborted) break;
|
|
6783
|
+
const addrInfo = deriveAddress(index, isChange);
|
|
6784
|
+
totalScanned++;
|
|
6785
|
+
onProgress?.({
|
|
6786
|
+
scanned: totalScanned,
|
|
6787
|
+
total: totalToScan,
|
|
6788
|
+
currentAddress: addrInfo.address,
|
|
6789
|
+
foundCount: foundAddresses.length,
|
|
6790
|
+
currentGap: consecutiveEmpty,
|
|
6791
|
+
nametagsFoundCount
|
|
6792
|
+
});
|
|
6793
|
+
try {
|
|
6794
|
+
const balance = await getBalance2(addrInfo.address);
|
|
6795
|
+
if (balance > 0) {
|
|
6796
|
+
let nametag;
|
|
6797
|
+
if (resolveNametag) {
|
|
6798
|
+
try {
|
|
6799
|
+
const tag = await resolveNametag(addrInfo.address);
|
|
6800
|
+
if (tag) {
|
|
6801
|
+
nametag = tag;
|
|
6802
|
+
nametagsFoundCount++;
|
|
6803
|
+
}
|
|
6804
|
+
} catch {
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6807
|
+
foundAddresses.push({
|
|
6808
|
+
index,
|
|
6809
|
+
address: addrInfo.address,
|
|
6810
|
+
path: addrInfo.path,
|
|
6811
|
+
balance,
|
|
6812
|
+
isChange,
|
|
6813
|
+
nametag
|
|
6814
|
+
});
|
|
6815
|
+
totalBalance += balance;
|
|
6816
|
+
consecutiveEmpty = 0;
|
|
6817
|
+
} else {
|
|
6818
|
+
consecutiveEmpty++;
|
|
6819
|
+
}
|
|
6820
|
+
} catch (err) {
|
|
6821
|
+
console.warn(`[scanAddresses] Error checking ${addrInfo.address}:`, err);
|
|
6822
|
+
consecutiveEmpty++;
|
|
6823
|
+
}
|
|
6824
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
6825
|
+
break;
|
|
6826
|
+
}
|
|
6827
|
+
if (totalScanned % 5 === 0) {
|
|
6828
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6831
|
+
if (signal?.aborted) break;
|
|
6832
|
+
}
|
|
6833
|
+
return {
|
|
6834
|
+
addresses: foundAddresses,
|
|
6835
|
+
totalBalance,
|
|
6836
|
+
scannedCount: totalScanned
|
|
6837
|
+
};
|
|
6838
|
+
}
|
|
6839
|
+
|
|
6559
6840
|
// serialization/wallet-text.ts
|
|
6560
6841
|
import CryptoJS7 from "crypto-js";
|
|
6561
6842
|
|
|
@@ -6812,10 +7093,11 @@ function parseWalletText(content) {
|
|
|
6812
7093
|
);
|
|
6813
7094
|
const descriptorPath = extractFromText(content, /DESCRIPTOR PATH:\s*([^\n]+)/);
|
|
6814
7095
|
const isBIP32 = content.includes("WALLET TYPE: BIP32 hierarchical deterministic wallet") || content.includes("WALLET TYPE: Alpha descriptor wallet") || !!chainCode;
|
|
7096
|
+
const effectiveDescriptorPath = descriptorPath ?? (isBIP32 ? "84'/1'/0'" : void 0);
|
|
6815
7097
|
const data = {
|
|
6816
7098
|
masterKey,
|
|
6817
7099
|
chainCode: chainCode ?? void 0,
|
|
6818
|
-
descriptorPath:
|
|
7100
|
+
descriptorPath: effectiveDescriptorPath,
|
|
6819
7101
|
derivationMode: isBIP32 ? "bip32" : "wif_hmac"
|
|
6820
7102
|
};
|
|
6821
7103
|
return {
|
|
@@ -6858,10 +7140,11 @@ function parseAndDecryptWalletText(content, password) {
|
|
|
6858
7140
|
);
|
|
6859
7141
|
const descriptorPath = extractFromText(content, /DESCRIPTOR PATH:\s*([^\n]+)/);
|
|
6860
7142
|
const isBIP32 = content.includes("WALLET TYPE: BIP32 hierarchical deterministic wallet") || content.includes("WALLET TYPE: Alpha descriptor wallet") || !!chainCode;
|
|
7143
|
+
const effectiveDescriptorPath = descriptorPath ?? (isBIP32 ? "84'/1'/0'" : void 0);
|
|
6861
7144
|
const data = {
|
|
6862
7145
|
masterKey,
|
|
6863
7146
|
chainCode: chainCode ?? void 0,
|
|
6864
|
-
descriptorPath:
|
|
7147
|
+
descriptorPath: effectiveDescriptorPath,
|
|
6865
7148
|
derivationMode: isBIP32 ? "bip32" : "wif_hmac"
|
|
6866
7149
|
};
|
|
6867
7150
|
return {
|
|
@@ -7402,8 +7685,8 @@ var Sphere = class _Sphere {
|
|
|
7402
7685
|
if (options.nametag) {
|
|
7403
7686
|
await sphere.registerNametag(options.nametag);
|
|
7404
7687
|
} else {
|
|
7405
|
-
await sphere.syncIdentityWithTransport();
|
|
7406
7688
|
await sphere.recoverNametagFromTransport();
|
|
7689
|
+
await sphere.syncIdentityWithTransport();
|
|
7407
7690
|
}
|
|
7408
7691
|
return sphere;
|
|
7409
7692
|
}
|
|
@@ -7450,7 +7733,15 @@ var Sphere = class _Sphere {
|
|
|
7450
7733
|
if (!options.mnemonic && !options.masterKey) {
|
|
7451
7734
|
throw new Error("Either mnemonic or masterKey is required");
|
|
7452
7735
|
}
|
|
7736
|
+
console.log("[Sphere.import] Starting import...");
|
|
7737
|
+
console.log("[Sphere.import] Clearing existing wallet data...");
|
|
7453
7738
|
await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
|
|
7739
|
+
console.log("[Sphere.import] Clear done");
|
|
7740
|
+
if (!options.storage.isConnected()) {
|
|
7741
|
+
console.log("[Sphere.import] Reconnecting storage...");
|
|
7742
|
+
await options.storage.connect();
|
|
7743
|
+
console.log("[Sphere.import] Storage reconnected");
|
|
7744
|
+
}
|
|
7454
7745
|
const sphere = new _Sphere(
|
|
7455
7746
|
options.storage,
|
|
7456
7747
|
options.transport,
|
|
@@ -7463,9 +7754,12 @@ var Sphere = class _Sphere {
|
|
|
7463
7754
|
if (!_Sphere.validateMnemonic(options.mnemonic)) {
|
|
7464
7755
|
throw new Error("Invalid mnemonic");
|
|
7465
7756
|
}
|
|
7757
|
+
console.log("[Sphere.import] Storing mnemonic...");
|
|
7466
7758
|
await sphere.storeMnemonic(options.mnemonic, options.derivationPath, options.basePath);
|
|
7759
|
+
console.log("[Sphere.import] Initializing identity from mnemonic...");
|
|
7467
7760
|
await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
|
|
7468
7761
|
} else if (options.masterKey) {
|
|
7762
|
+
console.log("[Sphere.import] Storing master key...");
|
|
7469
7763
|
await sphere.storeMasterKey(
|
|
7470
7764
|
options.masterKey,
|
|
7471
7765
|
options.chainCode,
|
|
@@ -7473,24 +7767,35 @@ var Sphere = class _Sphere {
|
|
|
7473
7767
|
options.basePath,
|
|
7474
7768
|
options.derivationMode
|
|
7475
7769
|
);
|
|
7770
|
+
console.log("[Sphere.import] Initializing identity from master key...");
|
|
7476
7771
|
await sphere.initializeIdentityFromMasterKey(
|
|
7477
7772
|
options.masterKey,
|
|
7478
7773
|
options.chainCode,
|
|
7479
7774
|
options.derivationPath
|
|
7480
7775
|
);
|
|
7481
7776
|
}
|
|
7777
|
+
console.log("[Sphere.import] Initializing providers...");
|
|
7482
7778
|
await sphere.initializeProviders();
|
|
7779
|
+
console.log("[Sphere.import] Providers initialized. Initializing modules...");
|
|
7483
7780
|
await sphere.initializeModules();
|
|
7781
|
+
console.log("[Sphere.import] Modules initialized");
|
|
7484
7782
|
if (!options.nametag) {
|
|
7783
|
+
console.log("[Sphere.import] Recovering nametag from transport...");
|
|
7485
7784
|
await sphere.recoverNametagFromTransport();
|
|
7785
|
+
console.log("[Sphere.import] Nametag recovery done");
|
|
7786
|
+
await sphere.syncIdentityWithTransport();
|
|
7486
7787
|
}
|
|
7788
|
+
console.log("[Sphere.import] Finalizing wallet creation...");
|
|
7487
7789
|
await sphere.finalizeWalletCreation();
|
|
7488
7790
|
sphere._initialized = true;
|
|
7489
7791
|
_Sphere.instance = sphere;
|
|
7792
|
+
console.log("[Sphere.import] Tracking address 0...");
|
|
7490
7793
|
await sphere.ensureAddressTracked(0);
|
|
7491
7794
|
if (options.nametag) {
|
|
7795
|
+
console.log("[Sphere.import] Registering nametag...");
|
|
7492
7796
|
await sphere.registerNametag(options.nametag);
|
|
7493
7797
|
}
|
|
7798
|
+
console.log("[Sphere.import] Import complete");
|
|
7494
7799
|
return sphere;
|
|
7495
7800
|
}
|
|
7496
7801
|
/**
|
|
@@ -7515,6 +7820,10 @@ var Sphere = class _Sphere {
|
|
|
7515
7820
|
static async clear(storageOrOptions) {
|
|
7516
7821
|
const storage = "get" in storageOrOptions ? storageOrOptions : storageOrOptions.storage;
|
|
7517
7822
|
const tokenStorage = "get" in storageOrOptions ? void 0 : storageOrOptions.tokenStorage;
|
|
7823
|
+
if (!storage.isConnected()) {
|
|
7824
|
+
await storage.connect();
|
|
7825
|
+
}
|
|
7826
|
+
console.log("[Sphere.clear] Removing storage keys...");
|
|
7518
7827
|
await storage.remove(STORAGE_KEYS_GLOBAL.MNEMONIC);
|
|
7519
7828
|
await storage.remove(STORAGE_KEYS_GLOBAL.MASTER_KEY);
|
|
7520
7829
|
await storage.remove(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
|
|
@@ -7527,11 +7836,30 @@ var Sphere = class _Sphere {
|
|
|
7527
7836
|
await storage.remove(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
|
|
7528
7837
|
await storage.remove(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
|
|
7529
7838
|
await storage.remove(STORAGE_KEYS_ADDRESS.OUTBOX);
|
|
7839
|
+
console.log("[Sphere.clear] Storage keys removed");
|
|
7530
7840
|
if (tokenStorage?.clear) {
|
|
7531
|
-
|
|
7841
|
+
console.log("[Sphere.clear] Clearing token storage...");
|
|
7842
|
+
try {
|
|
7843
|
+
await Promise.race([
|
|
7844
|
+
tokenStorage.clear(),
|
|
7845
|
+
new Promise(
|
|
7846
|
+
(_, reject) => setTimeout(() => reject(new Error("tokenStorage.clear() timed out after 2s")), 2e3)
|
|
7847
|
+
)
|
|
7848
|
+
]);
|
|
7849
|
+
console.log("[Sphere.clear] Token storage cleared");
|
|
7850
|
+
} catch (err) {
|
|
7851
|
+
console.warn("[Sphere.clear] Token storage clear failed/timed out:", err);
|
|
7852
|
+
}
|
|
7532
7853
|
}
|
|
7854
|
+
console.log("[Sphere.clear] Destroying vesting classifier...");
|
|
7855
|
+
await vestingClassifier.destroy();
|
|
7856
|
+
console.log("[Sphere.clear] Vesting classifier destroyed");
|
|
7533
7857
|
if (_Sphere.instance) {
|
|
7858
|
+
console.log("[Sphere.clear] Destroying Sphere instance...");
|
|
7534
7859
|
await _Sphere.instance.destroy();
|
|
7860
|
+
console.log("[Sphere.clear] Sphere instance destroyed");
|
|
7861
|
+
} else {
|
|
7862
|
+
console.log("[Sphere.clear] No Sphere instance to destroy");
|
|
7535
7863
|
}
|
|
7536
7864
|
}
|
|
7537
7865
|
/**
|
|
@@ -7712,7 +8040,7 @@ var Sphere = class _Sphere {
|
|
|
7712
8040
|
return {
|
|
7713
8041
|
source: this._source,
|
|
7714
8042
|
hasMnemonic: this._mnemonic !== null,
|
|
7715
|
-
hasChainCode: this._masterKey?.chainCode
|
|
8043
|
+
hasChainCode: !!this._masterKey?.chainCode,
|
|
7716
8044
|
derivationMode: this._derivationMode,
|
|
7717
8045
|
basePath: this._basePath,
|
|
7718
8046
|
address0
|
|
@@ -7765,7 +8093,7 @@ var Sphere = class _Sphere {
|
|
|
7765
8093
|
let chainCode;
|
|
7766
8094
|
if (this._masterKey) {
|
|
7767
8095
|
masterPrivateKey = this._masterKey.privateKey;
|
|
7768
|
-
chainCode = this._masterKey.chainCode;
|
|
8096
|
+
chainCode = this._masterKey.chainCode || void 0;
|
|
7769
8097
|
}
|
|
7770
8098
|
let mnemonic;
|
|
7771
8099
|
let encrypted = false;
|
|
@@ -7842,7 +8170,7 @@ var Sphere = class _Sphere {
|
|
|
7842
8170
|
}
|
|
7843
8171
|
}
|
|
7844
8172
|
const masterPrivateKey = this._masterKey?.privateKey || "";
|
|
7845
|
-
const chainCode = this._masterKey?.chainCode;
|
|
8173
|
+
const chainCode = this._masterKey?.chainCode || void 0;
|
|
7846
8174
|
const isBIP32 = this._derivationMode === "bip32";
|
|
7847
8175
|
const descriptorPath = this._basePath.replace(/^m\//, "");
|
|
7848
8176
|
if (options.password) {
|
|
@@ -7912,7 +8240,8 @@ var Sphere = class _Sphere {
|
|
|
7912
8240
|
storage: options.storage,
|
|
7913
8241
|
transport: options.transport,
|
|
7914
8242
|
oracle: options.oracle,
|
|
7915
|
-
tokenStorage: options.tokenStorage
|
|
8243
|
+
tokenStorage: options.tokenStorage,
|
|
8244
|
+
l1: options.l1
|
|
7916
8245
|
});
|
|
7917
8246
|
return { success: true, mnemonic };
|
|
7918
8247
|
}
|
|
@@ -7925,7 +8254,8 @@ var Sphere = class _Sphere {
|
|
|
7925
8254
|
storage: options.storage,
|
|
7926
8255
|
transport: options.transport,
|
|
7927
8256
|
oracle: options.oracle,
|
|
7928
|
-
tokenStorage: options.tokenStorage
|
|
8257
|
+
tokenStorage: options.tokenStorage,
|
|
8258
|
+
l1: options.l1
|
|
7929
8259
|
});
|
|
7930
8260
|
return { success: true };
|
|
7931
8261
|
}
|
|
@@ -7984,7 +8314,8 @@ var Sphere = class _Sphere {
|
|
|
7984
8314
|
transport: options.transport,
|
|
7985
8315
|
oracle: options.oracle,
|
|
7986
8316
|
tokenStorage: options.tokenStorage,
|
|
7987
|
-
nametag: options.nametag
|
|
8317
|
+
nametag: options.nametag,
|
|
8318
|
+
l1: options.l1
|
|
7988
8319
|
});
|
|
7989
8320
|
return { success: true, sphere, mnemonic };
|
|
7990
8321
|
}
|
|
@@ -8013,7 +8344,8 @@ var Sphere = class _Sphere {
|
|
|
8013
8344
|
transport: options.transport,
|
|
8014
8345
|
oracle: options.oracle,
|
|
8015
8346
|
tokenStorage: options.tokenStorage,
|
|
8016
|
-
nametag: options.nametag
|
|
8347
|
+
nametag: options.nametag,
|
|
8348
|
+
l1: options.l1
|
|
8017
8349
|
});
|
|
8018
8350
|
return { success: true, sphere };
|
|
8019
8351
|
}
|
|
@@ -8044,25 +8376,94 @@ var Sphere = class _Sphere {
|
|
|
8044
8376
|
transport: options.transport,
|
|
8045
8377
|
oracle: options.oracle,
|
|
8046
8378
|
tokenStorage: options.tokenStorage,
|
|
8047
|
-
nametag: options.nametag
|
|
8379
|
+
nametag: options.nametag,
|
|
8380
|
+
l1: options.l1
|
|
8048
8381
|
});
|
|
8049
8382
|
return { success: true, sphere };
|
|
8050
8383
|
}
|
|
8051
8384
|
if (fileType === "json") {
|
|
8052
8385
|
const content = typeof fileContent === "string" ? fileContent : new TextDecoder().decode(fileContent);
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8386
|
+
let parsed;
|
|
8387
|
+
try {
|
|
8388
|
+
parsed = JSON.parse(content);
|
|
8389
|
+
} catch {
|
|
8390
|
+
return { success: false, error: "Invalid JSON file" };
|
|
8391
|
+
}
|
|
8392
|
+
if (parsed.type === "sphere-wallet") {
|
|
8393
|
+
const result = await _Sphere.importFromJSON({
|
|
8394
|
+
jsonContent: content,
|
|
8395
|
+
password,
|
|
8396
|
+
storage: options.storage,
|
|
8397
|
+
transport: options.transport,
|
|
8398
|
+
oracle: options.oracle,
|
|
8399
|
+
tokenStorage: options.tokenStorage,
|
|
8400
|
+
l1: options.l1
|
|
8401
|
+
});
|
|
8402
|
+
if (result.success) {
|
|
8403
|
+
const sphere2 = _Sphere.getInstance();
|
|
8404
|
+
return { success: true, sphere: sphere2, mnemonic: result.mnemonic };
|
|
8405
|
+
}
|
|
8406
|
+
if (!password && result.error?.includes("Password required")) {
|
|
8407
|
+
return { success: false, needsPassword: true, error: result.error };
|
|
8408
|
+
}
|
|
8409
|
+
return { success: false, error: result.error };
|
|
8410
|
+
}
|
|
8411
|
+
let masterKey;
|
|
8412
|
+
let mnemonic;
|
|
8413
|
+
if (parsed.encrypted && typeof parsed.encrypted === "object") {
|
|
8414
|
+
if (!password) {
|
|
8415
|
+
return { success: false, needsPassword: true, error: "Password required for encrypted wallet" };
|
|
8416
|
+
}
|
|
8417
|
+
const enc = parsed.encrypted;
|
|
8418
|
+
if (!enc.salt || !enc.masterPrivateKey) {
|
|
8419
|
+
return { success: false, error: "Invalid encrypted wallet format" };
|
|
8420
|
+
}
|
|
8421
|
+
const decryptedKey = decryptWithSalt(enc.masterPrivateKey, password, enc.salt);
|
|
8422
|
+
if (!decryptedKey) {
|
|
8423
|
+
return { success: false, error: "Failed to decrypt - incorrect password?" };
|
|
8424
|
+
}
|
|
8425
|
+
masterKey = decryptedKey;
|
|
8426
|
+
if (enc.mnemonic) {
|
|
8427
|
+
mnemonic = decryptWithSalt(enc.mnemonic, password, enc.salt) ?? void 0;
|
|
8428
|
+
}
|
|
8429
|
+
} else {
|
|
8430
|
+
masterKey = parsed.masterPrivateKey;
|
|
8431
|
+
mnemonic = parsed.mnemonic;
|
|
8432
|
+
}
|
|
8433
|
+
if (!masterKey) {
|
|
8434
|
+
return { success: false, error: "No master key found in wallet JSON" };
|
|
8435
|
+
}
|
|
8436
|
+
const chainCode = parsed.chainCode;
|
|
8437
|
+
const descriptorPath = parsed.descriptorPath;
|
|
8438
|
+
const derivationMode = parsed.derivationMode;
|
|
8439
|
+
const isBIP32 = derivationMode === "bip32" || !!chainCode;
|
|
8440
|
+
const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
|
|
8441
|
+
if (mnemonic) {
|
|
8442
|
+
const sphere2 = await _Sphere.import({
|
|
8443
|
+
mnemonic,
|
|
8444
|
+
basePath,
|
|
8445
|
+
storage: options.storage,
|
|
8446
|
+
transport: options.transport,
|
|
8447
|
+
oracle: options.oracle,
|
|
8448
|
+
tokenStorage: options.tokenStorage,
|
|
8449
|
+
nametag: options.nametag,
|
|
8450
|
+
l1: options.l1
|
|
8451
|
+
});
|
|
8452
|
+
return { success: true, sphere: sphere2, mnemonic };
|
|
8453
|
+
}
|
|
8454
|
+
const sphere = await _Sphere.import({
|
|
8455
|
+
masterKey,
|
|
8456
|
+
chainCode,
|
|
8457
|
+
basePath,
|
|
8458
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
|
|
8056
8459
|
storage: options.storage,
|
|
8057
8460
|
transport: options.transport,
|
|
8058
8461
|
oracle: options.oracle,
|
|
8059
|
-
tokenStorage: options.tokenStorage
|
|
8462
|
+
tokenStorage: options.tokenStorage,
|
|
8463
|
+
nametag: options.nametag,
|
|
8464
|
+
l1: options.l1
|
|
8060
8465
|
});
|
|
8061
|
-
|
|
8062
|
-
const sphere = _Sphere.getInstance();
|
|
8063
|
-
return { success: true, sphere, mnemonic: result.mnemonic };
|
|
8064
|
-
}
|
|
8065
|
-
return result;
|
|
8466
|
+
return { success: true, sphere };
|
|
8066
8467
|
}
|
|
8067
8468
|
return { success: false, error: "Unsupported file type" };
|
|
8068
8469
|
}
|
|
@@ -8360,7 +8761,7 @@ var Sphere = class _Sphere {
|
|
|
8360
8761
|
transport: this._transport,
|
|
8361
8762
|
oracle: this._oracle,
|
|
8362
8763
|
emitEvent,
|
|
8363
|
-
chainCode: this._masterKey?.chainCode,
|
|
8764
|
+
chainCode: this._masterKey?.chainCode || void 0,
|
|
8364
8765
|
price: this._priceProvider ?? void 0
|
|
8365
8766
|
});
|
|
8366
8767
|
this._communications.initialize({
|
|
@@ -8405,6 +8806,9 @@ var Sphere = class _Sphere {
|
|
|
8405
8806
|
if (!this._masterKey) {
|
|
8406
8807
|
throw new Error("HD derivation requires master key with chain code");
|
|
8407
8808
|
}
|
|
8809
|
+
if (this._derivationMode === "wif_hmac") {
|
|
8810
|
+
return generateAddressFromMasterKey(this._masterKey.privateKey, index);
|
|
8811
|
+
}
|
|
8408
8812
|
const info = deriveAddressInfo(
|
|
8409
8813
|
this._masterKey,
|
|
8410
8814
|
this._basePath,
|
|
@@ -8476,6 +8880,66 @@ var Sphere = class _Sphere {
|
|
|
8476
8880
|
}
|
|
8477
8881
|
return addresses;
|
|
8478
8882
|
}
|
|
8883
|
+
/**
|
|
8884
|
+
* Scan blockchain addresses to discover used addresses with balances.
|
|
8885
|
+
* Derives addresses sequentially and checks L1 balance via Fulcrum.
|
|
8886
|
+
* Uses gap limit to stop after N consecutive empty addresses.
|
|
8887
|
+
*
|
|
8888
|
+
* @param options - Scanning options
|
|
8889
|
+
* @returns Scan results with found addresses and total balance
|
|
8890
|
+
*
|
|
8891
|
+
* @example
|
|
8892
|
+
* ```ts
|
|
8893
|
+
* const result = await sphere.scanAddresses({
|
|
8894
|
+
* maxAddresses: 100,
|
|
8895
|
+
* gapLimit: 20,
|
|
8896
|
+
* onProgress: (p) => console.log(`Scanned ${p.scanned}/${p.total}, found ${p.foundCount}`),
|
|
8897
|
+
* });
|
|
8898
|
+
* console.log(`Found ${result.addresses.length} addresses, total: ${result.totalBalance} ALPHA`);
|
|
8899
|
+
* ```
|
|
8900
|
+
*/
|
|
8901
|
+
async scanAddresses(options = {}) {
|
|
8902
|
+
this.ensureReady();
|
|
8903
|
+
if (!this._masterKey) {
|
|
8904
|
+
throw new Error("Address scanning requires HD master key");
|
|
8905
|
+
}
|
|
8906
|
+
const resolveNametag = options.resolveNametag ?? (this._transport.resolveAddressInfo ? async (l1Address) => {
|
|
8907
|
+
try {
|
|
8908
|
+
const info = await this._transport.resolveAddressInfo(l1Address);
|
|
8909
|
+
return info?.nametag ?? null;
|
|
8910
|
+
} catch {
|
|
8911
|
+
return null;
|
|
8912
|
+
}
|
|
8913
|
+
} : void 0);
|
|
8914
|
+
return scanAddressesImpl(
|
|
8915
|
+
(index, isChange) => this._deriveAddressInternal(index, isChange),
|
|
8916
|
+
{ ...options, resolveNametag }
|
|
8917
|
+
);
|
|
8918
|
+
}
|
|
8919
|
+
/**
|
|
8920
|
+
* Bulk-track scanned addresses with visibility and nametag data.
|
|
8921
|
+
* Selected addresses get `hidden: false`, unselected get `hidden: true`.
|
|
8922
|
+
* Performs only 2 storage writes total (tracked addresses + nametags).
|
|
8923
|
+
*/
|
|
8924
|
+
async trackScannedAddresses(entries) {
|
|
8925
|
+
this.ensureReady();
|
|
8926
|
+
for (const { index, hidden, nametag } of entries) {
|
|
8927
|
+
const tracked = await this.ensureAddressTracked(index);
|
|
8928
|
+
if (nametag) {
|
|
8929
|
+
let nametags = this._addressNametags.get(tracked.addressId);
|
|
8930
|
+
if (!nametags) {
|
|
8931
|
+
nametags = /* @__PURE__ */ new Map();
|
|
8932
|
+
this._addressNametags.set(tracked.addressId, nametags);
|
|
8933
|
+
}
|
|
8934
|
+
if (!nametags.has(0)) nametags.set(0, nametag);
|
|
8935
|
+
}
|
|
8936
|
+
if (tracked.hidden !== hidden) {
|
|
8937
|
+
tracked.hidden = hidden;
|
|
8938
|
+
}
|
|
8939
|
+
}
|
|
8940
|
+
await this.persistTrackedAddresses();
|
|
8941
|
+
await this.persistAddressNametags();
|
|
8942
|
+
}
|
|
8479
8943
|
// ===========================================================================
|
|
8480
8944
|
// Public Methods - Status
|
|
8481
8945
|
// ===========================================================================
|
|
@@ -8860,35 +9324,40 @@ var Sphere = class _Sphere {
|
|
|
8860
9324
|
if (this._identity?.nametag) {
|
|
8861
9325
|
return;
|
|
8862
9326
|
}
|
|
8863
|
-
|
|
9327
|
+
let recoveredNametag = null;
|
|
9328
|
+
if (this._transport.recoverNametag) {
|
|
9329
|
+
try {
|
|
9330
|
+
recoveredNametag = await this._transport.recoverNametag();
|
|
9331
|
+
} catch {
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9334
|
+
if (!recoveredNametag && this._transport.resolveAddressInfo && this._identity?.l1Address) {
|
|
9335
|
+
try {
|
|
9336
|
+
const info = await this._transport.resolveAddressInfo(this._identity.l1Address);
|
|
9337
|
+
if (info?.nametag) {
|
|
9338
|
+
recoveredNametag = info.nametag;
|
|
9339
|
+
}
|
|
9340
|
+
} catch {
|
|
9341
|
+
}
|
|
9342
|
+
}
|
|
9343
|
+
if (!recoveredNametag) {
|
|
8864
9344
|
return;
|
|
8865
9345
|
}
|
|
8866
9346
|
try {
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
this._identity.nametag = recoveredNametag;
|
|
8871
|
-
await this._updateCachedProxyAddress();
|
|
8872
|
-
}
|
|
8873
|
-
const entry = await this.ensureAddressTracked(this._currentAddressIndex);
|
|
8874
|
-
let nametags = this._addressNametags.get(entry.addressId);
|
|
8875
|
-
if (!nametags) {
|
|
8876
|
-
nametags = /* @__PURE__ */ new Map();
|
|
8877
|
-
this._addressNametags.set(entry.addressId, nametags);
|
|
8878
|
-
}
|
|
8879
|
-
const nextIndex = nametags.size;
|
|
8880
|
-
nametags.set(nextIndex, recoveredNametag);
|
|
8881
|
-
await this.persistAddressNametags();
|
|
8882
|
-
if (this._transport.publishIdentityBinding) {
|
|
8883
|
-
await this._transport.publishIdentityBinding(
|
|
8884
|
-
this._identity.chainPubkey,
|
|
8885
|
-
this._identity.l1Address,
|
|
8886
|
-
this._identity.directAddress || "",
|
|
8887
|
-
recoveredNametag
|
|
8888
|
-
);
|
|
8889
|
-
}
|
|
8890
|
-
this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
|
|
9347
|
+
if (this._identity) {
|
|
9348
|
+
this._identity.nametag = recoveredNametag;
|
|
9349
|
+
await this._updateCachedProxyAddress();
|
|
8891
9350
|
}
|
|
9351
|
+
const entry = await this.ensureAddressTracked(this._currentAddressIndex);
|
|
9352
|
+
let nametags = this._addressNametags.get(entry.addressId);
|
|
9353
|
+
if (!nametags) {
|
|
9354
|
+
nametags = /* @__PURE__ */ new Map();
|
|
9355
|
+
this._addressNametags.set(entry.addressId, nametags);
|
|
9356
|
+
}
|
|
9357
|
+
const nextIndex = nametags.size;
|
|
9358
|
+
nametags.set(nextIndex, recoveredNametag);
|
|
9359
|
+
await this.persistAddressNametags();
|
|
9360
|
+
this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
|
|
8892
9361
|
} catch {
|
|
8893
9362
|
}
|
|
8894
9363
|
}
|
|
@@ -9057,8 +9526,8 @@ var Sphere = class _Sphere {
|
|
|
9057
9526
|
};
|
|
9058
9527
|
this._masterKey = masterKey;
|
|
9059
9528
|
}
|
|
9060
|
-
async initializeIdentityFromMasterKey(masterKey, chainCode,
|
|
9061
|
-
const basePath =
|
|
9529
|
+
async initializeIdentityFromMasterKey(masterKey, chainCode, _derivationPath) {
|
|
9530
|
+
const basePath = this._basePath;
|
|
9062
9531
|
const fullPath = `${basePath}/0/0`;
|
|
9063
9532
|
let privateKey;
|
|
9064
9533
|
if (chainCode) {
|
|
@@ -9069,8 +9538,12 @@ var Sphere = class _Sphere {
|
|
|
9069
9538
|
chainCode
|
|
9070
9539
|
};
|
|
9071
9540
|
} else {
|
|
9072
|
-
|
|
9073
|
-
|
|
9541
|
+
const addr0 = generateAddressFromMasterKey(masterKey, 0);
|
|
9542
|
+
privateKey = addr0.privateKey;
|
|
9543
|
+
this._masterKey = {
|
|
9544
|
+
privateKey: masterKey,
|
|
9545
|
+
chainCode: ""
|
|
9546
|
+
};
|
|
9074
9547
|
}
|
|
9075
9548
|
const publicKey = getPublicKey(privateKey);
|
|
9076
9549
|
const address = publicKeyToAddress(publicKey, "alpha");
|
|
@@ -9093,8 +9566,12 @@ var Sphere = class _Sphere {
|
|
|
9093
9566
|
for (const provider of this._tokenStorageProviders.values()) {
|
|
9094
9567
|
provider.setIdentity(this._identity);
|
|
9095
9568
|
}
|
|
9096
|
-
|
|
9097
|
-
|
|
9569
|
+
if (!this._storage.isConnected()) {
|
|
9570
|
+
await this._storage.connect();
|
|
9571
|
+
}
|
|
9572
|
+
if (!this._transport.isConnected()) {
|
|
9573
|
+
await this._transport.connect();
|
|
9574
|
+
}
|
|
9098
9575
|
await this._oracle.initialize();
|
|
9099
9576
|
for (const provider of this._tokenStorageProviders.values()) {
|
|
9100
9577
|
await provider.initialize();
|
|
@@ -9110,7 +9587,7 @@ var Sphere = class _Sphere {
|
|
|
9110
9587
|
oracle: this._oracle,
|
|
9111
9588
|
emitEvent,
|
|
9112
9589
|
// Pass chain code for L1 HD derivation
|
|
9113
|
-
chainCode: this._masterKey?.chainCode,
|
|
9590
|
+
chainCode: this._masterKey?.chainCode || void 0,
|
|
9114
9591
|
price: this._priceProvider ?? void 0
|
|
9115
9592
|
});
|
|
9116
9593
|
this._communications.initialize({
|
|
@@ -9197,6 +9674,9 @@ var CurrencyUtils = {
|
|
|
9197
9674
|
toHumanReadable,
|
|
9198
9675
|
format: formatAmount
|
|
9199
9676
|
};
|
|
9677
|
+
|
|
9678
|
+
// core/index.ts
|
|
9679
|
+
init_bech32();
|
|
9200
9680
|
export {
|
|
9201
9681
|
CHARSET,
|
|
9202
9682
|
CurrencyUtils,
|
|
@@ -9217,6 +9697,7 @@ export {
|
|
|
9217
9697
|
decryptJson,
|
|
9218
9698
|
decryptMnemonic,
|
|
9219
9699
|
decryptSimple,
|
|
9700
|
+
decryptWithSalt,
|
|
9220
9701
|
deriveAddressInfo,
|
|
9221
9702
|
deriveChildKey,
|
|
9222
9703
|
deriveKeyAtPath,
|
|
@@ -9258,6 +9739,7 @@ export {
|
|
|
9258
9739
|
randomHex,
|
|
9259
9740
|
randomUUID,
|
|
9260
9741
|
ripemd160,
|
|
9742
|
+
scanAddressesImpl,
|
|
9261
9743
|
serializeEncrypted,
|
|
9262
9744
|
sha256,
|
|
9263
9745
|
sleep,
|