@zubari/sdk 0.5.2 → 0.5.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/dist/index.js +227 -797
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +225 -795
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +175 -745
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +173 -743
- package/dist/react/index.mjs.map +1 -1
- package/dist/services/index.js +113 -707
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +111 -705
- package/dist/services/index.mjs.map +1 -1
- package/dist/wallet/index.js +176 -746
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +174 -744
- 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",
|
|
@@ -280,14 +277,14 @@ var WdkApiClient = class {
|
|
|
280
277
|
/**
|
|
281
278
|
* Derive address for a specific chain using Tether WDK
|
|
282
279
|
*/
|
|
283
|
-
async deriveAddress(seed,
|
|
280
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
284
281
|
try {
|
|
285
282
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
286
283
|
method: "POST",
|
|
287
284
|
headers: {
|
|
288
285
|
"Content-Type": "application/json"
|
|
289
286
|
},
|
|
290
|
-
body: JSON.stringify({ seed, chain
|
|
287
|
+
body: JSON.stringify({ seed, chain, network })
|
|
291
288
|
});
|
|
292
289
|
return await response.json();
|
|
293
290
|
} catch (error) {
|
|
@@ -320,14 +317,14 @@ var WdkApiClient = class {
|
|
|
320
317
|
/**
|
|
321
318
|
* Send a transaction on a specific chain using Tether WDK
|
|
322
319
|
*/
|
|
323
|
-
async sendTransaction(seed,
|
|
320
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
324
321
|
try {
|
|
325
322
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
326
323
|
method: "POST",
|
|
327
324
|
headers: {
|
|
328
325
|
"Content-Type": "application/json"
|
|
329
326
|
},
|
|
330
|
-
body: JSON.stringify({ seed, chain
|
|
327
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
331
328
|
});
|
|
332
329
|
return await response.json();
|
|
333
330
|
} catch (error) {
|
|
@@ -341,14 +338,14 @@ var WdkApiClient = class {
|
|
|
341
338
|
* Get transaction history for an address on a specific chain
|
|
342
339
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
343
340
|
*/
|
|
344
|
-
async getTransactionHistory(seed,
|
|
341
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
345
342
|
try {
|
|
346
343
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
347
344
|
method: "POST",
|
|
348
345
|
headers: {
|
|
349
346
|
"Content-Type": "application/json"
|
|
350
347
|
},
|
|
351
|
-
body: JSON.stringify({ seed, chain
|
|
348
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
352
349
|
});
|
|
353
350
|
return await response.json();
|
|
354
351
|
} catch (error) {
|
|
@@ -362,14 +359,14 @@ var WdkApiClient = class {
|
|
|
362
359
|
* Get transaction status by hash
|
|
363
360
|
* Fetches from blockchain explorers to check confirmation status
|
|
364
361
|
*/
|
|
365
|
-
async getTransactionStatus(txHash,
|
|
362
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
366
363
|
try {
|
|
367
364
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
368
365
|
method: "POST",
|
|
369
366
|
headers: {
|
|
370
367
|
"Content-Type": "application/json"
|
|
371
368
|
},
|
|
372
|
-
body: JSON.stringify({ txHash, chain
|
|
369
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
373
370
|
});
|
|
374
371
|
return await response.json();
|
|
375
372
|
} catch (error) {
|
|
@@ -390,589 +387,6 @@ function getWdkApiClient(baseUrl) {
|
|
|
390
387
|
}
|
|
391
388
|
return wdkApiClient;
|
|
392
389
|
}
|
|
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
390
|
var DERIVATION_PATHS2 = {
|
|
977
391
|
ethereum: "m/44'/60'/0'/0/0",
|
|
978
392
|
bitcoin_mainnet: "m/84'/0'/0'/0/0",
|
|
@@ -989,7 +403,7 @@ function deriveEthereumAddress(seed) {
|
|
|
989
403
|
function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
990
404
|
try {
|
|
991
405
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
992
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
406
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
993
407
|
const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
|
|
994
408
|
const child = hdKey.derive(path);
|
|
995
409
|
if (!child.publicKey) {
|
|
@@ -997,10 +411,10 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
997
411
|
}
|
|
998
412
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
999
413
|
const witnessVersion = 0;
|
|
1000
|
-
const words = bech32.toWords(pubKeyHash);
|
|
414
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1001
415
|
words.unshift(witnessVersion);
|
|
1002
416
|
const hrp = network === "testnet" ? "tb" : "bc";
|
|
1003
|
-
const address = bech32.encode(hrp, words);
|
|
417
|
+
const address = base.bech32.encode(hrp, words);
|
|
1004
418
|
return address;
|
|
1005
419
|
} catch (error) {
|
|
1006
420
|
console.error("Bitcoin address derivation failed:", error);
|
|
@@ -1073,7 +487,7 @@ function deriveTronAddress(seed) {
|
|
|
1073
487
|
for (let i = 0; i < 20; i++) {
|
|
1074
488
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1075
489
|
}
|
|
1076
|
-
const tronBase58check = base58check(sha256.sha256);
|
|
490
|
+
const tronBase58check = base.base58check(sha256.sha256);
|
|
1077
491
|
return tronBase58check.encode(addressBytes);
|
|
1078
492
|
} catch (error) {
|
|
1079
493
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1083,17 +497,17 @@ function deriveTronAddress(seed) {
|
|
|
1083
497
|
function deriveSparkAddress(seed, network = "mainnet") {
|
|
1084
498
|
try {
|
|
1085
499
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
1086
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
500
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
1087
501
|
const child = hdKey.derive(DERIVATION_PATHS2.spark);
|
|
1088
502
|
if (!child.publicKey) {
|
|
1089
503
|
throw new Error("Failed to derive public key");
|
|
1090
504
|
}
|
|
1091
505
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
1092
506
|
const witnessVersion = 0;
|
|
1093
|
-
const words = bech32.toWords(pubKeyHash);
|
|
507
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1094
508
|
words.unshift(witnessVersion);
|
|
1095
509
|
const hrp = network === "testnet" ? "tsp" : "sp";
|
|
1096
|
-
const address = bech32.encode(hrp, words);
|
|
510
|
+
const address = base.bech32.encode(hrp, words);
|
|
1097
511
|
return address;
|
|
1098
512
|
} catch (error) {
|
|
1099
513
|
console.error("Spark address derivation failed:", error);
|
|
@@ -1189,9 +603,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1189
603
|
"no route": "NETWORK_ERROR"
|
|
1190
604
|
}
|
|
1191
605
|
};
|
|
1192
|
-
function parseChainError(
|
|
606
|
+
function parseChainError(chain, errorMessage) {
|
|
1193
607
|
const errorLower = errorMessage.toLowerCase();
|
|
1194
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
608
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1195
609
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1196
610
|
if (errorLower.includes(pattern)) {
|
|
1197
611
|
return code;
|
|
@@ -1329,38 +743,38 @@ var ZubariWdkService = class {
|
|
|
1329
743
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1330
744
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1331
745
|
*/
|
|
1332
|
-
async deriveAddress(seed,
|
|
746
|
+
async deriveAddress(seed, chain) {
|
|
1333
747
|
await this.initialize();
|
|
1334
|
-
const path = this.getDerivationPath(
|
|
748
|
+
const path = this.getDerivationPath(chain);
|
|
1335
749
|
try {
|
|
1336
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
750
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1337
751
|
if (response.success && response.address) {
|
|
1338
752
|
return {
|
|
1339
|
-
chain
|
|
753
|
+
chain,
|
|
1340
754
|
address: response.address,
|
|
1341
755
|
path: response.path || path
|
|
1342
756
|
};
|
|
1343
757
|
}
|
|
1344
758
|
} catch (error) {
|
|
1345
|
-
console.warn(`API address derivation failed for ${
|
|
1346
|
-
if (
|
|
1347
|
-
return this.deriveBrowserAddress(seed,
|
|
759
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
760
|
+
if (chain === "ethereum") {
|
|
761
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1348
762
|
}
|
|
1349
763
|
}
|
|
1350
764
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1351
765
|
try {
|
|
1352
766
|
const wdk = this.nativeWdkService;
|
|
1353
767
|
await wdk.initialize(seed);
|
|
1354
|
-
return await wdk.deriveAddress(
|
|
768
|
+
return await wdk.deriveAddress(chain);
|
|
1355
769
|
} catch (error) {
|
|
1356
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
770
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1357
771
|
}
|
|
1358
772
|
}
|
|
1359
|
-
if (
|
|
1360
|
-
return this.deriveBrowserAddress(seed,
|
|
773
|
+
if (chain === "ethereum") {
|
|
774
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1361
775
|
}
|
|
1362
776
|
throw new Error(
|
|
1363
|
-
`WDK API required for ${
|
|
777
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1364
778
|
);
|
|
1365
779
|
}
|
|
1366
780
|
/**
|
|
@@ -1440,13 +854,13 @@ var ZubariWdkService = class {
|
|
|
1440
854
|
/**
|
|
1441
855
|
* Get fee rates for a chain
|
|
1442
856
|
*/
|
|
1443
|
-
async getFeeRates(seed,
|
|
857
|
+
async getFeeRates(seed, chain) {
|
|
1444
858
|
await this.initialize();
|
|
1445
859
|
try {
|
|
1446
860
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1447
861
|
method: "POST",
|
|
1448
862
|
headers: { "Content-Type": "application/json" },
|
|
1449
|
-
body: JSON.stringify({ seed, chain
|
|
863
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1450
864
|
});
|
|
1451
865
|
if (response.ok) {
|
|
1452
866
|
const data = await response.json();
|
|
@@ -1455,20 +869,20 @@ var ZubariWdkService = class {
|
|
|
1455
869
|
}
|
|
1456
870
|
}
|
|
1457
871
|
} catch (error) {
|
|
1458
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
872
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1459
873
|
}
|
|
1460
874
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1461
875
|
}
|
|
1462
876
|
/**
|
|
1463
877
|
* Estimate transaction fee
|
|
1464
878
|
*/
|
|
1465
|
-
async estimateFee(seed,
|
|
879
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1466
880
|
await this.initialize();
|
|
1467
881
|
try {
|
|
1468
882
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1469
883
|
method: "POST",
|
|
1470
884
|
headers: { "Content-Type": "application/json" },
|
|
1471
|
-
body: JSON.stringify({ seed, chain
|
|
885
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1472
886
|
});
|
|
1473
887
|
if (response.ok) {
|
|
1474
888
|
const data = await response.json();
|
|
@@ -1477,9 +891,9 @@ var ZubariWdkService = class {
|
|
|
1477
891
|
}
|
|
1478
892
|
}
|
|
1479
893
|
} catch (error) {
|
|
1480
|
-
console.warn(`Failed to estimate fee for ${
|
|
894
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1481
895
|
}
|
|
1482
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
896
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1483
897
|
}
|
|
1484
898
|
/**
|
|
1485
899
|
* Send a transaction on any supported chain
|
|
@@ -1490,10 +904,10 @@ var ZubariWdkService = class {
|
|
|
1490
904
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1491
905
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1492
906
|
*/
|
|
1493
|
-
async sendTransaction(seed,
|
|
907
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1494
908
|
await this.initialize();
|
|
1495
909
|
const startTime = Date.now();
|
|
1496
|
-
console.log(`[ZubariWdkService] Sending ${
|
|
910
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
1497
911
|
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1498
912
|
amount,
|
|
1499
913
|
network: this.config.network
|
|
@@ -1502,7 +916,7 @@ var ZubariWdkService = class {
|
|
|
1502
916
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1503
917
|
method: "POST",
|
|
1504
918
|
headers: { "Content-Type": "application/json" },
|
|
1505
|
-
body: JSON.stringify({ seed, chain
|
|
919
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1506
920
|
});
|
|
1507
921
|
const elapsed = Date.now() - startTime;
|
|
1508
922
|
if (response.ok) {
|
|
@@ -1512,22 +926,22 @@ var ZubariWdkService = class {
|
|
|
1512
926
|
txHash = txHash.hash;
|
|
1513
927
|
}
|
|
1514
928
|
if (txHash) {
|
|
1515
|
-
const isValid = this.validateTxHash(
|
|
929
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1516
930
|
if (!isValid) {
|
|
1517
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
931
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1518
932
|
}
|
|
1519
933
|
}
|
|
1520
|
-
console.log(`[ZubariWdkService] ${
|
|
934
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1521
935
|
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1522
936
|
elapsed: `${elapsed}ms`
|
|
1523
937
|
});
|
|
1524
938
|
if (!data.success) {
|
|
1525
|
-
const errorCode2 = parseChainError(
|
|
939
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1526
940
|
return {
|
|
1527
941
|
success: false,
|
|
1528
942
|
error: data.error,
|
|
1529
943
|
errorCode: errorCode2,
|
|
1530
|
-
chain
|
|
944
|
+
chain
|
|
1531
945
|
};
|
|
1532
946
|
}
|
|
1533
947
|
return {
|
|
@@ -1536,14 +950,14 @@ var ZubariWdkService = class {
|
|
|
1536
950
|
from: data.from,
|
|
1537
951
|
to: data.to,
|
|
1538
952
|
amount: data.amount,
|
|
1539
|
-
chain: data.chain ||
|
|
953
|
+
chain: data.chain || chain,
|
|
1540
954
|
network: data.network || this.config.network
|
|
1541
955
|
};
|
|
1542
956
|
}
|
|
1543
957
|
const errorData = await response.json().catch(() => ({}));
|
|
1544
958
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1545
|
-
const errorCode = parseChainError(
|
|
1546
|
-
console.error(`[ZubariWdkService] ${
|
|
959
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
960
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
1547
961
|
status: response.status,
|
|
1548
962
|
error: errorMessage,
|
|
1549
963
|
errorCode,
|
|
@@ -1553,13 +967,13 @@ var ZubariWdkService = class {
|
|
|
1553
967
|
success: false,
|
|
1554
968
|
error: errorMessage,
|
|
1555
969
|
errorCode,
|
|
1556
|
-
chain
|
|
970
|
+
chain
|
|
1557
971
|
};
|
|
1558
972
|
} catch (error) {
|
|
1559
973
|
const elapsed = Date.now() - startTime;
|
|
1560
974
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1561
|
-
const errorCode = parseChainError(
|
|
1562
|
-
console.error(`[ZubariWdkService] ${
|
|
975
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
976
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
1563
977
|
error: errorMessage,
|
|
1564
978
|
errorCode,
|
|
1565
979
|
elapsed: `${elapsed}ms`
|
|
@@ -1568,15 +982,15 @@ var ZubariWdkService = class {
|
|
|
1568
982
|
success: false,
|
|
1569
983
|
error: errorMessage,
|
|
1570
984
|
errorCode,
|
|
1571
|
-
chain
|
|
985
|
+
chain
|
|
1572
986
|
};
|
|
1573
987
|
}
|
|
1574
988
|
}
|
|
1575
989
|
/**
|
|
1576
990
|
* Validate transaction hash format for a specific chain
|
|
1577
991
|
*/
|
|
1578
|
-
validateTxHash(
|
|
1579
|
-
switch (
|
|
992
|
+
validateTxHash(chain, txHash) {
|
|
993
|
+
switch (chain) {
|
|
1580
994
|
case "ethereum":
|
|
1581
995
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1582
996
|
case "bitcoin":
|
|
@@ -1608,7 +1022,7 @@ var ZubariWdkService = class {
|
|
|
1608
1022
|
// ==========================================
|
|
1609
1023
|
// Private Helper Methods
|
|
1610
1024
|
// ==========================================
|
|
1611
|
-
getDerivationPath(
|
|
1025
|
+
getDerivationPath(chain) {
|
|
1612
1026
|
const paths = {
|
|
1613
1027
|
bitcoin: this.config.network === "testnet" ? "m/84'/1'/0'/0/0" : "m/84'/0'/0'/0/0",
|
|
1614
1028
|
ethereum: "m/44'/60'/0'/0/0",
|
|
@@ -1617,9 +1031,9 @@ var ZubariWdkService = class {
|
|
|
1617
1031
|
solana: "m/44'/501'/0'/0'",
|
|
1618
1032
|
spark: "m/44'/998'/0'/0/0"
|
|
1619
1033
|
};
|
|
1620
|
-
return paths[
|
|
1034
|
+
return paths[chain];
|
|
1621
1035
|
}
|
|
1622
|
-
getChainSymbol(
|
|
1036
|
+
getChainSymbol(chain) {
|
|
1623
1037
|
const symbols = {
|
|
1624
1038
|
ethereum: "ETH",
|
|
1625
1039
|
bitcoin: "BTC",
|
|
@@ -1628,16 +1042,16 @@ var ZubariWdkService = class {
|
|
|
1628
1042
|
solana: "SOL",
|
|
1629
1043
|
spark: "SAT"
|
|
1630
1044
|
};
|
|
1631
|
-
return symbols[
|
|
1045
|
+
return symbols[chain];
|
|
1632
1046
|
}
|
|
1633
1047
|
/**
|
|
1634
1048
|
* Derive address using browser-compatible libraries
|
|
1635
1049
|
*/
|
|
1636
|
-
async deriveBrowserAddress(seed,
|
|
1637
|
-
const path = this.getDerivationPath(
|
|
1050
|
+
async deriveBrowserAddress(seed, chain) {
|
|
1051
|
+
const path = this.getDerivationPath(chain);
|
|
1638
1052
|
try {
|
|
1639
1053
|
let address;
|
|
1640
|
-
switch (
|
|
1054
|
+
switch (chain) {
|
|
1641
1055
|
case "ethereum":
|
|
1642
1056
|
address = deriveEthereumAddress(seed);
|
|
1643
1057
|
break;
|
|
@@ -1657,11 +1071,11 @@ var ZubariWdkService = class {
|
|
|
1657
1071
|
address = await deriveTonAddress(seed);
|
|
1658
1072
|
break;
|
|
1659
1073
|
default:
|
|
1660
|
-
throw new Error(`Unsupported chain: ${
|
|
1074
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1661
1075
|
}
|
|
1662
|
-
return { chain
|
|
1076
|
+
return { chain, address, path };
|
|
1663
1077
|
} catch (error) {
|
|
1664
|
-
console.error(`Browser derivation failed for ${
|
|
1078
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1665
1079
|
throw error;
|
|
1666
1080
|
}
|
|
1667
1081
|
}
|
|
@@ -1674,7 +1088,7 @@ var ZubariWdkService = class {
|
|
|
1674
1088
|
};
|
|
1675
1089
|
var defaultService = null;
|
|
1676
1090
|
function getZubariWdkService(config) {
|
|
1677
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1091
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1678
1092
|
defaultService = new ZubariWdkService(config);
|
|
1679
1093
|
}
|
|
1680
1094
|
return defaultService;
|
|
@@ -1727,12 +1141,12 @@ var ZubariWallet = class {
|
|
|
1727
1141
|
solana: "solana",
|
|
1728
1142
|
spark: "spark"
|
|
1729
1143
|
};
|
|
1730
|
-
const
|
|
1731
|
-
if (!
|
|
1144
|
+
const chain = chainMap[network];
|
|
1145
|
+
if (!chain) {
|
|
1732
1146
|
throw new Error(`Unsupported network: ${network}`);
|
|
1733
1147
|
}
|
|
1734
1148
|
try {
|
|
1735
|
-
const result = await this.wdkService.deriveAddress(this.seed,
|
|
1149
|
+
const result = await this.wdkService.deriveAddress(this.seed, chain);
|
|
1736
1150
|
const account = {
|
|
1737
1151
|
network,
|
|
1738
1152
|
address: result.address,
|
|
@@ -1787,13 +1201,13 @@ var ZubariWallet = class {
|
|
|
1787
1201
|
solana: "solana",
|
|
1788
1202
|
spark: "spark"
|
|
1789
1203
|
};
|
|
1790
|
-
const
|
|
1791
|
-
if (!
|
|
1204
|
+
const chain = chainMap[network];
|
|
1205
|
+
if (!chain) {
|
|
1792
1206
|
throw new Error(`Unsupported network: ${network}`);
|
|
1793
1207
|
}
|
|
1794
1208
|
try {
|
|
1795
1209
|
const balances = await this.wdkService.getAllBalances(this.seed);
|
|
1796
|
-
const chainBalance = balances[
|
|
1210
|
+
const chainBalance = balances[chain];
|
|
1797
1211
|
if (chainBalance) {
|
|
1798
1212
|
const balanceValue = BigInt(chainBalance.balance || "0");
|
|
1799
1213
|
const decimals = networkConfig.nativeCurrency.decimals;
|
|
@@ -1882,14 +1296,14 @@ var ZubariWallet = class {
|
|
|
1882
1296
|
solana: "solana",
|
|
1883
1297
|
spark: "spark"
|
|
1884
1298
|
};
|
|
1885
|
-
const
|
|
1886
|
-
if (!
|
|
1299
|
+
const chain = chainMap[network];
|
|
1300
|
+
if (!chain) {
|
|
1887
1301
|
throw new Error(`Unsupported network: ${network}`);
|
|
1888
1302
|
}
|
|
1889
1303
|
try {
|
|
1890
1304
|
const result = await this.wdkService.sendTransaction(
|
|
1891
1305
|
this.seed,
|
|
1892
|
-
|
|
1306
|
+
chain,
|
|
1893
1307
|
to,
|
|
1894
1308
|
amount.toString()
|
|
1895
1309
|
);
|
|
@@ -2564,8 +1978,8 @@ async function fetchPrices() {
|
|
|
2564
1978
|
if (response.ok) {
|
|
2565
1979
|
const data = await response.json();
|
|
2566
1980
|
const prices = {};
|
|
2567
|
-
for (const [
|
|
2568
|
-
prices[
|
|
1981
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1982
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2569
1983
|
}
|
|
2570
1984
|
priceCache = { prices, timestamp: Date.now() };
|
|
2571
1985
|
return prices;
|
|
@@ -2575,9 +1989,22 @@ async function fetchPrices() {
|
|
|
2575
1989
|
}
|
|
2576
1990
|
return priceCache?.prices || {};
|
|
2577
1991
|
}
|
|
2578
|
-
async function getPriceForChain(
|
|
1992
|
+
async function getPriceForChain(chain) {
|
|
2579
1993
|
const prices = await fetchPrices();
|
|
2580
|
-
return prices[
|
|
1994
|
+
return prices[chain] || 0;
|
|
1995
|
+
}
|
|
1996
|
+
function tonFriendlyToRaw(addr) {
|
|
1997
|
+
if (addr.includes(":")) return addr;
|
|
1998
|
+
try {
|
|
1999
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
2000
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
2001
|
+
if (bytes.length !== 36) return addr;
|
|
2002
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
2003
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2004
|
+
return `${workchain}:${hash}`;
|
|
2005
|
+
} catch {
|
|
2006
|
+
return addr;
|
|
2007
|
+
}
|
|
2581
2008
|
}
|
|
2582
2009
|
var STORAGE_KEYS = {
|
|
2583
2010
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2783,9 +2210,9 @@ var WalletManager = class _WalletManager {
|
|
|
2783
2210
|
if (!this.derivedAddress) {
|
|
2784
2211
|
throw new Error("Wallet not initialized");
|
|
2785
2212
|
}
|
|
2786
|
-
const
|
|
2213
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2787
2214
|
const client = viem.createPublicClient({
|
|
2788
|
-
chain
|
|
2215
|
+
chain,
|
|
2789
2216
|
transport: viem.http(this.config.rpcUrl, {
|
|
2790
2217
|
timeout: 15e3,
|
|
2791
2218
|
// 15 second timeout
|
|
@@ -2807,9 +2234,9 @@ var WalletManager = class _WalletManager {
|
|
|
2807
2234
|
* Create viem public client for the current network
|
|
2808
2235
|
*/
|
|
2809
2236
|
getPublicClient() {
|
|
2810
|
-
const
|
|
2237
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2811
2238
|
return viem.createPublicClient({
|
|
2812
|
-
chain
|
|
2239
|
+
chain,
|
|
2813
2240
|
transport: viem.http(this.config.rpcUrl, {
|
|
2814
2241
|
timeout: 15e3,
|
|
2815
2242
|
// 15 second timeout
|
|
@@ -2863,11 +2290,11 @@ var WalletManager = class _WalletManager {
|
|
|
2863
2290
|
*
|
|
2864
2291
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2865
2292
|
*/
|
|
2866
|
-
static async deriveAddressForChainAsync(seed,
|
|
2867
|
-
if (
|
|
2293
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
2294
|
+
if (chain === "ethereum") {
|
|
2868
2295
|
try {
|
|
2869
2296
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2870
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
2297
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2871
2298
|
return result2.address;
|
|
2872
2299
|
} catch (error) {
|
|
2873
2300
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2875,7 +2302,7 @@ var WalletManager = class _WalletManager {
|
|
|
2875
2302
|
}
|
|
2876
2303
|
}
|
|
2877
2304
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2878
|
-
const result = await wdkService.deriveAddress(seed,
|
|
2305
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2879
2306
|
return result.address;
|
|
2880
2307
|
}
|
|
2881
2308
|
/**
|
|
@@ -2884,14 +2311,14 @@ var WalletManager = class _WalletManager {
|
|
|
2884
2311
|
*
|
|
2885
2312
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2886
2313
|
*/
|
|
2887
|
-
static deriveAddressForChain(seed,
|
|
2888
|
-
if (
|
|
2314
|
+
static deriveAddressForChain(seed, chain) {
|
|
2315
|
+
if (chain === "ethereum") {
|
|
2889
2316
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2890
2317
|
const ethNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2891
2318
|
return ethNode.address;
|
|
2892
2319
|
}
|
|
2893
2320
|
throw new Error(
|
|
2894
|
-
`Sync derivation not supported for ${
|
|
2321
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2895
2322
|
);
|
|
2896
2323
|
}
|
|
2897
2324
|
/**
|
|
@@ -2923,9 +2350,9 @@ var WalletManager = class _WalletManager {
|
|
|
2923
2350
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2924
2351
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2925
2352
|
const addresses = {};
|
|
2926
|
-
for (const [
|
|
2927
|
-
if (enabledChainsSet.has(
|
|
2928
|
-
addresses[
|
|
2353
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
2354
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
2355
|
+
addresses[chain] = address;
|
|
2929
2356
|
}
|
|
2930
2357
|
}
|
|
2931
2358
|
this.derivedAddresses = addresses;
|
|
@@ -2966,10 +2393,10 @@ var WalletManager = class _WalletManager {
|
|
|
2966
2393
|
*/
|
|
2967
2394
|
normalizeAddresses(addresses) {
|
|
2968
2395
|
const normalized = {};
|
|
2969
|
-
for (const [
|
|
2396
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2970
2397
|
const addr = this.normalizeAddress(value);
|
|
2971
2398
|
if (addr) {
|
|
2972
|
-
normalized[
|
|
2399
|
+
normalized[chain] = addr;
|
|
2973
2400
|
}
|
|
2974
2401
|
}
|
|
2975
2402
|
return normalized;
|
|
@@ -3022,20 +2449,20 @@ var WalletManager = class _WalletManager {
|
|
|
3022
2449
|
* Get address for a specific chain
|
|
3023
2450
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
3024
2451
|
*/
|
|
3025
|
-
getAddressForChain(
|
|
3026
|
-
const cachedValue = this.derivedAddresses[
|
|
2452
|
+
getAddressForChain(chain) {
|
|
2453
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
3027
2454
|
if (cachedValue) {
|
|
3028
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
2455
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
3029
2456
|
const addr = this.normalizeAddress(cachedValue);
|
|
3030
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
2457
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) normalized:`, addr);
|
|
3031
2458
|
if (addr) {
|
|
3032
|
-
this.derivedAddresses[
|
|
2459
|
+
this.derivedAddresses[chain] = addr;
|
|
3033
2460
|
return addr;
|
|
3034
2461
|
}
|
|
3035
2462
|
}
|
|
3036
|
-
if (
|
|
3037
|
-
this.derivedAddresses[
|
|
3038
|
-
return this.derivedAddresses[
|
|
2463
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
2464
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
2465
|
+
return this.derivedAddresses[chain];
|
|
3039
2466
|
}
|
|
3040
2467
|
return null;
|
|
3041
2468
|
}
|
|
@@ -3048,11 +2475,11 @@ var WalletManager = class _WalletManager {
|
|
|
3048
2475
|
/**
|
|
3049
2476
|
* Set the selected chain
|
|
3050
2477
|
*/
|
|
3051
|
-
setSelectedChain(
|
|
3052
|
-
if (!this.config.enabledChains.includes(
|
|
3053
|
-
throw new Error(`Chain ${
|
|
2478
|
+
setSelectedChain(chain) {
|
|
2479
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
2480
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
3054
2481
|
}
|
|
3055
|
-
this.selectedChain =
|
|
2482
|
+
this.selectedChain = chain;
|
|
3056
2483
|
}
|
|
3057
2484
|
/**
|
|
3058
2485
|
* Get the currently selected chain
|
|
@@ -3069,22 +2496,22 @@ var WalletManager = class _WalletManager {
|
|
|
3069
2496
|
/**
|
|
3070
2497
|
* Get chain configuration
|
|
3071
2498
|
*/
|
|
3072
|
-
getChainConfig(
|
|
3073
|
-
return getNetworkConfig(
|
|
2499
|
+
getChainConfig(chain) {
|
|
2500
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
3074
2501
|
}
|
|
3075
2502
|
/**
|
|
3076
2503
|
* Fetch balance for a specific chain
|
|
3077
2504
|
* Note: Currently only Ethereum is implemented
|
|
3078
2505
|
*/
|
|
3079
|
-
async fetchBalanceForChain(
|
|
3080
|
-
const address = this.getAddressForChain(
|
|
2506
|
+
async fetchBalanceForChain(chain) {
|
|
2507
|
+
const address = this.getAddressForChain(chain);
|
|
3081
2508
|
if (!address) {
|
|
3082
|
-
throw new Error(`No address for chain ${
|
|
2509
|
+
throw new Error(`No address for chain ${chain}`);
|
|
3083
2510
|
}
|
|
3084
|
-
const networkConfig = this.getChainConfig(
|
|
2511
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3085
2512
|
let balance = "0";
|
|
3086
2513
|
const tokenBalances = {};
|
|
3087
|
-
if (
|
|
2514
|
+
if (chain === "ethereum") {
|
|
3088
2515
|
const viemChain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
3089
2516
|
const isTestnet = this.config.network !== "mainnet";
|
|
3090
2517
|
const client = viem.createPublicClient({
|
|
@@ -3131,7 +2558,7 @@ var WalletManager = class _WalletManager {
|
|
|
3131
2558
|
} else if (usdtResult.status === "rejected") {
|
|
3132
2559
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
3133
2560
|
}
|
|
3134
|
-
} else if (
|
|
2561
|
+
} else if (chain === "bitcoin") {
|
|
3135
2562
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
3136
2563
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
3137
2564
|
"https://mempool.space/testnet/api",
|
|
@@ -3163,7 +2590,7 @@ var WalletManager = class _WalletManager {
|
|
|
3163
2590
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
3164
2591
|
}
|
|
3165
2592
|
}
|
|
3166
|
-
} else if (
|
|
2593
|
+
} else if (chain === "solana") {
|
|
3167
2594
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
3168
2595
|
try {
|
|
3169
2596
|
const response = await fetch(rpcUrl, {
|
|
@@ -3183,7 +2610,7 @@ var WalletManager = class _WalletManager {
|
|
|
3183
2610
|
}
|
|
3184
2611
|
}
|
|
3185
2612
|
} catch (error) {
|
|
3186
|
-
console.warn(`Failed to fetch ${
|
|
2613
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3187
2614
|
}
|
|
3188
2615
|
const isTestnet = this.config.network !== "mainnet";
|
|
3189
2616
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -3217,7 +2644,7 @@ var WalletManager = class _WalletManager {
|
|
|
3217
2644
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
3218
2645
|
}
|
|
3219
2646
|
}
|
|
3220
|
-
} else if (
|
|
2647
|
+
} else if (chain === "tron") {
|
|
3221
2648
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
3222
2649
|
const baseUrl = tronConfig.rpcUrl;
|
|
3223
2650
|
try {
|
|
@@ -3246,9 +2673,9 @@ var WalletManager = class _WalletManager {
|
|
|
3246
2673
|
}
|
|
3247
2674
|
}
|
|
3248
2675
|
} catch (error) {
|
|
3249
|
-
console.warn(`Failed to fetch ${
|
|
2676
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3250
2677
|
}
|
|
3251
|
-
} else if (
|
|
2678
|
+
} else if (chain === "ton") {
|
|
3252
2679
|
const isTestnet = this.config.network !== "mainnet";
|
|
3253
2680
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
3254
2681
|
try {
|
|
@@ -3264,25 +2691,36 @@ var WalletManager = class _WalletManager {
|
|
|
3264
2691
|
}
|
|
3265
2692
|
}
|
|
3266
2693
|
} catch (error) {
|
|
3267
|
-
console.warn(`Failed to fetch ${
|
|
2694
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3268
2695
|
}
|
|
3269
2696
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
3270
2697
|
if (usdtJetton) {
|
|
3271
|
-
const
|
|
2698
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
3272
2699
|
try {
|
|
2700
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
3273
2701
|
const jettonResponse = await fetch(
|
|
3274
|
-
`${
|
|
2702
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
3275
2703
|
{ headers: { "Accept": "application/json" } }
|
|
3276
2704
|
);
|
|
3277
2705
|
if (jettonResponse.ok) {
|
|
3278
2706
|
const jettonData = await jettonResponse.json();
|
|
3279
|
-
const
|
|
3280
|
-
if (
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
2707
|
+
const balances = jettonData.balances;
|
|
2708
|
+
if (balances && balances.length > 0) {
|
|
2709
|
+
for (const jb of balances) {
|
|
2710
|
+
const jettonAddr = jb.jetton?.address;
|
|
2711
|
+
if (jettonAddr) {
|
|
2712
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2713
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2714
|
+
const rawBalance = jb.balance;
|
|
2715
|
+
if (rawBalance) {
|
|
2716
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2717
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2718
|
+
if (usdtAmount > 0) {
|
|
2719
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
break;
|
|
2723
|
+
}
|
|
3286
2724
|
}
|
|
3287
2725
|
}
|
|
3288
2726
|
}
|
|
@@ -3291,7 +2729,7 @@ var WalletManager = class _WalletManager {
|
|
|
3291
2729
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
3292
2730
|
}
|
|
3293
2731
|
}
|
|
3294
|
-
} else if (
|
|
2732
|
+
} else if (chain === "spark") {
|
|
3295
2733
|
try {
|
|
3296
2734
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
3297
2735
|
method: "POST",
|
|
@@ -3310,14 +2748,14 @@ var WalletManager = class _WalletManager {
|
|
|
3310
2748
|
}
|
|
3311
2749
|
}
|
|
3312
2750
|
} catch (error) {
|
|
3313
|
-
console.warn(`Failed to fetch ${
|
|
2751
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3314
2752
|
}
|
|
3315
2753
|
}
|
|
3316
|
-
const priceUsd = await getPriceForChain(
|
|
2754
|
+
const priceUsd = await getPriceForChain(chain);
|
|
3317
2755
|
const balanceNum = parseFloat(balance) || 0;
|
|
3318
2756
|
const balanceUsd = balanceNum * priceUsd;
|
|
3319
2757
|
return {
|
|
3320
|
-
chain
|
|
2758
|
+
chain,
|
|
3321
2759
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3322
2760
|
balance,
|
|
3323
2761
|
balanceUsd,
|
|
@@ -3331,19 +2769,19 @@ var WalletManager = class _WalletManager {
|
|
|
3331
2769
|
*/
|
|
3332
2770
|
async fetchAllBalances() {
|
|
3333
2771
|
const balances = [];
|
|
3334
|
-
for (const
|
|
2772
|
+
for (const chain of this.config.enabledChains) {
|
|
3335
2773
|
try {
|
|
3336
|
-
const balance = await this.fetchBalanceForChain(
|
|
2774
|
+
const balance = await this.fetchBalanceForChain(chain);
|
|
3337
2775
|
balances.push(balance);
|
|
3338
2776
|
} catch (error) {
|
|
3339
|
-
console.error(`Failed to fetch balance for ${
|
|
3340
|
-
const networkConfig = this.getChainConfig(
|
|
2777
|
+
console.error(`Failed to fetch balance for ${chain}:`, error);
|
|
2778
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3341
2779
|
balances.push({
|
|
3342
|
-
chain
|
|
2780
|
+
chain,
|
|
3343
2781
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3344
2782
|
balance: "0",
|
|
3345
2783
|
balanceUsd: 0,
|
|
3346
|
-
address: this.getAddressForChain(
|
|
2784
|
+
address: this.getAddressForChain(chain) || "",
|
|
3347
2785
|
decimals: networkConfig.nativeCurrency.decimals
|
|
3348
2786
|
});
|
|
3349
2787
|
}
|
|
@@ -3373,13 +2811,13 @@ var WalletManager = class _WalletManager {
|
|
|
3373
2811
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
3374
2812
|
* @returns Transaction result with hash and status
|
|
3375
2813
|
*/
|
|
3376
|
-
async sendTransaction(
|
|
2814
|
+
async sendTransaction(chain, to, amount, token) {
|
|
3377
2815
|
if (!this.currentSeed) {
|
|
3378
2816
|
return { success: false, error: "Wallet is locked" };
|
|
3379
2817
|
}
|
|
3380
|
-
const fromAddress = this.getAddressForChain(
|
|
2818
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
3381
2819
|
if (!fromAddress) {
|
|
3382
|
-
return { success: false, error: `No address for chain ${
|
|
2820
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
3383
2821
|
}
|
|
3384
2822
|
try {
|
|
3385
2823
|
const headers = {
|
|
@@ -3393,7 +2831,7 @@ var WalletManager = class _WalletManager {
|
|
|
3393
2831
|
headers,
|
|
3394
2832
|
body: JSON.stringify({
|
|
3395
2833
|
seed: this.currentSeed,
|
|
3396
|
-
chain
|
|
2834
|
+
chain,
|
|
3397
2835
|
to,
|
|
3398
2836
|
amount,
|
|
3399
2837
|
token,
|
|
@@ -3402,12 +2840,12 @@ var WalletManager = class _WalletManager {
|
|
|
3402
2840
|
});
|
|
3403
2841
|
if (response.ok) {
|
|
3404
2842
|
const data = await response.json();
|
|
3405
|
-
console.log(`Transaction sent on ${
|
|
2843
|
+
console.log(`Transaction sent on ${chain}:`, data);
|
|
3406
2844
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
3407
2845
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
3408
2846
|
txHash = txHash.hash;
|
|
3409
2847
|
}
|
|
3410
|
-
if (
|
|
2848
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
3411
2849
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
3412
2850
|
}
|
|
3413
2851
|
return {
|
|
@@ -3416,7 +2854,7 @@ var WalletManager = class _WalletManager {
|
|
|
3416
2854
|
from: fromAddress,
|
|
3417
2855
|
to,
|
|
3418
2856
|
amount,
|
|
3419
|
-
chain
|
|
2857
|
+
chain
|
|
3420
2858
|
};
|
|
3421
2859
|
}
|
|
3422
2860
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -3425,7 +2863,7 @@ var WalletManager = class _WalletManager {
|
|
|
3425
2863
|
error: errorData.error || `HTTP ${response.status}`
|
|
3426
2864
|
};
|
|
3427
2865
|
} catch (error) {
|
|
3428
|
-
console.error(`Transaction failed on ${
|
|
2866
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
3429
2867
|
return {
|
|
3430
2868
|
success: false,
|
|
3431
2869
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -3435,7 +2873,7 @@ var WalletManager = class _WalletManager {
|
|
|
3435
2873
|
/**
|
|
3436
2874
|
* Estimate transaction fee using Tether WDK
|
|
3437
2875
|
*/
|
|
3438
|
-
async estimateFee(
|
|
2876
|
+
async estimateFee(chain, to, amount, token) {
|
|
3439
2877
|
try {
|
|
3440
2878
|
const headers = {
|
|
3441
2879
|
"Content-Type": "application/json"
|
|
@@ -3447,7 +2885,7 @@ var WalletManager = class _WalletManager {
|
|
|
3447
2885
|
method: "POST",
|
|
3448
2886
|
headers,
|
|
3449
2887
|
body: JSON.stringify({
|
|
3450
|
-
chain
|
|
2888
|
+
chain,
|
|
3451
2889
|
to,
|
|
3452
2890
|
amount,
|
|
3453
2891
|
token,
|
|
@@ -3471,14 +2909,6 @@ var WalletManager = class _WalletManager {
|
|
|
3471
2909
|
}
|
|
3472
2910
|
}
|
|
3473
2911
|
};
|
|
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
2912
|
|
|
3483
2913
|
exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS;
|
|
3484
2914
|
exports.WalletManager = WalletManager;
|