@zubari/sdk 0.5.2 → 0.5.4
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/{PayoutsProtocol-B5z8SEA-.d.ts → PayoutsProtocol-DAa-9A5C.d.ts} +8 -1
- package/dist/{PayoutsProtocol-CLiMFe54.d.mts → PayoutsProtocol-DKEQhwYH.d.mts} +8 -1
- package/dist/{TransactionService-BtWUjKt_.d.ts → TransactionService-BEkgF1T6.d.ts} +12 -2
- package/dist/{TransactionService-Lr_WS6iR.d.mts → TransactionService-CF_C3Kqm.d.mts} +12 -2
- package/dist/{WalletManager-DQQwVkoa.d.ts → WalletManager-CeLlZo2y.d.ts} +23 -2
- package/dist/{WalletManager-Sbpx4E1-.d.mts → WalletManager-DIx8nENh.d.mts} +23 -2
- package/dist/{contracts-B842YprC.d.mts → contracts-JfZDzaV7.d.ts} +11 -2
- package/dist/{contracts-s_CDIruh.d.ts → contracts-pugJnFzl.d.mts} +11 -2
- package/dist/{index-CTyZlHKg.d.mts → index-c90msmwW.d.mts} +2 -1
- package/dist/{index-CTyZlHKg.d.ts → index-c90msmwW.d.ts} +2 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +339 -916
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +337 -914
- package/dist/index.mjs.map +1 -1
- package/dist/protocols/index.d.mts +2 -2
- package/dist/protocols/index.d.ts +2 -2
- package/dist/protocols/index.js +24 -11
- package/dist/protocols/index.js.map +1 -1
- package/dist/protocols/index.mjs +24 -11
- package/dist/protocols/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +255 -826
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +253 -824
- package/dist/react/index.mjs.map +1 -1
- package/dist/services/index.d.mts +2 -2
- package/dist/services/index.d.ts +2 -2
- package/dist/services/index.js +179 -767
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +177 -765
- package/dist/services/index.mjs.map +1 -1
- package/dist/storage/index.js +5 -2
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +5 -2
- package/dist/storage/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +3 -3
- package/dist/wallet/index.d.ts +3 -3
- package/dist/wallet/index.js +262 -854
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +260 -852
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.js
CHANGED
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
var ethers = require('ethers');
|
|
4
4
|
var bip39 = require('@scure/bip39');
|
|
5
5
|
var english = require('@scure/bip39/wordlists/english');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var legacy_js = require('@noble/hashes/legacy.js');
|
|
9
|
-
var sha2_js = require('@noble/hashes/sha2.js');
|
|
10
|
-
var utils_js = require('@noble/hashes/utils.js');
|
|
6
|
+
var bip32 = require('@scure/bip32');
|
|
7
|
+
var base = require('@scure/base');
|
|
11
8
|
var sha256 = require('@noble/hashes/sha256');
|
|
12
9
|
var ripemd160 = require('@noble/hashes/ripemd160');
|
|
13
10
|
var viem = require('viem');
|
|
@@ -134,8 +131,8 @@ var TESTNET_NETWORKS = {
|
|
|
134
131
|
var USDT_ADDRESSES = {
|
|
135
132
|
ethereum: {
|
|
136
133
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
137
|
-
testnet: "
|
|
138
|
-
// Sepolia
|
|
134
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
135
|
+
// Sepolia (Test Tether USD)
|
|
139
136
|
},
|
|
140
137
|
tron: {
|
|
141
138
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -153,11 +150,11 @@ var USDT_ADDRESSES = {
|
|
|
153
150
|
}
|
|
154
151
|
};
|
|
155
152
|
var DERIVATION_PATHS = {
|
|
156
|
-
bitcoin: "m/
|
|
153
|
+
bitcoin: "m/84'/0'/0'/0",
|
|
157
154
|
ethereum: "m/44'/60'/0'/0",
|
|
158
|
-
ton: "m/44'/607'/0'
|
|
155
|
+
ton: "m/44'/607'/0'",
|
|
159
156
|
tron: "m/44'/195'/0'/0",
|
|
160
|
-
solana: "m/44'/501'/0'
|
|
157
|
+
solana: "m/44'/501'/0'",
|
|
161
158
|
spark: "m/44'/998'/0'/0"
|
|
162
159
|
};
|
|
163
160
|
function getNetworkConfig(network, isTestnet = false) {
|
|
@@ -235,8 +232,27 @@ var WdkApiClient = class {
|
|
|
235
232
|
constructor(config) {
|
|
236
233
|
this.config = {
|
|
237
234
|
baseUrl: config.baseUrl,
|
|
238
|
-
timeout: config.timeout || 3e4
|
|
235
|
+
timeout: config.timeout || 3e4,
|
|
236
|
+
authToken: config.authToken
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Set or update the auth token for authenticated requests
|
|
241
|
+
*/
|
|
242
|
+
setAuthToken(token) {
|
|
243
|
+
this.config.authToken = token;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Build headers for API requests, including Authorization when available
|
|
247
|
+
*/
|
|
248
|
+
getHeaders() {
|
|
249
|
+
const headers = {
|
|
250
|
+
"Content-Type": "application/json"
|
|
239
251
|
};
|
|
252
|
+
if (this.config.authToken) {
|
|
253
|
+
headers["Authorization"] = `Bearer ${this.config.authToken}`;
|
|
254
|
+
}
|
|
255
|
+
return headers;
|
|
240
256
|
}
|
|
241
257
|
/**
|
|
242
258
|
* Generate a new BIP-39 seed phrase using Tether WDK
|
|
@@ -245,9 +261,7 @@ var WdkApiClient = class {
|
|
|
245
261
|
try {
|
|
246
262
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
|
|
247
263
|
method: "POST",
|
|
248
|
-
headers:
|
|
249
|
-
"Content-Type": "application/json"
|
|
250
|
-
}
|
|
264
|
+
headers: this.getHeaders()
|
|
251
265
|
});
|
|
252
266
|
return await response.json();
|
|
253
267
|
} catch (error) {
|
|
@@ -264,9 +278,7 @@ var WdkApiClient = class {
|
|
|
264
278
|
try {
|
|
265
279
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
|
|
266
280
|
method: "POST",
|
|
267
|
-
headers:
|
|
268
|
-
"Content-Type": "application/json"
|
|
269
|
-
},
|
|
281
|
+
headers: this.getHeaders(),
|
|
270
282
|
body: JSON.stringify({ seed })
|
|
271
283
|
});
|
|
272
284
|
return await response.json();
|
|
@@ -280,14 +292,12 @@ var WdkApiClient = class {
|
|
|
280
292
|
/**
|
|
281
293
|
* Derive address for a specific chain using Tether WDK
|
|
282
294
|
*/
|
|
283
|
-
async deriveAddress(seed,
|
|
295
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
284
296
|
try {
|
|
285
297
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
286
298
|
method: "POST",
|
|
287
|
-
headers:
|
|
288
|
-
|
|
289
|
-
},
|
|
290
|
-
body: JSON.stringify({ seed, chain: chain2, network })
|
|
299
|
+
headers: this.getHeaders(),
|
|
300
|
+
body: JSON.stringify({ seed, chain, network })
|
|
291
301
|
});
|
|
292
302
|
return await response.json();
|
|
293
303
|
} catch (error) {
|
|
@@ -304,9 +314,7 @@ var WdkApiClient = class {
|
|
|
304
314
|
try {
|
|
305
315
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
|
|
306
316
|
method: "POST",
|
|
307
|
-
headers:
|
|
308
|
-
"Content-Type": "application/json"
|
|
309
|
-
},
|
|
317
|
+
headers: this.getHeaders(),
|
|
310
318
|
body: JSON.stringify({ seed, network })
|
|
311
319
|
});
|
|
312
320
|
return await response.json();
|
|
@@ -320,14 +328,12 @@ var WdkApiClient = class {
|
|
|
320
328
|
/**
|
|
321
329
|
* Send a transaction on a specific chain using Tether WDK
|
|
322
330
|
*/
|
|
323
|
-
async sendTransaction(seed,
|
|
331
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
324
332
|
try {
|
|
325
333
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
326
334
|
method: "POST",
|
|
327
|
-
headers:
|
|
328
|
-
|
|
329
|
-
},
|
|
330
|
-
body: JSON.stringify({ seed, chain: chain2, to, amount, network })
|
|
335
|
+
headers: this.getHeaders(),
|
|
336
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
331
337
|
});
|
|
332
338
|
return await response.json();
|
|
333
339
|
} catch (error) {
|
|
@@ -341,14 +347,12 @@ var WdkApiClient = class {
|
|
|
341
347
|
* Get transaction history for an address on a specific chain
|
|
342
348
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
343
349
|
*/
|
|
344
|
-
async getTransactionHistory(seed,
|
|
350
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
345
351
|
try {
|
|
346
352
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
347
353
|
method: "POST",
|
|
348
|
-
headers:
|
|
349
|
-
|
|
350
|
-
},
|
|
351
|
-
body: JSON.stringify({ seed, chain: chain2, network, limit })
|
|
354
|
+
headers: this.getHeaders(),
|
|
355
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
352
356
|
});
|
|
353
357
|
return await response.json();
|
|
354
358
|
} catch (error) {
|
|
@@ -362,14 +366,12 @@ var WdkApiClient = class {
|
|
|
362
366
|
* Get transaction status by hash
|
|
363
367
|
* Fetches from blockchain explorers to check confirmation status
|
|
364
368
|
*/
|
|
365
|
-
async getTransactionStatus(txHash,
|
|
369
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
366
370
|
try {
|
|
367
371
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
368
372
|
method: "POST",
|
|
369
|
-
headers:
|
|
370
|
-
|
|
371
|
-
},
|
|
372
|
-
body: JSON.stringify({ txHash, chain: chain2, network })
|
|
373
|
+
headers: this.getHeaders(),
|
|
374
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
373
375
|
});
|
|
374
376
|
return await response.json();
|
|
375
377
|
} catch (error) {
|
|
@@ -382,605 +384,23 @@ var WdkApiClient = class {
|
|
|
382
384
|
};
|
|
383
385
|
var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
384
386
|
var wdkApiClient = null;
|
|
385
|
-
function getWdkApiClient(baseUrl) {
|
|
387
|
+
function getWdkApiClient(baseUrl, authToken) {
|
|
386
388
|
if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
|
|
387
389
|
wdkApiClient = new WdkApiClient({
|
|
388
|
-
baseUrl: baseUrl || DEFAULT_API_URL
|
|
390
|
+
baseUrl: baseUrl || DEFAULT_API_URL,
|
|
391
|
+
authToken
|
|
389
392
|
});
|
|
390
393
|
}
|
|
391
394
|
return wdkApiClient;
|
|
392
395
|
}
|
|
393
|
-
|
|
394
|
-
// node_modules/@scure/base/index.js
|
|
395
|
-
function isBytes(a) {
|
|
396
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
397
|
-
}
|
|
398
|
-
function isArrayOf(isString, arr) {
|
|
399
|
-
if (!Array.isArray(arr))
|
|
400
|
-
return false;
|
|
401
|
-
if (arr.length === 0)
|
|
402
|
-
return true;
|
|
403
|
-
if (isString) {
|
|
404
|
-
return arr.every((item) => typeof item === "string");
|
|
405
|
-
} else {
|
|
406
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
function afn(input) {
|
|
410
|
-
if (typeof input !== "function")
|
|
411
|
-
throw new Error("function expected");
|
|
412
|
-
return true;
|
|
413
|
-
}
|
|
414
|
-
function astr(label, input) {
|
|
415
|
-
if (typeof input !== "string")
|
|
416
|
-
throw new Error(`${label}: string expected`);
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
function anumber(n) {
|
|
420
|
-
if (!Number.isSafeInteger(n))
|
|
421
|
-
throw new Error(`invalid integer: ${n}`);
|
|
422
|
-
}
|
|
423
|
-
function aArr(input) {
|
|
424
|
-
if (!Array.isArray(input))
|
|
425
|
-
throw new Error("array expected");
|
|
426
|
-
}
|
|
427
|
-
function astrArr(label, input) {
|
|
428
|
-
if (!isArrayOf(true, input))
|
|
429
|
-
throw new Error(`${label}: array of strings expected`);
|
|
430
|
-
}
|
|
431
|
-
function anumArr(label, input) {
|
|
432
|
-
if (!isArrayOf(false, input))
|
|
433
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
434
|
-
}
|
|
435
|
-
// @__NO_SIDE_EFFECTS__
|
|
436
|
-
function chain(...args) {
|
|
437
|
-
const id = (a) => a;
|
|
438
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
439
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
440
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
441
|
-
return { encode, decode };
|
|
442
|
-
}
|
|
443
|
-
// @__NO_SIDE_EFFECTS__
|
|
444
|
-
function alphabet(letters) {
|
|
445
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
446
|
-
const len = lettersA.length;
|
|
447
|
-
astrArr("alphabet", lettersA);
|
|
448
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
449
|
-
return {
|
|
450
|
-
encode: (digits) => {
|
|
451
|
-
aArr(digits);
|
|
452
|
-
return digits.map((i) => {
|
|
453
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
454
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
455
|
-
return lettersA[i];
|
|
456
|
-
});
|
|
457
|
-
},
|
|
458
|
-
decode: (input) => {
|
|
459
|
-
aArr(input);
|
|
460
|
-
return input.map((letter) => {
|
|
461
|
-
astr("alphabet.decode", letter);
|
|
462
|
-
const i = indexes.get(letter);
|
|
463
|
-
if (i === void 0)
|
|
464
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
465
|
-
return i;
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
// @__NO_SIDE_EFFECTS__
|
|
471
|
-
function join(separator = "") {
|
|
472
|
-
astr("join", separator);
|
|
473
|
-
return {
|
|
474
|
-
encode: (from) => {
|
|
475
|
-
astrArr("join.decode", from);
|
|
476
|
-
return from.join(separator);
|
|
477
|
-
},
|
|
478
|
-
decode: (to) => {
|
|
479
|
-
astr("join.decode", to);
|
|
480
|
-
return to.split(separator);
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
function convertRadix(data, from, to) {
|
|
485
|
-
if (from < 2)
|
|
486
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
487
|
-
if (to < 2)
|
|
488
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
489
|
-
aArr(data);
|
|
490
|
-
if (!data.length)
|
|
491
|
-
return [];
|
|
492
|
-
let pos = 0;
|
|
493
|
-
const res = [];
|
|
494
|
-
const digits = Array.from(data, (d) => {
|
|
495
|
-
anumber(d);
|
|
496
|
-
if (d < 0 || d >= from)
|
|
497
|
-
throw new Error(`invalid integer: ${d}`);
|
|
498
|
-
return d;
|
|
499
|
-
});
|
|
500
|
-
const dlen = digits.length;
|
|
501
|
-
while (true) {
|
|
502
|
-
let carry = 0;
|
|
503
|
-
let done = true;
|
|
504
|
-
for (let i = pos; i < dlen; i++) {
|
|
505
|
-
const digit = digits[i];
|
|
506
|
-
const fromCarry = from * carry;
|
|
507
|
-
const digitBase = fromCarry + digit;
|
|
508
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
509
|
-
throw new Error("convertRadix: carry overflow");
|
|
510
|
-
}
|
|
511
|
-
const div = digitBase / to;
|
|
512
|
-
carry = digitBase % to;
|
|
513
|
-
const rounded = Math.floor(div);
|
|
514
|
-
digits[i] = rounded;
|
|
515
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
516
|
-
throw new Error("convertRadix: carry overflow");
|
|
517
|
-
if (!done)
|
|
518
|
-
continue;
|
|
519
|
-
else if (!rounded)
|
|
520
|
-
pos = i;
|
|
521
|
-
else
|
|
522
|
-
done = false;
|
|
523
|
-
}
|
|
524
|
-
res.push(carry);
|
|
525
|
-
if (done)
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
529
|
-
res.push(0);
|
|
530
|
-
return res.reverse();
|
|
531
|
-
}
|
|
532
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
533
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
534
|
-
var powers = /* @__PURE__ */ (() => {
|
|
535
|
-
let res = [];
|
|
536
|
-
for (let i = 0; i < 40; i++)
|
|
537
|
-
res.push(2 ** i);
|
|
538
|
-
return res;
|
|
539
|
-
})();
|
|
540
|
-
function convertRadix2(data, from, to, padding) {
|
|
541
|
-
aArr(data);
|
|
542
|
-
if (from <= 0 || from > 32)
|
|
543
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
544
|
-
if (to <= 0 || to > 32)
|
|
545
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
546
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
547
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
548
|
-
}
|
|
549
|
-
let carry = 0;
|
|
550
|
-
let pos = 0;
|
|
551
|
-
const max = powers[from];
|
|
552
|
-
const mask = powers[to] - 1;
|
|
553
|
-
const res = [];
|
|
554
|
-
for (const n of data) {
|
|
555
|
-
anumber(n);
|
|
556
|
-
if (n >= max)
|
|
557
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
558
|
-
carry = carry << from | n;
|
|
559
|
-
if (pos + from > 32)
|
|
560
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
561
|
-
pos += from;
|
|
562
|
-
for (; pos >= to; pos -= to)
|
|
563
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
564
|
-
const pow = powers[pos];
|
|
565
|
-
if (pow === void 0)
|
|
566
|
-
throw new Error("invalid carry");
|
|
567
|
-
carry &= pow - 1;
|
|
568
|
-
}
|
|
569
|
-
carry = carry << to - pos & mask;
|
|
570
|
-
if (!padding && pos >= from)
|
|
571
|
-
throw new Error("Excess padding");
|
|
572
|
-
if (!padding && carry > 0)
|
|
573
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
574
|
-
if (padding && pos > 0)
|
|
575
|
-
res.push(carry >>> 0);
|
|
576
|
-
return res;
|
|
577
|
-
}
|
|
578
|
-
// @__NO_SIDE_EFFECTS__
|
|
579
|
-
function radix(num) {
|
|
580
|
-
anumber(num);
|
|
581
|
-
const _256 = 2 ** 8;
|
|
582
|
-
return {
|
|
583
|
-
encode: (bytes) => {
|
|
584
|
-
if (!isBytes(bytes))
|
|
585
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
586
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
587
|
-
},
|
|
588
|
-
decode: (digits) => {
|
|
589
|
-
anumArr("radix.decode", digits);
|
|
590
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
// @__NO_SIDE_EFFECTS__
|
|
595
|
-
function radix2(bits, revPadding = false) {
|
|
596
|
-
anumber(bits);
|
|
597
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
598
|
-
throw new Error("radix2: carry overflow");
|
|
599
|
-
return {
|
|
600
|
-
encode: (bytes) => {
|
|
601
|
-
if (!isBytes(bytes))
|
|
602
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
603
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
604
|
-
},
|
|
605
|
-
decode: (digits) => {
|
|
606
|
-
anumArr("radix2.decode", digits);
|
|
607
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
function unsafeWrapper(fn) {
|
|
612
|
-
afn(fn);
|
|
613
|
-
return function(...args) {
|
|
614
|
-
try {
|
|
615
|
-
return fn.apply(null, args);
|
|
616
|
-
} catch (e) {
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
function checksum(len, fn) {
|
|
621
|
-
anumber(len);
|
|
622
|
-
afn(fn);
|
|
623
|
-
return {
|
|
624
|
-
encode(data) {
|
|
625
|
-
if (!isBytes(data))
|
|
626
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
627
|
-
const sum = fn(data).slice(0, len);
|
|
628
|
-
const res = new Uint8Array(data.length + len);
|
|
629
|
-
res.set(data);
|
|
630
|
-
res.set(sum, data.length);
|
|
631
|
-
return res;
|
|
632
|
-
},
|
|
633
|
-
decode(data) {
|
|
634
|
-
if (!isBytes(data))
|
|
635
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
636
|
-
const payload = data.slice(0, -len);
|
|
637
|
-
const oldChecksum = data.slice(-len);
|
|
638
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
639
|
-
for (let i = 0; i < len; i++)
|
|
640
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
641
|
-
throw new Error("Invalid checksum");
|
|
642
|
-
return payload;
|
|
643
|
-
}
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
647
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
648
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
649
|
-
var base58check = createBase58check;
|
|
650
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
651
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
652
|
-
function bech32Polymod(pre) {
|
|
653
|
-
const b = pre >> 25;
|
|
654
|
-
let chk = (pre & 33554431) << 5;
|
|
655
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
656
|
-
if ((b >> i & 1) === 1)
|
|
657
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
658
|
-
}
|
|
659
|
-
return chk;
|
|
660
|
-
}
|
|
661
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
662
|
-
const len = prefix.length;
|
|
663
|
-
let chk = 1;
|
|
664
|
-
for (let i = 0; i < len; i++) {
|
|
665
|
-
const c = prefix.charCodeAt(i);
|
|
666
|
-
if (c < 33 || c > 126)
|
|
667
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
668
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
669
|
-
}
|
|
670
|
-
chk = bech32Polymod(chk);
|
|
671
|
-
for (let i = 0; i < len; i++)
|
|
672
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
673
|
-
for (let v of words)
|
|
674
|
-
chk = bech32Polymod(chk) ^ v;
|
|
675
|
-
for (let i = 0; i < 6; i++)
|
|
676
|
-
chk = bech32Polymod(chk);
|
|
677
|
-
chk ^= encodingConst;
|
|
678
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
679
|
-
}
|
|
680
|
-
// @__NO_SIDE_EFFECTS__
|
|
681
|
-
function genBech32(encoding) {
|
|
682
|
-
const ENCODING_CONST = 1 ;
|
|
683
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
684
|
-
const fromWords = _words.decode;
|
|
685
|
-
const toWords = _words.encode;
|
|
686
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
687
|
-
function encode(prefix, words, limit = 90) {
|
|
688
|
-
astr("bech32.encode prefix", prefix);
|
|
689
|
-
if (isBytes(words))
|
|
690
|
-
words = Array.from(words);
|
|
691
|
-
anumArr("bech32.encode", words);
|
|
692
|
-
const plen = prefix.length;
|
|
693
|
-
if (plen === 0)
|
|
694
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
695
|
-
const actualLength = plen + 7 + words.length;
|
|
696
|
-
if (limit !== false && actualLength > limit)
|
|
697
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
698
|
-
const lowered = prefix.toLowerCase();
|
|
699
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
700
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
701
|
-
}
|
|
702
|
-
function decode(str, limit = 90) {
|
|
703
|
-
astr("bech32.decode input", str);
|
|
704
|
-
const slen = str.length;
|
|
705
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
706
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
707
|
-
const lowered = str.toLowerCase();
|
|
708
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
709
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
710
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
711
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
712
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
713
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
714
|
-
const data = lowered.slice(sepIndex + 1);
|
|
715
|
-
if (data.length < 6)
|
|
716
|
-
throw new Error("Data must be at least 6 characters long");
|
|
717
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
718
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
719
|
-
if (!data.endsWith(sum))
|
|
720
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
721
|
-
return { prefix, words };
|
|
722
|
-
}
|
|
723
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
724
|
-
function decodeToBytes(str) {
|
|
725
|
-
const { prefix, words } = decode(str, false);
|
|
726
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
727
|
-
}
|
|
728
|
-
function encodeFromBytes(prefix, bytes) {
|
|
729
|
-
return encode(prefix, toWords(bytes));
|
|
730
|
-
}
|
|
731
|
-
return {
|
|
732
|
-
encode,
|
|
733
|
-
decode,
|
|
734
|
-
encodeFromBytes,
|
|
735
|
-
decodeToBytes,
|
|
736
|
-
decodeUnsafe,
|
|
737
|
-
fromWords,
|
|
738
|
-
fromWordsUnsafe,
|
|
739
|
-
toWords
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
743
|
-
|
|
744
|
-
// node_modules/@scure/bip32/index.js
|
|
745
|
-
var Point = secp256k1_js.secp256k1.Point;
|
|
746
|
-
var { Fn } = Point;
|
|
747
|
-
var base58check2 = createBase58check(sha2_js.sha256);
|
|
748
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
749
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
750
|
-
var HARDENED_OFFSET = 2147483648;
|
|
751
|
-
var hash160 = (data) => legacy_js.ripemd160(sha2_js.sha256(data));
|
|
752
|
-
var fromU32 = (data) => utils_js.createView(data).getUint32(0, false);
|
|
753
|
-
var toU32 = (n) => {
|
|
754
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
755
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
756
|
-
}
|
|
757
|
-
const buf = new Uint8Array(4);
|
|
758
|
-
utils_js.createView(buf).setUint32(0, n, false);
|
|
759
|
-
return buf;
|
|
760
|
-
};
|
|
761
|
-
var HDKey = class _HDKey {
|
|
762
|
-
get fingerprint() {
|
|
763
|
-
if (!this.pubHash) {
|
|
764
|
-
throw new Error("No publicKey set!");
|
|
765
|
-
}
|
|
766
|
-
return fromU32(this.pubHash);
|
|
767
|
-
}
|
|
768
|
-
get identifier() {
|
|
769
|
-
return this.pubHash;
|
|
770
|
-
}
|
|
771
|
-
get pubKeyHash() {
|
|
772
|
-
return this.pubHash;
|
|
773
|
-
}
|
|
774
|
-
get privateKey() {
|
|
775
|
-
return this._privateKey || null;
|
|
776
|
-
}
|
|
777
|
-
get publicKey() {
|
|
778
|
-
return this._publicKey || null;
|
|
779
|
-
}
|
|
780
|
-
get privateExtendedKey() {
|
|
781
|
-
const priv = this._privateKey;
|
|
782
|
-
if (!priv) {
|
|
783
|
-
throw new Error("No private key");
|
|
784
|
-
}
|
|
785
|
-
return base58check2.encode(this.serialize(this.versions.private, utils_js.concatBytes(Uint8Array.of(0), priv)));
|
|
786
|
-
}
|
|
787
|
-
get publicExtendedKey() {
|
|
788
|
-
if (!this._publicKey) {
|
|
789
|
-
throw new Error("No public key");
|
|
790
|
-
}
|
|
791
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
792
|
-
}
|
|
793
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
794
|
-
utils_js.abytes(seed);
|
|
795
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
796
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
797
|
-
}
|
|
798
|
-
const I = hmac_js.hmac(sha2_js.sha512, MASTER_SECRET, seed);
|
|
799
|
-
const privateKey = I.slice(0, 32);
|
|
800
|
-
const chainCode = I.slice(32);
|
|
801
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
802
|
-
}
|
|
803
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
804
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
805
|
-
const keyView = utils_js.createView(keyBuffer);
|
|
806
|
-
const version = keyView.getUint32(0, false);
|
|
807
|
-
const opt = {
|
|
808
|
-
versions,
|
|
809
|
-
depth: keyBuffer[4],
|
|
810
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
811
|
-
index: keyView.getUint32(9, false),
|
|
812
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
813
|
-
};
|
|
814
|
-
const key = keyBuffer.slice(45);
|
|
815
|
-
const isPriv = key[0] === 0;
|
|
816
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
817
|
-
throw new Error("Version mismatch");
|
|
818
|
-
}
|
|
819
|
-
if (isPriv) {
|
|
820
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
821
|
-
} else {
|
|
822
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
static fromJSON(json) {
|
|
826
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
827
|
-
}
|
|
828
|
-
versions;
|
|
829
|
-
depth = 0;
|
|
830
|
-
index = 0;
|
|
831
|
-
chainCode = null;
|
|
832
|
-
parentFingerprint = 0;
|
|
833
|
-
_privateKey;
|
|
834
|
-
_publicKey;
|
|
835
|
-
pubHash;
|
|
836
|
-
constructor(opt) {
|
|
837
|
-
if (!opt || typeof opt !== "object") {
|
|
838
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
839
|
-
}
|
|
840
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
841
|
-
this.depth = opt.depth || 0;
|
|
842
|
-
this.chainCode = opt.chainCode || null;
|
|
843
|
-
this.index = opt.index || 0;
|
|
844
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
845
|
-
if (!this.depth) {
|
|
846
|
-
if (this.parentFingerprint || this.index) {
|
|
847
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
if (this.depth > 255) {
|
|
851
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
852
|
-
}
|
|
853
|
-
if (opt.publicKey && opt.privateKey) {
|
|
854
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
855
|
-
}
|
|
856
|
-
if (opt.privateKey) {
|
|
857
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
858
|
-
throw new Error("Invalid private key");
|
|
859
|
-
this._privateKey = opt.privateKey;
|
|
860
|
-
this._publicKey = secp256k1_js.secp256k1.getPublicKey(opt.privateKey, true);
|
|
861
|
-
} else if (opt.publicKey) {
|
|
862
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
863
|
-
} else {
|
|
864
|
-
throw new Error("HDKey: no public or private key provided");
|
|
865
|
-
}
|
|
866
|
-
this.pubHash = hash160(this._publicKey);
|
|
867
|
-
}
|
|
868
|
-
derive(path) {
|
|
869
|
-
if (!/^[mM]'?/.test(path)) {
|
|
870
|
-
throw new Error('Path must start with "m" or "M"');
|
|
871
|
-
}
|
|
872
|
-
if (/^[mM]'?$/.test(path)) {
|
|
873
|
-
return this;
|
|
874
|
-
}
|
|
875
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
876
|
-
let child = this;
|
|
877
|
-
for (const c of parts) {
|
|
878
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
879
|
-
const m1 = m && m[1];
|
|
880
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
881
|
-
throw new Error("invalid child index: " + c);
|
|
882
|
-
let idx = +m1;
|
|
883
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
884
|
-
throw new Error("Invalid index");
|
|
885
|
-
}
|
|
886
|
-
if (m[2] === "'") {
|
|
887
|
-
idx += HARDENED_OFFSET;
|
|
888
|
-
}
|
|
889
|
-
child = child.deriveChild(idx);
|
|
890
|
-
}
|
|
891
|
-
return child;
|
|
892
|
-
}
|
|
893
|
-
deriveChild(index) {
|
|
894
|
-
if (!this._publicKey || !this.chainCode) {
|
|
895
|
-
throw new Error("No publicKey or chainCode set");
|
|
896
|
-
}
|
|
897
|
-
let data = toU32(index);
|
|
898
|
-
if (index >= HARDENED_OFFSET) {
|
|
899
|
-
const priv = this._privateKey;
|
|
900
|
-
if (!priv) {
|
|
901
|
-
throw new Error("Could not derive hardened child key");
|
|
902
|
-
}
|
|
903
|
-
data = utils_js.concatBytes(Uint8Array.of(0), priv, data);
|
|
904
|
-
} else {
|
|
905
|
-
data = utils_js.concatBytes(this._publicKey, data);
|
|
906
|
-
}
|
|
907
|
-
const I = hmac_js.hmac(sha2_js.sha512, this.chainCode, data);
|
|
908
|
-
const childTweak = I.slice(0, 32);
|
|
909
|
-
const chainCode = I.slice(32);
|
|
910
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
911
|
-
throw new Error("Tweak bigger than curve order");
|
|
912
|
-
}
|
|
913
|
-
const opt = {
|
|
914
|
-
versions: this.versions,
|
|
915
|
-
chainCode,
|
|
916
|
-
depth: this.depth + 1,
|
|
917
|
-
parentFingerprint: this.fingerprint,
|
|
918
|
-
index
|
|
919
|
-
};
|
|
920
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
921
|
-
try {
|
|
922
|
-
if (this._privateKey) {
|
|
923
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
924
|
-
if (!Fn.isValidNot0(added)) {
|
|
925
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
926
|
-
}
|
|
927
|
-
opt.privateKey = Fn.toBytes(added);
|
|
928
|
-
} else {
|
|
929
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
930
|
-
if (added.equals(Point.ZERO)) {
|
|
931
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
932
|
-
}
|
|
933
|
-
opt.publicKey = added.toBytes(true);
|
|
934
|
-
}
|
|
935
|
-
return new _HDKey(opt);
|
|
936
|
-
} catch (err) {
|
|
937
|
-
return this.deriveChild(index + 1);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
sign(hash) {
|
|
941
|
-
if (!this._privateKey) {
|
|
942
|
-
throw new Error("No privateKey set!");
|
|
943
|
-
}
|
|
944
|
-
utils_js.abytes(hash, 32);
|
|
945
|
-
return secp256k1_js.secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
946
|
-
}
|
|
947
|
-
verify(hash, signature) {
|
|
948
|
-
utils_js.abytes(hash, 32);
|
|
949
|
-
utils_js.abytes(signature, 64);
|
|
950
|
-
if (!this._publicKey) {
|
|
951
|
-
throw new Error("No publicKey set!");
|
|
952
|
-
}
|
|
953
|
-
return secp256k1_js.secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
954
|
-
}
|
|
955
|
-
wipePrivateData() {
|
|
956
|
-
if (this._privateKey) {
|
|
957
|
-
this._privateKey.fill(0);
|
|
958
|
-
this._privateKey = void 0;
|
|
959
|
-
}
|
|
960
|
-
return this;
|
|
961
|
-
}
|
|
962
|
-
toJSON() {
|
|
963
|
-
return {
|
|
964
|
-
xpriv: this.privateExtendedKey,
|
|
965
|
-
xpub: this.publicExtendedKey
|
|
966
|
-
};
|
|
967
|
-
}
|
|
968
|
-
serialize(version, key) {
|
|
969
|
-
if (!this.chainCode) {
|
|
970
|
-
throw new Error("No chainCode set");
|
|
971
|
-
}
|
|
972
|
-
utils_js.abytes(key, 33);
|
|
973
|
-
return utils_js.concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
974
|
-
}
|
|
975
|
-
};
|
|
976
396
|
var DERIVATION_PATHS2 = {
|
|
977
|
-
ethereum:
|
|
978
|
-
bitcoin_mainnet:
|
|
397
|
+
ethereum: `${DERIVATION_PATHS.ethereum}/0`,
|
|
398
|
+
bitcoin_mainnet: `${DERIVATION_PATHS.bitcoin}/0`,
|
|
979
399
|
bitcoin_testnet: "m/84'/1'/0'/0/0",
|
|
980
|
-
ton:
|
|
981
|
-
tron:
|
|
982
|
-
solana:
|
|
983
|
-
spark:
|
|
400
|
+
ton: `${DERIVATION_PATHS.ton}/0'/0'`,
|
|
401
|
+
tron: `${DERIVATION_PATHS.tron}/0`,
|
|
402
|
+
solana: `${DERIVATION_PATHS.solana}/0'`,
|
|
403
|
+
spark: `${DERIVATION_PATHS.spark}/0`
|
|
984
404
|
};
|
|
985
405
|
function deriveEthereumAddress(seed) {
|
|
986
406
|
const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
|
|
@@ -989,7 +409,7 @@ function deriveEthereumAddress(seed) {
|
|
|
989
409
|
function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
990
410
|
try {
|
|
991
411
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
992
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
412
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
993
413
|
const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
|
|
994
414
|
const child = hdKey.derive(path);
|
|
995
415
|
if (!child.publicKey) {
|
|
@@ -997,10 +417,10 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
997
417
|
}
|
|
998
418
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
999
419
|
const witnessVersion = 0;
|
|
1000
|
-
const words = bech32.toWords(pubKeyHash);
|
|
420
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1001
421
|
words.unshift(witnessVersion);
|
|
1002
422
|
const hrp = network === "testnet" ? "tb" : "bc";
|
|
1003
|
-
const address = bech32.encode(hrp, words);
|
|
423
|
+
const address = base.bech32.encode(hrp, words);
|
|
1004
424
|
return address;
|
|
1005
425
|
} catch (error) {
|
|
1006
426
|
console.error("Bitcoin address derivation failed:", error);
|
|
@@ -1073,7 +493,7 @@ function deriveTronAddress(seed) {
|
|
|
1073
493
|
for (let i = 0; i < 20; i++) {
|
|
1074
494
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1075
495
|
}
|
|
1076
|
-
const tronBase58check = base58check(sha256.sha256);
|
|
496
|
+
const tronBase58check = base.base58check(sha256.sha256);
|
|
1077
497
|
return tronBase58check.encode(addressBytes);
|
|
1078
498
|
} catch (error) {
|
|
1079
499
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1083,17 +503,17 @@ function deriveTronAddress(seed) {
|
|
|
1083
503
|
function deriveSparkAddress(seed, network = "mainnet") {
|
|
1084
504
|
try {
|
|
1085
505
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
1086
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
506
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
1087
507
|
const child = hdKey.derive(DERIVATION_PATHS2.spark);
|
|
1088
508
|
if (!child.publicKey) {
|
|
1089
509
|
throw new Error("Failed to derive public key");
|
|
1090
510
|
}
|
|
1091
511
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
1092
512
|
const witnessVersion = 0;
|
|
1093
|
-
const words = bech32.toWords(pubKeyHash);
|
|
513
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1094
514
|
words.unshift(witnessVersion);
|
|
1095
515
|
const hrp = network === "testnet" ? "tsp" : "sp";
|
|
1096
|
-
const address = bech32.encode(hrp, words);
|
|
516
|
+
const address = base.bech32.encode(hrp, words);
|
|
1097
517
|
return address;
|
|
1098
518
|
} catch (error) {
|
|
1099
519
|
console.error("Spark address derivation failed:", error);
|
|
@@ -1189,9 +609,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1189
609
|
"no route": "NETWORK_ERROR"
|
|
1190
610
|
}
|
|
1191
611
|
};
|
|
1192
|
-
function parseChainError(
|
|
612
|
+
function parseChainError(chain, errorMessage) {
|
|
1193
613
|
const errorLower = errorMessage.toLowerCase();
|
|
1194
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
614
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1195
615
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1196
616
|
if (errorLower.includes(pattern)) {
|
|
1197
617
|
return code;
|
|
@@ -1329,38 +749,38 @@ var ZubariWdkService = class {
|
|
|
1329
749
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1330
750
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1331
751
|
*/
|
|
1332
|
-
async deriveAddress(seed,
|
|
752
|
+
async deriveAddress(seed, chain) {
|
|
1333
753
|
await this.initialize();
|
|
1334
|
-
const path = this.getDerivationPath(
|
|
754
|
+
const path = this.getDerivationPath(chain);
|
|
1335
755
|
try {
|
|
1336
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
756
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1337
757
|
if (response.success && response.address) {
|
|
1338
758
|
return {
|
|
1339
|
-
chain
|
|
759
|
+
chain,
|
|
1340
760
|
address: response.address,
|
|
1341
761
|
path: response.path || path
|
|
1342
762
|
};
|
|
1343
763
|
}
|
|
1344
764
|
} catch (error) {
|
|
1345
|
-
console.warn(`API address derivation failed for ${
|
|
1346
|
-
if (
|
|
1347
|
-
return this.deriveBrowserAddress(seed,
|
|
765
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
766
|
+
if (chain === "ethereum") {
|
|
767
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1348
768
|
}
|
|
1349
769
|
}
|
|
1350
770
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1351
771
|
try {
|
|
1352
772
|
const wdk = this.nativeWdkService;
|
|
1353
773
|
await wdk.initialize(seed);
|
|
1354
|
-
return await wdk.deriveAddress(
|
|
774
|
+
return await wdk.deriveAddress(chain);
|
|
1355
775
|
} catch (error) {
|
|
1356
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
776
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1357
777
|
}
|
|
1358
778
|
}
|
|
1359
|
-
if (
|
|
1360
|
-
return this.deriveBrowserAddress(seed,
|
|
779
|
+
if (chain === "ethereum") {
|
|
780
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1361
781
|
}
|
|
1362
782
|
throw new Error(
|
|
1363
|
-
`WDK API required for ${
|
|
783
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1364
784
|
);
|
|
1365
785
|
}
|
|
1366
786
|
/**
|
|
@@ -1440,13 +860,13 @@ var ZubariWdkService = class {
|
|
|
1440
860
|
/**
|
|
1441
861
|
* Get fee rates for a chain
|
|
1442
862
|
*/
|
|
1443
|
-
async getFeeRates(seed,
|
|
863
|
+
async getFeeRates(seed, chain) {
|
|
1444
864
|
await this.initialize();
|
|
1445
865
|
try {
|
|
1446
866
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1447
867
|
method: "POST",
|
|
1448
868
|
headers: { "Content-Type": "application/json" },
|
|
1449
|
-
body: JSON.stringify({ seed, chain
|
|
869
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1450
870
|
});
|
|
1451
871
|
if (response.ok) {
|
|
1452
872
|
const data = await response.json();
|
|
@@ -1455,20 +875,20 @@ var ZubariWdkService = class {
|
|
|
1455
875
|
}
|
|
1456
876
|
}
|
|
1457
877
|
} catch (error) {
|
|
1458
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
878
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1459
879
|
}
|
|
1460
880
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1461
881
|
}
|
|
1462
882
|
/**
|
|
1463
883
|
* Estimate transaction fee
|
|
1464
884
|
*/
|
|
1465
|
-
async estimateFee(seed,
|
|
885
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1466
886
|
await this.initialize();
|
|
1467
887
|
try {
|
|
1468
888
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1469
889
|
method: "POST",
|
|
1470
890
|
headers: { "Content-Type": "application/json" },
|
|
1471
|
-
body: JSON.stringify({ seed, chain
|
|
891
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1472
892
|
});
|
|
1473
893
|
if (response.ok) {
|
|
1474
894
|
const data = await response.json();
|
|
@@ -1477,9 +897,9 @@ var ZubariWdkService = class {
|
|
|
1477
897
|
}
|
|
1478
898
|
}
|
|
1479
899
|
} catch (error) {
|
|
1480
|
-
console.warn(`Failed to estimate fee for ${
|
|
900
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1481
901
|
}
|
|
1482
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
902
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1483
903
|
}
|
|
1484
904
|
/**
|
|
1485
905
|
* Send a transaction on any supported chain
|
|
@@ -1490,19 +910,14 @@ var ZubariWdkService = class {
|
|
|
1490
910
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1491
911
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1492
912
|
*/
|
|
1493
|
-
async sendTransaction(seed,
|
|
913
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1494
914
|
await this.initialize();
|
|
1495
915
|
const startTime = Date.now();
|
|
1496
|
-
console.log(`[ZubariWdkService] Sending ${chain2} transaction`, {
|
|
1497
|
-
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1498
|
-
amount,
|
|
1499
|
-
network: this.config.network
|
|
1500
|
-
});
|
|
1501
916
|
try {
|
|
1502
917
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1503
918
|
method: "POST",
|
|
1504
919
|
headers: { "Content-Type": "application/json" },
|
|
1505
|
-
body: JSON.stringify({ seed, chain
|
|
920
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1506
921
|
});
|
|
1507
922
|
const elapsed = Date.now() - startTime;
|
|
1508
923
|
if (response.ok) {
|
|
@@ -1512,22 +927,18 @@ var ZubariWdkService = class {
|
|
|
1512
927
|
txHash = txHash.hash;
|
|
1513
928
|
}
|
|
1514
929
|
if (txHash) {
|
|
1515
|
-
const isValid = this.validateTxHash(
|
|
930
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1516
931
|
if (!isValid) {
|
|
1517
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
932
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1518
933
|
}
|
|
1519
934
|
}
|
|
1520
|
-
console.log(`[ZubariWdkService] ${chain2} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1521
|
-
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1522
|
-
elapsed: `${elapsed}ms`
|
|
1523
|
-
});
|
|
1524
935
|
if (!data.success) {
|
|
1525
|
-
const errorCode2 = parseChainError(
|
|
936
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1526
937
|
return {
|
|
1527
938
|
success: false,
|
|
1528
939
|
error: data.error,
|
|
1529
940
|
errorCode: errorCode2,
|
|
1530
|
-
chain
|
|
941
|
+
chain
|
|
1531
942
|
};
|
|
1532
943
|
}
|
|
1533
944
|
return {
|
|
@@ -1536,47 +947,35 @@ var ZubariWdkService = class {
|
|
|
1536
947
|
from: data.from,
|
|
1537
948
|
to: data.to,
|
|
1538
949
|
amount: data.amount,
|
|
1539
|
-
chain: data.chain ||
|
|
950
|
+
chain: data.chain || chain,
|
|
1540
951
|
network: data.network || this.config.network
|
|
1541
952
|
};
|
|
1542
953
|
}
|
|
1543
954
|
const errorData = await response.json().catch(() => ({}));
|
|
1544
955
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1545
|
-
const errorCode = parseChainError(
|
|
1546
|
-
console.error(`[ZubariWdkService] ${chain2} transaction FAILED`, {
|
|
1547
|
-
status: response.status,
|
|
1548
|
-
error: errorMessage,
|
|
1549
|
-
errorCode,
|
|
1550
|
-
elapsed: `${elapsed}ms`
|
|
1551
|
-
});
|
|
956
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1552
957
|
return {
|
|
1553
958
|
success: false,
|
|
1554
959
|
error: errorMessage,
|
|
1555
960
|
errorCode,
|
|
1556
|
-
chain
|
|
961
|
+
chain
|
|
1557
962
|
};
|
|
1558
963
|
} catch (error) {
|
|
1559
|
-
const elapsed = Date.now() - startTime;
|
|
1560
964
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1561
|
-
const errorCode = parseChainError(
|
|
1562
|
-
console.error(`[ZubariWdkService] ${chain2} transaction ERROR`, {
|
|
1563
|
-
error: errorMessage,
|
|
1564
|
-
errorCode,
|
|
1565
|
-
elapsed: `${elapsed}ms`
|
|
1566
|
-
});
|
|
965
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1567
966
|
return {
|
|
1568
967
|
success: false,
|
|
1569
968
|
error: errorMessage,
|
|
1570
969
|
errorCode,
|
|
1571
|
-
chain
|
|
970
|
+
chain
|
|
1572
971
|
};
|
|
1573
972
|
}
|
|
1574
973
|
}
|
|
1575
974
|
/**
|
|
1576
975
|
* Validate transaction hash format for a specific chain
|
|
1577
976
|
*/
|
|
1578
|
-
validateTxHash(
|
|
1579
|
-
switch (
|
|
977
|
+
validateTxHash(chain, txHash) {
|
|
978
|
+
switch (chain) {
|
|
1580
979
|
case "ethereum":
|
|
1581
980
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1582
981
|
case "bitcoin":
|
|
@@ -1608,18 +1007,25 @@ var ZubariWdkService = class {
|
|
|
1608
1007
|
// ==========================================
|
|
1609
1008
|
// Private Helper Methods
|
|
1610
1009
|
// ==========================================
|
|
1611
|
-
getDerivationPath(
|
|
1612
|
-
const
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1010
|
+
getDerivationPath(chain) {
|
|
1011
|
+
const basePath = DERIVATION_PATHS[chain];
|
|
1012
|
+
if (chain === "bitcoin" && this.config.network === "testnet") {
|
|
1013
|
+
return "m/84'/1'/0'/0/0";
|
|
1014
|
+
}
|
|
1015
|
+
switch (chain) {
|
|
1016
|
+
case "ton":
|
|
1017
|
+
return `${basePath}/0'/0'`;
|
|
1018
|
+
case "solana":
|
|
1019
|
+
return `${basePath}/0'`;
|
|
1020
|
+
case "bitcoin":
|
|
1021
|
+
case "ethereum":
|
|
1022
|
+
case "tron":
|
|
1023
|
+
case "spark":
|
|
1024
|
+
default:
|
|
1025
|
+
return `${basePath}/0`;
|
|
1026
|
+
}
|
|
1621
1027
|
}
|
|
1622
|
-
getChainSymbol(
|
|
1028
|
+
getChainSymbol(chain) {
|
|
1623
1029
|
const symbols = {
|
|
1624
1030
|
ethereum: "ETH",
|
|
1625
1031
|
bitcoin: "BTC",
|
|
@@ -1628,16 +1034,16 @@ var ZubariWdkService = class {
|
|
|
1628
1034
|
solana: "SOL",
|
|
1629
1035
|
spark: "SAT"
|
|
1630
1036
|
};
|
|
1631
|
-
return symbols[
|
|
1037
|
+
return symbols[chain];
|
|
1632
1038
|
}
|
|
1633
1039
|
/**
|
|
1634
1040
|
* Derive address using browser-compatible libraries
|
|
1635
1041
|
*/
|
|
1636
|
-
async deriveBrowserAddress(seed,
|
|
1637
|
-
const path = this.getDerivationPath(
|
|
1042
|
+
async deriveBrowserAddress(seed, chain) {
|
|
1043
|
+
const path = this.getDerivationPath(chain);
|
|
1638
1044
|
try {
|
|
1639
1045
|
let address;
|
|
1640
|
-
switch (
|
|
1046
|
+
switch (chain) {
|
|
1641
1047
|
case "ethereum":
|
|
1642
1048
|
address = deriveEthereumAddress(seed);
|
|
1643
1049
|
break;
|
|
@@ -1657,11 +1063,11 @@ var ZubariWdkService = class {
|
|
|
1657
1063
|
address = await deriveTonAddress(seed);
|
|
1658
1064
|
break;
|
|
1659
1065
|
default:
|
|
1660
|
-
throw new Error(`Unsupported chain: ${
|
|
1066
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1661
1067
|
}
|
|
1662
|
-
return { chain
|
|
1068
|
+
return { chain, address, path };
|
|
1663
1069
|
} catch (error) {
|
|
1664
|
-
console.error(`Browser derivation failed for ${
|
|
1070
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1665
1071
|
throw error;
|
|
1666
1072
|
}
|
|
1667
1073
|
}
|
|
@@ -1674,19 +1080,28 @@ var ZubariWdkService = class {
|
|
|
1674
1080
|
};
|
|
1675
1081
|
var defaultService = null;
|
|
1676
1082
|
function getZubariWdkService(config) {
|
|
1677
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1083
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1678
1084
|
defaultService = new ZubariWdkService(config);
|
|
1679
1085
|
}
|
|
1680
1086
|
return defaultService;
|
|
1681
1087
|
}
|
|
1682
1088
|
|
|
1683
1089
|
// src/wallet/ZubariWallet.ts
|
|
1684
|
-
var ZubariWallet = class {
|
|
1090
|
+
var ZubariWallet = class _ZubariWallet {
|
|
1685
1091
|
seed;
|
|
1686
1092
|
config;
|
|
1687
1093
|
accounts = /* @__PURE__ */ new Map();
|
|
1688
1094
|
wdkService;
|
|
1689
1095
|
initialized = false;
|
|
1096
|
+
/** Mapping from NetworkType to SupportedChain (identity map, shared across methods) */
|
|
1097
|
+
static CHAIN_MAP = {
|
|
1098
|
+
ethereum: "ethereum",
|
|
1099
|
+
bitcoin: "bitcoin",
|
|
1100
|
+
ton: "ton",
|
|
1101
|
+
tron: "tron",
|
|
1102
|
+
solana: "solana",
|
|
1103
|
+
spark: "spark"
|
|
1104
|
+
};
|
|
1690
1105
|
constructor(seed, config) {
|
|
1691
1106
|
this.seed = seed;
|
|
1692
1107
|
this.config = {
|
|
@@ -1719,20 +1134,12 @@ var ZubariWallet = class {
|
|
|
1719
1134
|
async deriveAccount(network, index = 0) {
|
|
1720
1135
|
const basePath = DERIVATION_PATHS[network];
|
|
1721
1136
|
const derivationPath = `${basePath}/${index}`;
|
|
1722
|
-
const
|
|
1723
|
-
|
|
1724
|
-
bitcoin: "bitcoin",
|
|
1725
|
-
ton: "ton",
|
|
1726
|
-
tron: "tron",
|
|
1727
|
-
solana: "solana",
|
|
1728
|
-
spark: "spark"
|
|
1729
|
-
};
|
|
1730
|
-
const chain2 = chainMap[network];
|
|
1731
|
-
if (!chain2) {
|
|
1137
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1138
|
+
if (!chain) {
|
|
1732
1139
|
throw new Error(`Unsupported network: ${network}`);
|
|
1733
1140
|
}
|
|
1734
1141
|
try {
|
|
1735
|
-
const result = await this.wdkService.deriveAddress(this.seed,
|
|
1142
|
+
const result = await this.wdkService.deriveAddress(this.seed, chain);
|
|
1736
1143
|
const account = {
|
|
1737
1144
|
network,
|
|
1738
1145
|
address: result.address,
|
|
@@ -1779,21 +1186,13 @@ var ZubariWallet = class {
|
|
|
1779
1186
|
*/
|
|
1780
1187
|
async getBalance(network) {
|
|
1781
1188
|
const networkConfig = getNetworkConfig(network, this.config.network === "testnet");
|
|
1782
|
-
const
|
|
1783
|
-
|
|
1784
|
-
bitcoin: "bitcoin",
|
|
1785
|
-
ton: "ton",
|
|
1786
|
-
tron: "tron",
|
|
1787
|
-
solana: "solana",
|
|
1788
|
-
spark: "spark"
|
|
1789
|
-
};
|
|
1790
|
-
const chain2 = chainMap[network];
|
|
1791
|
-
if (!chain2) {
|
|
1189
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1190
|
+
if (!chain) {
|
|
1792
1191
|
throw new Error(`Unsupported network: ${network}`);
|
|
1793
1192
|
}
|
|
1794
1193
|
try {
|
|
1795
1194
|
const balances = await this.wdkService.getAllBalances(this.seed);
|
|
1796
|
-
const chainBalance = balances[
|
|
1195
|
+
const chainBalance = balances[chain];
|
|
1797
1196
|
if (chainBalance) {
|
|
1798
1197
|
const balanceValue = BigInt(chainBalance.balance || "0");
|
|
1799
1198
|
const decimals = networkConfig.nativeCurrency.decimals;
|
|
@@ -1874,22 +1273,14 @@ var ZubariWallet = class {
|
|
|
1874
1273
|
*/
|
|
1875
1274
|
async send(network, params) {
|
|
1876
1275
|
const { to, amount } = params;
|
|
1877
|
-
const
|
|
1878
|
-
|
|
1879
|
-
bitcoin: "bitcoin",
|
|
1880
|
-
ton: "ton",
|
|
1881
|
-
tron: "tron",
|
|
1882
|
-
solana: "solana",
|
|
1883
|
-
spark: "spark"
|
|
1884
|
-
};
|
|
1885
|
-
const chain2 = chainMap[network];
|
|
1886
|
-
if (!chain2) {
|
|
1276
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1277
|
+
if (!chain) {
|
|
1887
1278
|
throw new Error(`Unsupported network: ${network}`);
|
|
1888
1279
|
}
|
|
1889
1280
|
try {
|
|
1890
1281
|
const result = await this.wdkService.sendTransaction(
|
|
1891
1282
|
this.seed,
|
|
1892
|
-
|
|
1283
|
+
chain,
|
|
1893
1284
|
to,
|
|
1894
1285
|
amount.toString()
|
|
1895
1286
|
);
|
|
@@ -2187,7 +1578,10 @@ var KeyManager = class {
|
|
|
2187
1578
|
static KEY_LENGTH = 256;
|
|
2188
1579
|
static IV_LENGTH = 12;
|
|
2189
1580
|
static SALT_LENGTH = 16;
|
|
2190
|
-
|
|
1581
|
+
// OWASP 2023 recommends 600,000 iterations for PBKDF2-SHA256 to resist
|
|
1582
|
+
// brute-force attacks with modern GPU hardware.
|
|
1583
|
+
// See: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
|
|
1584
|
+
static PBKDF2_ITERATIONS = 6e5;
|
|
2191
1585
|
/**
|
|
2192
1586
|
* Encrypt a seed phrase with a password
|
|
2193
1587
|
*/
|
|
@@ -2426,7 +1820,7 @@ var WebEncryptedStorageAdapter = class {
|
|
|
2426
1820
|
{
|
|
2427
1821
|
name: "PBKDF2",
|
|
2428
1822
|
salt: salt.buffer,
|
|
2429
|
-
iterations:
|
|
1823
|
+
iterations: 6e5,
|
|
2430
1824
|
hash: "SHA-256"
|
|
2431
1825
|
},
|
|
2432
1826
|
keyMaterial,
|
|
@@ -2564,8 +1958,8 @@ async function fetchPrices() {
|
|
|
2564
1958
|
if (response.ok) {
|
|
2565
1959
|
const data = await response.json();
|
|
2566
1960
|
const prices = {};
|
|
2567
|
-
for (const [
|
|
2568
|
-
prices[
|
|
1961
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1962
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2569
1963
|
}
|
|
2570
1964
|
priceCache = { prices, timestamp: Date.now() };
|
|
2571
1965
|
return prices;
|
|
@@ -2575,9 +1969,22 @@ async function fetchPrices() {
|
|
|
2575
1969
|
}
|
|
2576
1970
|
return priceCache?.prices || {};
|
|
2577
1971
|
}
|
|
2578
|
-
async function getPriceForChain(
|
|
1972
|
+
async function getPriceForChain(chain) {
|
|
2579
1973
|
const prices = await fetchPrices();
|
|
2580
|
-
return prices[
|
|
1974
|
+
return prices[chain] || 0;
|
|
1975
|
+
}
|
|
1976
|
+
function tonFriendlyToRaw(addr) {
|
|
1977
|
+
if (addr.includes(":")) return addr;
|
|
1978
|
+
try {
|
|
1979
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1980
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1981
|
+
if (bytes.length !== 36) return addr;
|
|
1982
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1983
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1984
|
+
return `${workchain}:${hash}`;
|
|
1985
|
+
} catch {
|
|
1986
|
+
return addr;
|
|
1987
|
+
}
|
|
2581
1988
|
}
|
|
2582
1989
|
var STORAGE_KEYS = {
|
|
2583
1990
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2726,6 +2133,16 @@ var WalletManager = class _WalletManager {
|
|
|
2726
2133
|
}
|
|
2727
2134
|
/**
|
|
2728
2135
|
* Lock wallet (clear seed from memory)
|
|
2136
|
+
*
|
|
2137
|
+
* SECURITY NOTE: JavaScript strings are immutable and cannot be overwritten
|
|
2138
|
+
* in place. Setting `this.currentSeed = null` removes the reference, but
|
|
2139
|
+
* the original string may persist in memory until garbage collected.
|
|
2140
|
+
* There is no reliable way to zero out a JS string.
|
|
2141
|
+
*
|
|
2142
|
+
* TODO: In a future version, store the seed as a Uint8Array instead of a
|
|
2143
|
+
* string. Uint8Array contents can be explicitly zeroed (e.g.,
|
|
2144
|
+
* `seedBytes.fill(0)`) before releasing the reference, which provides
|
|
2145
|
+
* stronger guarantees that sensitive material is scrubbed from memory.
|
|
2729
2146
|
*/
|
|
2730
2147
|
lock() {
|
|
2731
2148
|
this.currentSeed = null;
|
|
@@ -2783,9 +2200,9 @@ var WalletManager = class _WalletManager {
|
|
|
2783
2200
|
if (!this.derivedAddress) {
|
|
2784
2201
|
throw new Error("Wallet not initialized");
|
|
2785
2202
|
}
|
|
2786
|
-
const
|
|
2203
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2787
2204
|
const client = viem.createPublicClient({
|
|
2788
|
-
chain
|
|
2205
|
+
chain,
|
|
2789
2206
|
transport: viem.http(this.config.rpcUrl, {
|
|
2790
2207
|
timeout: 15e3,
|
|
2791
2208
|
// 15 second timeout
|
|
@@ -2807,9 +2224,9 @@ var WalletManager = class _WalletManager {
|
|
|
2807
2224
|
* Create viem public client for the current network
|
|
2808
2225
|
*/
|
|
2809
2226
|
getPublicClient() {
|
|
2810
|
-
const
|
|
2227
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2811
2228
|
return viem.createPublicClient({
|
|
2812
|
-
chain
|
|
2229
|
+
chain,
|
|
2813
2230
|
transport: viem.http(this.config.rpcUrl, {
|
|
2814
2231
|
timeout: 15e3,
|
|
2815
2232
|
// 15 second timeout
|
|
@@ -2863,11 +2280,11 @@ var WalletManager = class _WalletManager {
|
|
|
2863
2280
|
*
|
|
2864
2281
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2865
2282
|
*/
|
|
2866
|
-
static async deriveAddressForChainAsync(seed,
|
|
2867
|
-
if (
|
|
2283
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
2284
|
+
if (chain === "ethereum") {
|
|
2868
2285
|
try {
|
|
2869
2286
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2870
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
2287
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2871
2288
|
return result2.address;
|
|
2872
2289
|
} catch (error) {
|
|
2873
2290
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2875,7 +2292,7 @@ var WalletManager = class _WalletManager {
|
|
|
2875
2292
|
}
|
|
2876
2293
|
}
|
|
2877
2294
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2878
|
-
const result = await wdkService.deriveAddress(seed,
|
|
2295
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2879
2296
|
return result.address;
|
|
2880
2297
|
}
|
|
2881
2298
|
/**
|
|
@@ -2884,14 +2301,14 @@ var WalletManager = class _WalletManager {
|
|
|
2884
2301
|
*
|
|
2885
2302
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2886
2303
|
*/
|
|
2887
|
-
static deriveAddressForChain(seed,
|
|
2888
|
-
if (
|
|
2304
|
+
static deriveAddressForChain(seed, chain) {
|
|
2305
|
+
if (chain === "ethereum") {
|
|
2889
2306
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2890
2307
|
const ethNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2891
2308
|
return ethNode.address;
|
|
2892
2309
|
}
|
|
2893
2310
|
throw new Error(
|
|
2894
|
-
`Sync derivation not supported for ${
|
|
2311
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2895
2312
|
);
|
|
2896
2313
|
}
|
|
2897
2314
|
/**
|
|
@@ -2923,9 +2340,9 @@ var WalletManager = class _WalletManager {
|
|
|
2923
2340
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2924
2341
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2925
2342
|
const addresses = {};
|
|
2926
|
-
for (const [
|
|
2927
|
-
if (enabledChainsSet.has(
|
|
2928
|
-
addresses[
|
|
2343
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
2344
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
2345
|
+
addresses[chain] = address;
|
|
2929
2346
|
}
|
|
2930
2347
|
}
|
|
2931
2348
|
this.derivedAddresses = addresses;
|
|
@@ -2942,7 +2359,6 @@ var WalletManager = class _WalletManager {
|
|
|
2942
2359
|
async saveAddressesToStorage(addresses) {
|
|
2943
2360
|
try {
|
|
2944
2361
|
await this.storage.setItem(STORAGE_KEYS.DERIVED_ADDRESSES, JSON.stringify(addresses));
|
|
2945
|
-
console.log("Saved derived addresses to storage:", Object.keys(addresses));
|
|
2946
2362
|
} catch (error) {
|
|
2947
2363
|
console.warn("Failed to save addresses to storage:", error);
|
|
2948
2364
|
}
|
|
@@ -2966,10 +2382,10 @@ var WalletManager = class _WalletManager {
|
|
|
2966
2382
|
*/
|
|
2967
2383
|
normalizeAddresses(addresses) {
|
|
2968
2384
|
const normalized = {};
|
|
2969
|
-
for (const [
|
|
2385
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2970
2386
|
const addr = this.normalizeAddress(value);
|
|
2971
2387
|
if (addr) {
|
|
2972
|
-
normalized[
|
|
2388
|
+
normalized[chain] = addr;
|
|
2973
2389
|
}
|
|
2974
2390
|
}
|
|
2975
2391
|
return normalized;
|
|
@@ -2982,9 +2398,7 @@ var WalletManager = class _WalletManager {
|
|
|
2982
2398
|
const stored = await this.storage.getItem(STORAGE_KEYS.DERIVED_ADDRESSES);
|
|
2983
2399
|
if (stored) {
|
|
2984
2400
|
const rawAddresses = JSON.parse(stored);
|
|
2985
|
-
console.log("[WalletManager] Raw addresses from storage:", rawAddresses);
|
|
2986
2401
|
const addresses = this.normalizeAddresses(rawAddresses);
|
|
2987
|
-
console.log("[WalletManager] Normalized addresses:", addresses);
|
|
2988
2402
|
await this.saveAddressesToStorage(addresses);
|
|
2989
2403
|
return addresses;
|
|
2990
2404
|
}
|
|
@@ -3009,11 +2423,8 @@ var WalletManager = class _WalletManager {
|
|
|
3009
2423
|
if (storedAddresses && Object.keys(storedAddresses).length > 1) {
|
|
3010
2424
|
const expectedEthAddress = _WalletManager.deriveAddress(this.currentSeed);
|
|
3011
2425
|
if (storedAddresses.ethereum === expectedEthAddress) {
|
|
3012
|
-
console.log("Using addresses from storage (verified by Ethereum address)");
|
|
3013
2426
|
this.derivedAddresses = storedAddresses;
|
|
3014
2427
|
return storedAddresses;
|
|
3015
|
-
} else {
|
|
3016
|
-
console.log("Stored addresses do not match current seed, re-deriving...");
|
|
3017
2428
|
}
|
|
3018
2429
|
}
|
|
3019
2430
|
return await this.deriveAllAddressesWithWdk();
|
|
@@ -3022,20 +2433,18 @@ var WalletManager = class _WalletManager {
|
|
|
3022
2433
|
* Get address for a specific chain
|
|
3023
2434
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
3024
2435
|
*/
|
|
3025
|
-
getAddressForChain(
|
|
3026
|
-
const cachedValue = this.derivedAddresses[
|
|
2436
|
+
getAddressForChain(chain) {
|
|
2437
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
3027
2438
|
if (cachedValue) {
|
|
3028
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
3029
2439
|
const addr = this.normalizeAddress(cachedValue);
|
|
3030
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) normalized:`, addr);
|
|
3031
2440
|
if (addr) {
|
|
3032
|
-
this.derivedAddresses[
|
|
2441
|
+
this.derivedAddresses[chain] = addr;
|
|
3033
2442
|
return addr;
|
|
3034
2443
|
}
|
|
3035
2444
|
}
|
|
3036
|
-
if (
|
|
3037
|
-
this.derivedAddresses[
|
|
3038
|
-
return this.derivedAddresses[
|
|
2445
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
2446
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
2447
|
+
return this.derivedAddresses[chain];
|
|
3039
2448
|
}
|
|
3040
2449
|
return null;
|
|
3041
2450
|
}
|
|
@@ -3048,11 +2457,11 @@ var WalletManager = class _WalletManager {
|
|
|
3048
2457
|
/**
|
|
3049
2458
|
* Set the selected chain
|
|
3050
2459
|
*/
|
|
3051
|
-
setSelectedChain(
|
|
3052
|
-
if (!this.config.enabledChains.includes(
|
|
3053
|
-
throw new Error(`Chain ${
|
|
2460
|
+
setSelectedChain(chain) {
|
|
2461
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
2462
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
3054
2463
|
}
|
|
3055
|
-
this.selectedChain =
|
|
2464
|
+
this.selectedChain = chain;
|
|
3056
2465
|
}
|
|
3057
2466
|
/**
|
|
3058
2467
|
* Get the currently selected chain
|
|
@@ -3069,22 +2478,22 @@ var WalletManager = class _WalletManager {
|
|
|
3069
2478
|
/**
|
|
3070
2479
|
* Get chain configuration
|
|
3071
2480
|
*/
|
|
3072
|
-
getChainConfig(
|
|
3073
|
-
return getNetworkConfig(
|
|
2481
|
+
getChainConfig(chain) {
|
|
2482
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
3074
2483
|
}
|
|
3075
2484
|
/**
|
|
3076
2485
|
* Fetch balance for a specific chain
|
|
3077
2486
|
* Note: Currently only Ethereum is implemented
|
|
3078
2487
|
*/
|
|
3079
|
-
async fetchBalanceForChain(
|
|
3080
|
-
const address = this.getAddressForChain(
|
|
2488
|
+
async fetchBalanceForChain(chain) {
|
|
2489
|
+
const address = this.getAddressForChain(chain);
|
|
3081
2490
|
if (!address) {
|
|
3082
|
-
throw new Error(`No address for chain ${
|
|
2491
|
+
throw new Error(`No address for chain ${chain}`);
|
|
3083
2492
|
}
|
|
3084
|
-
const networkConfig = this.getChainConfig(
|
|
2493
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3085
2494
|
let balance = "0";
|
|
3086
2495
|
const tokenBalances = {};
|
|
3087
|
-
if (
|
|
2496
|
+
if (chain === "ethereum") {
|
|
3088
2497
|
const viemChain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
3089
2498
|
const isTestnet = this.config.network !== "mainnet";
|
|
3090
2499
|
const client = viem.createPublicClient({
|
|
@@ -3131,7 +2540,7 @@ var WalletManager = class _WalletManager {
|
|
|
3131
2540
|
} else if (usdtResult.status === "rejected") {
|
|
3132
2541
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
3133
2542
|
}
|
|
3134
|
-
} else if (
|
|
2543
|
+
} else if (chain === "bitcoin") {
|
|
3135
2544
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
3136
2545
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
3137
2546
|
"https://mempool.space/testnet/api",
|
|
@@ -3154,16 +2563,14 @@ var WalletManager = class _WalletManager {
|
|
|
3154
2563
|
const mempoolSpent = data.mempool_stats?.spent_txo_sum || 0;
|
|
3155
2564
|
const satoshis = chainFunded - chainSpent + (mempoolFunded - mempoolSpent);
|
|
3156
2565
|
balance = (satoshis / 1e8).toFixed(8);
|
|
3157
|
-
console.log(`Bitcoin balance for ${address}: ${balance} BTC (${satoshis} sats) via ${apiUrl}`);
|
|
3158
2566
|
break;
|
|
3159
2567
|
}
|
|
3160
|
-
console.log(`No transactions found on ${apiUrl}, trying next...`);
|
|
3161
2568
|
}
|
|
3162
2569
|
} catch (error) {
|
|
3163
2570
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
3164
2571
|
}
|
|
3165
2572
|
}
|
|
3166
|
-
} else if (
|
|
2573
|
+
} else if (chain === "solana") {
|
|
3167
2574
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
3168
2575
|
try {
|
|
3169
2576
|
const response = await fetch(rpcUrl, {
|
|
@@ -3183,7 +2590,7 @@ var WalletManager = class _WalletManager {
|
|
|
3183
2590
|
}
|
|
3184
2591
|
}
|
|
3185
2592
|
} catch (error) {
|
|
3186
|
-
console.warn(`Failed to fetch ${
|
|
2593
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3187
2594
|
}
|
|
3188
2595
|
const isTestnet = this.config.network !== "mainnet";
|
|
3189
2596
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -3217,7 +2624,7 @@ var WalletManager = class _WalletManager {
|
|
|
3217
2624
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
3218
2625
|
}
|
|
3219
2626
|
}
|
|
3220
|
-
} else if (
|
|
2627
|
+
} else if (chain === "tron") {
|
|
3221
2628
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
3222
2629
|
const baseUrl = tronConfig.rpcUrl;
|
|
3223
2630
|
try {
|
|
@@ -3246,9 +2653,9 @@ var WalletManager = class _WalletManager {
|
|
|
3246
2653
|
}
|
|
3247
2654
|
}
|
|
3248
2655
|
} catch (error) {
|
|
3249
|
-
console.warn(`Failed to fetch ${
|
|
2656
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3250
2657
|
}
|
|
3251
|
-
} else if (
|
|
2658
|
+
} else if (chain === "ton") {
|
|
3252
2659
|
const isTestnet = this.config.network !== "mainnet";
|
|
3253
2660
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
3254
2661
|
try {
|
|
@@ -3260,29 +2667,39 @@ var WalletManager = class _WalletManager {
|
|
|
3260
2667
|
if (data.ok && data.result !== void 0) {
|
|
3261
2668
|
const nanotons = BigInt(data.result);
|
|
3262
2669
|
balance = (Number(nanotons) / 1e9).toFixed(9);
|
|
3263
|
-
console.log(`TON balance for ${address}: ${balance} TON`);
|
|
3264
2670
|
}
|
|
3265
2671
|
}
|
|
3266
2672
|
} catch (error) {
|
|
3267
|
-
console.warn(`Failed to fetch ${
|
|
2673
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3268
2674
|
}
|
|
3269
2675
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
3270
2676
|
if (usdtJetton) {
|
|
3271
|
-
const
|
|
2677
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
3272
2678
|
try {
|
|
2679
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
3273
2680
|
const jettonResponse = await fetch(
|
|
3274
|
-
`${
|
|
2681
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
3275
2682
|
{ headers: { "Accept": "application/json" } }
|
|
3276
2683
|
);
|
|
3277
2684
|
if (jettonResponse.ok) {
|
|
3278
2685
|
const jettonData = await jettonResponse.json();
|
|
3279
|
-
const
|
|
3280
|
-
if (
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
2686
|
+
const balances = jettonData.balances;
|
|
2687
|
+
if (balances && balances.length > 0) {
|
|
2688
|
+
for (const jb of balances) {
|
|
2689
|
+
const jettonAddr = jb.jetton?.address;
|
|
2690
|
+
if (jettonAddr) {
|
|
2691
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2692
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2693
|
+
const rawBalance = jb.balance;
|
|
2694
|
+
if (rawBalance) {
|
|
2695
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2696
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2697
|
+
if (usdtAmount > 0) {
|
|
2698
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
break;
|
|
2702
|
+
}
|
|
3286
2703
|
}
|
|
3287
2704
|
}
|
|
3288
2705
|
}
|
|
@@ -3291,7 +2708,7 @@ var WalletManager = class _WalletManager {
|
|
|
3291
2708
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
3292
2709
|
}
|
|
3293
2710
|
}
|
|
3294
|
-
} else if (
|
|
2711
|
+
} else if (chain === "spark") {
|
|
3295
2712
|
try {
|
|
3296
2713
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
3297
2714
|
method: "POST",
|
|
@@ -3306,18 +2723,17 @@ var WalletManager = class _WalletManager {
|
|
|
3306
2723
|
const data = await response.json();
|
|
3307
2724
|
if (data.success && data.balance !== void 0) {
|
|
3308
2725
|
balance = (parseFloat(data.balance) / 1e8).toFixed(8);
|
|
3309
|
-
console.log(`Spark balance for ${address}: ${balance} BTC`);
|
|
3310
2726
|
}
|
|
3311
2727
|
}
|
|
3312
2728
|
} catch (error) {
|
|
3313
|
-
console.warn(`Failed to fetch ${
|
|
2729
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3314
2730
|
}
|
|
3315
2731
|
}
|
|
3316
|
-
const priceUsd = await getPriceForChain(
|
|
2732
|
+
const priceUsd = await getPriceForChain(chain);
|
|
3317
2733
|
const balanceNum = parseFloat(balance) || 0;
|
|
3318
2734
|
const balanceUsd = balanceNum * priceUsd;
|
|
3319
2735
|
return {
|
|
3320
|
-
chain
|
|
2736
|
+
chain,
|
|
3321
2737
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3322
2738
|
balance,
|
|
3323
2739
|
balanceUsd,
|
|
@@ -3327,28 +2743,29 @@ var WalletManager = class _WalletManager {
|
|
|
3327
2743
|
};
|
|
3328
2744
|
}
|
|
3329
2745
|
/**
|
|
3330
|
-
* Fetch balances for all enabled chains
|
|
2746
|
+
* Fetch balances for all enabled chains in parallel.
|
|
2747
|
+
* Uses Promise.allSettled so that one chain failing does not block others.
|
|
3331
2748
|
*/
|
|
3332
2749
|
async fetchAllBalances() {
|
|
3333
|
-
const
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
const networkConfig = this.getChainConfig(chain2);
|
|
3341
|
-
balances.push({
|
|
3342
|
-
chain: chain2,
|
|
3343
|
-
symbol: networkConfig.nativeCurrency.symbol,
|
|
3344
|
-
balance: "0",
|
|
3345
|
-
balanceUsd: 0,
|
|
3346
|
-
address: this.getAddressForChain(chain2) || "",
|
|
3347
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
3348
|
-
});
|
|
2750
|
+
const results = await Promise.allSettled(
|
|
2751
|
+
this.config.enabledChains.map((chain) => this.fetchBalanceForChain(chain))
|
|
2752
|
+
);
|
|
2753
|
+
return results.map((result, index) => {
|
|
2754
|
+
const chain = this.config.enabledChains[index];
|
|
2755
|
+
if (result.status === "fulfilled") {
|
|
2756
|
+
return result.value;
|
|
3349
2757
|
}
|
|
3350
|
-
|
|
3351
|
-
|
|
2758
|
+
console.error(`Failed to fetch balance for ${chain}:`, result.reason);
|
|
2759
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2760
|
+
return {
|
|
2761
|
+
chain,
|
|
2762
|
+
symbol: networkConfig.nativeCurrency.symbol,
|
|
2763
|
+
balance: "0",
|
|
2764
|
+
balanceUsd: 0,
|
|
2765
|
+
address: this.getAddressForChain(chain) || "",
|
|
2766
|
+
decimals: networkConfig.nativeCurrency.decimals
|
|
2767
|
+
};
|
|
2768
|
+
});
|
|
3352
2769
|
}
|
|
3353
2770
|
/**
|
|
3354
2771
|
* Get extended wallet state with multi-chain info
|
|
@@ -3373,13 +2790,13 @@ var WalletManager = class _WalletManager {
|
|
|
3373
2790
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
3374
2791
|
* @returns Transaction result with hash and status
|
|
3375
2792
|
*/
|
|
3376
|
-
async sendTransaction(
|
|
2793
|
+
async sendTransaction(chain, to, amount, token) {
|
|
3377
2794
|
if (!this.currentSeed) {
|
|
3378
2795
|
return { success: false, error: "Wallet is locked" };
|
|
3379
2796
|
}
|
|
3380
|
-
const fromAddress = this.getAddressForChain(
|
|
2797
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
3381
2798
|
if (!fromAddress) {
|
|
3382
|
-
return { success: false, error: `No address for chain ${
|
|
2799
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
3383
2800
|
}
|
|
3384
2801
|
try {
|
|
3385
2802
|
const headers = {
|
|
@@ -3393,7 +2810,7 @@ var WalletManager = class _WalletManager {
|
|
|
3393
2810
|
headers,
|
|
3394
2811
|
body: JSON.stringify({
|
|
3395
2812
|
seed: this.currentSeed,
|
|
3396
|
-
chain
|
|
2813
|
+
chain,
|
|
3397
2814
|
to,
|
|
3398
2815
|
amount,
|
|
3399
2816
|
token,
|
|
@@ -3402,12 +2819,11 @@ var WalletManager = class _WalletManager {
|
|
|
3402
2819
|
});
|
|
3403
2820
|
if (response.ok) {
|
|
3404
2821
|
const data = await response.json();
|
|
3405
|
-
console.log(`Transaction sent on ${chain2}:`, data);
|
|
3406
2822
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
3407
2823
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
3408
2824
|
txHash = txHash.hash;
|
|
3409
2825
|
}
|
|
3410
|
-
if (
|
|
2826
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
3411
2827
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
3412
2828
|
}
|
|
3413
2829
|
return {
|
|
@@ -3416,7 +2832,7 @@ var WalletManager = class _WalletManager {
|
|
|
3416
2832
|
from: fromAddress,
|
|
3417
2833
|
to,
|
|
3418
2834
|
amount,
|
|
3419
|
-
chain
|
|
2835
|
+
chain
|
|
3420
2836
|
};
|
|
3421
2837
|
}
|
|
3422
2838
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -3425,7 +2841,7 @@ var WalletManager = class _WalletManager {
|
|
|
3425
2841
|
error: errorData.error || `HTTP ${response.status}`
|
|
3426
2842
|
};
|
|
3427
2843
|
} catch (error) {
|
|
3428
|
-
console.error(`Transaction failed on ${
|
|
2844
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
3429
2845
|
return {
|
|
3430
2846
|
success: false,
|
|
3431
2847
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -3435,7 +2851,7 @@ var WalletManager = class _WalletManager {
|
|
|
3435
2851
|
/**
|
|
3436
2852
|
* Estimate transaction fee using Tether WDK
|
|
3437
2853
|
*/
|
|
3438
|
-
async estimateFee(
|
|
2854
|
+
async estimateFee(chain, to, amount, token) {
|
|
3439
2855
|
try {
|
|
3440
2856
|
const headers = {
|
|
3441
2857
|
"Content-Type": "application/json"
|
|
@@ -3447,7 +2863,7 @@ var WalletManager = class _WalletManager {
|
|
|
3447
2863
|
method: "POST",
|
|
3448
2864
|
headers,
|
|
3449
2865
|
body: JSON.stringify({
|
|
3450
|
-
chain
|
|
2866
|
+
chain,
|
|
3451
2867
|
to,
|
|
3452
2868
|
amount,
|
|
3453
2869
|
token,
|
|
@@ -3471,14 +2887,6 @@ var WalletManager = class _WalletManager {
|
|
|
3471
2887
|
}
|
|
3472
2888
|
}
|
|
3473
2889
|
};
|
|
3474
|
-
/*! Bundled license information:
|
|
3475
|
-
|
|
3476
|
-
@scure/base/index.js:
|
|
3477
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3478
|
-
|
|
3479
|
-
@scure/bip32/index.js:
|
|
3480
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
3481
|
-
*/
|
|
3482
2890
|
|
|
3483
2891
|
exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS;
|
|
3484
2892
|
exports.WalletManager = WalletManager;
|