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