@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.mjs
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { Wallet, HDNodeWallet } from 'ethers';
|
|
2
2
|
import { generateMnemonic, validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';
|
|
3
3
|
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
8
|
-
import { createView, concatBytes, abytes } from '@noble/hashes/utils.js';
|
|
9
|
-
import { sha256 as sha256$1 } from '@noble/hashes/sha256';
|
|
4
|
+
import { HDKey } from '@scure/bip32';
|
|
5
|
+
import { bech32, base58check } from '@scure/base';
|
|
6
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
10
7
|
import { ripemd160 } from '@noble/hashes/ripemd160';
|
|
11
8
|
import { createPublicClient, http, formatEther, getAddress } from 'viem';
|
|
12
9
|
import { mainnet, sepolia } from 'viem/chains';
|
|
@@ -132,8 +129,8 @@ var TESTNET_NETWORKS = {
|
|
|
132
129
|
var USDT_ADDRESSES = {
|
|
133
130
|
ethereum: {
|
|
134
131
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
135
|
-
testnet: "
|
|
136
|
-
// Sepolia
|
|
132
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
133
|
+
// Sepolia (Test Tether USD)
|
|
137
134
|
},
|
|
138
135
|
tron: {
|
|
139
136
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -278,14 +275,14 @@ var WdkApiClient = class {
|
|
|
278
275
|
/**
|
|
279
276
|
* Derive address for a specific chain using Tether WDK
|
|
280
277
|
*/
|
|
281
|
-
async deriveAddress(seed,
|
|
278
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
282
279
|
try {
|
|
283
280
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
284
281
|
method: "POST",
|
|
285
282
|
headers: {
|
|
286
283
|
"Content-Type": "application/json"
|
|
287
284
|
},
|
|
288
|
-
body: JSON.stringify({ seed, chain
|
|
285
|
+
body: JSON.stringify({ seed, chain, network })
|
|
289
286
|
});
|
|
290
287
|
return await response.json();
|
|
291
288
|
} catch (error) {
|
|
@@ -318,14 +315,14 @@ var WdkApiClient = class {
|
|
|
318
315
|
/**
|
|
319
316
|
* Send a transaction on a specific chain using Tether WDK
|
|
320
317
|
*/
|
|
321
|
-
async sendTransaction(seed,
|
|
318
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
322
319
|
try {
|
|
323
320
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
324
321
|
method: "POST",
|
|
325
322
|
headers: {
|
|
326
323
|
"Content-Type": "application/json"
|
|
327
324
|
},
|
|
328
|
-
body: JSON.stringify({ seed, chain
|
|
325
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
329
326
|
});
|
|
330
327
|
return await response.json();
|
|
331
328
|
} catch (error) {
|
|
@@ -339,14 +336,14 @@ var WdkApiClient = class {
|
|
|
339
336
|
* Get transaction history for an address on a specific chain
|
|
340
337
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
341
338
|
*/
|
|
342
|
-
async getTransactionHistory(seed,
|
|
339
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
343
340
|
try {
|
|
344
341
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
345
342
|
method: "POST",
|
|
346
343
|
headers: {
|
|
347
344
|
"Content-Type": "application/json"
|
|
348
345
|
},
|
|
349
|
-
body: JSON.stringify({ seed, chain
|
|
346
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
350
347
|
});
|
|
351
348
|
return await response.json();
|
|
352
349
|
} catch (error) {
|
|
@@ -360,14 +357,14 @@ var WdkApiClient = class {
|
|
|
360
357
|
* Get transaction status by hash
|
|
361
358
|
* Fetches from blockchain explorers to check confirmation status
|
|
362
359
|
*/
|
|
363
|
-
async getTransactionStatus(txHash,
|
|
360
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
364
361
|
try {
|
|
365
362
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
366
363
|
method: "POST",
|
|
367
364
|
headers: {
|
|
368
365
|
"Content-Type": "application/json"
|
|
369
366
|
},
|
|
370
|
-
body: JSON.stringify({ txHash, chain
|
|
367
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
371
368
|
});
|
|
372
369
|
return await response.json();
|
|
373
370
|
} catch (error) {
|
|
@@ -388,589 +385,6 @@ function getWdkApiClient(baseUrl) {
|
|
|
388
385
|
}
|
|
389
386
|
return wdkApiClient;
|
|
390
387
|
}
|
|
391
|
-
|
|
392
|
-
// node_modules/@scure/base/index.js
|
|
393
|
-
function isBytes(a) {
|
|
394
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
395
|
-
}
|
|
396
|
-
function isArrayOf(isString, arr) {
|
|
397
|
-
if (!Array.isArray(arr))
|
|
398
|
-
return false;
|
|
399
|
-
if (arr.length === 0)
|
|
400
|
-
return true;
|
|
401
|
-
if (isString) {
|
|
402
|
-
return arr.every((item) => typeof item === "string");
|
|
403
|
-
} else {
|
|
404
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
function afn(input) {
|
|
408
|
-
if (typeof input !== "function")
|
|
409
|
-
throw new Error("function expected");
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
function astr(label, input) {
|
|
413
|
-
if (typeof input !== "string")
|
|
414
|
-
throw new Error(`${label}: string expected`);
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
|
-
function anumber(n) {
|
|
418
|
-
if (!Number.isSafeInteger(n))
|
|
419
|
-
throw new Error(`invalid integer: ${n}`);
|
|
420
|
-
}
|
|
421
|
-
function aArr(input) {
|
|
422
|
-
if (!Array.isArray(input))
|
|
423
|
-
throw new Error("array expected");
|
|
424
|
-
}
|
|
425
|
-
function astrArr(label, input) {
|
|
426
|
-
if (!isArrayOf(true, input))
|
|
427
|
-
throw new Error(`${label}: array of strings expected`);
|
|
428
|
-
}
|
|
429
|
-
function anumArr(label, input) {
|
|
430
|
-
if (!isArrayOf(false, input))
|
|
431
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
432
|
-
}
|
|
433
|
-
// @__NO_SIDE_EFFECTS__
|
|
434
|
-
function chain(...args) {
|
|
435
|
-
const id = (a) => a;
|
|
436
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
437
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
438
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
439
|
-
return { encode, decode };
|
|
440
|
-
}
|
|
441
|
-
// @__NO_SIDE_EFFECTS__
|
|
442
|
-
function alphabet(letters) {
|
|
443
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
444
|
-
const len = lettersA.length;
|
|
445
|
-
astrArr("alphabet", lettersA);
|
|
446
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
447
|
-
return {
|
|
448
|
-
encode: (digits) => {
|
|
449
|
-
aArr(digits);
|
|
450
|
-
return digits.map((i) => {
|
|
451
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
452
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
453
|
-
return lettersA[i];
|
|
454
|
-
});
|
|
455
|
-
},
|
|
456
|
-
decode: (input) => {
|
|
457
|
-
aArr(input);
|
|
458
|
-
return input.map((letter) => {
|
|
459
|
-
astr("alphabet.decode", letter);
|
|
460
|
-
const i = indexes.get(letter);
|
|
461
|
-
if (i === void 0)
|
|
462
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
463
|
-
return i;
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
// @__NO_SIDE_EFFECTS__
|
|
469
|
-
function join(separator = "") {
|
|
470
|
-
astr("join", separator);
|
|
471
|
-
return {
|
|
472
|
-
encode: (from) => {
|
|
473
|
-
astrArr("join.decode", from);
|
|
474
|
-
return from.join(separator);
|
|
475
|
-
},
|
|
476
|
-
decode: (to) => {
|
|
477
|
-
astr("join.decode", to);
|
|
478
|
-
return to.split(separator);
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
function convertRadix(data, from, to) {
|
|
483
|
-
if (from < 2)
|
|
484
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
485
|
-
if (to < 2)
|
|
486
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
487
|
-
aArr(data);
|
|
488
|
-
if (!data.length)
|
|
489
|
-
return [];
|
|
490
|
-
let pos = 0;
|
|
491
|
-
const res = [];
|
|
492
|
-
const digits = Array.from(data, (d) => {
|
|
493
|
-
anumber(d);
|
|
494
|
-
if (d < 0 || d >= from)
|
|
495
|
-
throw new Error(`invalid integer: ${d}`);
|
|
496
|
-
return d;
|
|
497
|
-
});
|
|
498
|
-
const dlen = digits.length;
|
|
499
|
-
while (true) {
|
|
500
|
-
let carry = 0;
|
|
501
|
-
let done = true;
|
|
502
|
-
for (let i = pos; i < dlen; i++) {
|
|
503
|
-
const digit = digits[i];
|
|
504
|
-
const fromCarry = from * carry;
|
|
505
|
-
const digitBase = fromCarry + digit;
|
|
506
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
507
|
-
throw new Error("convertRadix: carry overflow");
|
|
508
|
-
}
|
|
509
|
-
const div = digitBase / to;
|
|
510
|
-
carry = digitBase % to;
|
|
511
|
-
const rounded = Math.floor(div);
|
|
512
|
-
digits[i] = rounded;
|
|
513
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
514
|
-
throw new Error("convertRadix: carry overflow");
|
|
515
|
-
if (!done)
|
|
516
|
-
continue;
|
|
517
|
-
else if (!rounded)
|
|
518
|
-
pos = i;
|
|
519
|
-
else
|
|
520
|
-
done = false;
|
|
521
|
-
}
|
|
522
|
-
res.push(carry);
|
|
523
|
-
if (done)
|
|
524
|
-
break;
|
|
525
|
-
}
|
|
526
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
527
|
-
res.push(0);
|
|
528
|
-
return res.reverse();
|
|
529
|
-
}
|
|
530
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
531
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
532
|
-
var powers = /* @__PURE__ */ (() => {
|
|
533
|
-
let res = [];
|
|
534
|
-
for (let i = 0; i < 40; i++)
|
|
535
|
-
res.push(2 ** i);
|
|
536
|
-
return res;
|
|
537
|
-
})();
|
|
538
|
-
function convertRadix2(data, from, to, padding) {
|
|
539
|
-
aArr(data);
|
|
540
|
-
if (from <= 0 || from > 32)
|
|
541
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
542
|
-
if (to <= 0 || to > 32)
|
|
543
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
544
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
545
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
546
|
-
}
|
|
547
|
-
let carry = 0;
|
|
548
|
-
let pos = 0;
|
|
549
|
-
const max = powers[from];
|
|
550
|
-
const mask = powers[to] - 1;
|
|
551
|
-
const res = [];
|
|
552
|
-
for (const n of data) {
|
|
553
|
-
anumber(n);
|
|
554
|
-
if (n >= max)
|
|
555
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
556
|
-
carry = carry << from | n;
|
|
557
|
-
if (pos + from > 32)
|
|
558
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
559
|
-
pos += from;
|
|
560
|
-
for (; pos >= to; pos -= to)
|
|
561
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
562
|
-
const pow = powers[pos];
|
|
563
|
-
if (pow === void 0)
|
|
564
|
-
throw new Error("invalid carry");
|
|
565
|
-
carry &= pow - 1;
|
|
566
|
-
}
|
|
567
|
-
carry = carry << to - pos & mask;
|
|
568
|
-
if (!padding && pos >= from)
|
|
569
|
-
throw new Error("Excess padding");
|
|
570
|
-
if (!padding && carry > 0)
|
|
571
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
572
|
-
if (padding && pos > 0)
|
|
573
|
-
res.push(carry >>> 0);
|
|
574
|
-
return res;
|
|
575
|
-
}
|
|
576
|
-
// @__NO_SIDE_EFFECTS__
|
|
577
|
-
function radix(num) {
|
|
578
|
-
anumber(num);
|
|
579
|
-
const _256 = 2 ** 8;
|
|
580
|
-
return {
|
|
581
|
-
encode: (bytes) => {
|
|
582
|
-
if (!isBytes(bytes))
|
|
583
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
584
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
585
|
-
},
|
|
586
|
-
decode: (digits) => {
|
|
587
|
-
anumArr("radix.decode", digits);
|
|
588
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
// @__NO_SIDE_EFFECTS__
|
|
593
|
-
function radix2(bits, revPadding = false) {
|
|
594
|
-
anumber(bits);
|
|
595
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
596
|
-
throw new Error("radix2: carry overflow");
|
|
597
|
-
return {
|
|
598
|
-
encode: (bytes) => {
|
|
599
|
-
if (!isBytes(bytes))
|
|
600
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
601
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
602
|
-
},
|
|
603
|
-
decode: (digits) => {
|
|
604
|
-
anumArr("radix2.decode", digits);
|
|
605
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
function unsafeWrapper(fn) {
|
|
610
|
-
afn(fn);
|
|
611
|
-
return function(...args) {
|
|
612
|
-
try {
|
|
613
|
-
return fn.apply(null, args);
|
|
614
|
-
} catch (e) {
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
function checksum(len, fn) {
|
|
619
|
-
anumber(len);
|
|
620
|
-
afn(fn);
|
|
621
|
-
return {
|
|
622
|
-
encode(data) {
|
|
623
|
-
if (!isBytes(data))
|
|
624
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
625
|
-
const sum = fn(data).slice(0, len);
|
|
626
|
-
const res = new Uint8Array(data.length + len);
|
|
627
|
-
res.set(data);
|
|
628
|
-
res.set(sum, data.length);
|
|
629
|
-
return res;
|
|
630
|
-
},
|
|
631
|
-
decode(data) {
|
|
632
|
-
if (!isBytes(data))
|
|
633
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
634
|
-
const payload = data.slice(0, -len);
|
|
635
|
-
const oldChecksum = data.slice(-len);
|
|
636
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
637
|
-
for (let i = 0; i < len; i++)
|
|
638
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
639
|
-
throw new Error("Invalid checksum");
|
|
640
|
-
return payload;
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
645
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
646
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
647
|
-
var base58check = createBase58check;
|
|
648
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
649
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
650
|
-
function bech32Polymod(pre) {
|
|
651
|
-
const b = pre >> 25;
|
|
652
|
-
let chk = (pre & 33554431) << 5;
|
|
653
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
654
|
-
if ((b >> i & 1) === 1)
|
|
655
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
656
|
-
}
|
|
657
|
-
return chk;
|
|
658
|
-
}
|
|
659
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
660
|
-
const len = prefix.length;
|
|
661
|
-
let chk = 1;
|
|
662
|
-
for (let i = 0; i < len; i++) {
|
|
663
|
-
const c = prefix.charCodeAt(i);
|
|
664
|
-
if (c < 33 || c > 126)
|
|
665
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
666
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
667
|
-
}
|
|
668
|
-
chk = bech32Polymod(chk);
|
|
669
|
-
for (let i = 0; i < len; i++)
|
|
670
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
671
|
-
for (let v of words)
|
|
672
|
-
chk = bech32Polymod(chk) ^ v;
|
|
673
|
-
for (let i = 0; i < 6; i++)
|
|
674
|
-
chk = bech32Polymod(chk);
|
|
675
|
-
chk ^= encodingConst;
|
|
676
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
677
|
-
}
|
|
678
|
-
// @__NO_SIDE_EFFECTS__
|
|
679
|
-
function genBech32(encoding) {
|
|
680
|
-
const ENCODING_CONST = 1 ;
|
|
681
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
682
|
-
const fromWords = _words.decode;
|
|
683
|
-
const toWords = _words.encode;
|
|
684
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
685
|
-
function encode(prefix, words, limit = 90) {
|
|
686
|
-
astr("bech32.encode prefix", prefix);
|
|
687
|
-
if (isBytes(words))
|
|
688
|
-
words = Array.from(words);
|
|
689
|
-
anumArr("bech32.encode", words);
|
|
690
|
-
const plen = prefix.length;
|
|
691
|
-
if (plen === 0)
|
|
692
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
693
|
-
const actualLength = plen + 7 + words.length;
|
|
694
|
-
if (limit !== false && actualLength > limit)
|
|
695
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
696
|
-
const lowered = prefix.toLowerCase();
|
|
697
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
698
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
699
|
-
}
|
|
700
|
-
function decode(str, limit = 90) {
|
|
701
|
-
astr("bech32.decode input", str);
|
|
702
|
-
const slen = str.length;
|
|
703
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
704
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
705
|
-
const lowered = str.toLowerCase();
|
|
706
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
707
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
708
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
709
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
710
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
711
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
712
|
-
const data = lowered.slice(sepIndex + 1);
|
|
713
|
-
if (data.length < 6)
|
|
714
|
-
throw new Error("Data must be at least 6 characters long");
|
|
715
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
716
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
717
|
-
if (!data.endsWith(sum))
|
|
718
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
719
|
-
return { prefix, words };
|
|
720
|
-
}
|
|
721
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
722
|
-
function decodeToBytes(str) {
|
|
723
|
-
const { prefix, words } = decode(str, false);
|
|
724
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
725
|
-
}
|
|
726
|
-
function encodeFromBytes(prefix, bytes) {
|
|
727
|
-
return encode(prefix, toWords(bytes));
|
|
728
|
-
}
|
|
729
|
-
return {
|
|
730
|
-
encode,
|
|
731
|
-
decode,
|
|
732
|
-
encodeFromBytes,
|
|
733
|
-
decodeToBytes,
|
|
734
|
-
decodeUnsafe,
|
|
735
|
-
fromWords,
|
|
736
|
-
fromWordsUnsafe,
|
|
737
|
-
toWords
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
741
|
-
|
|
742
|
-
// node_modules/@scure/bip32/index.js
|
|
743
|
-
var Point = secp256k1.Point;
|
|
744
|
-
var { Fn } = Point;
|
|
745
|
-
var base58check2 = createBase58check(sha256);
|
|
746
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
747
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
748
|
-
var HARDENED_OFFSET = 2147483648;
|
|
749
|
-
var hash160 = (data) => ripemd160$1(sha256(data));
|
|
750
|
-
var fromU32 = (data) => createView(data).getUint32(0, false);
|
|
751
|
-
var toU32 = (n) => {
|
|
752
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
753
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
754
|
-
}
|
|
755
|
-
const buf = new Uint8Array(4);
|
|
756
|
-
createView(buf).setUint32(0, n, false);
|
|
757
|
-
return buf;
|
|
758
|
-
};
|
|
759
|
-
var HDKey = class _HDKey {
|
|
760
|
-
get fingerprint() {
|
|
761
|
-
if (!this.pubHash) {
|
|
762
|
-
throw new Error("No publicKey set!");
|
|
763
|
-
}
|
|
764
|
-
return fromU32(this.pubHash);
|
|
765
|
-
}
|
|
766
|
-
get identifier() {
|
|
767
|
-
return this.pubHash;
|
|
768
|
-
}
|
|
769
|
-
get pubKeyHash() {
|
|
770
|
-
return this.pubHash;
|
|
771
|
-
}
|
|
772
|
-
get privateKey() {
|
|
773
|
-
return this._privateKey || null;
|
|
774
|
-
}
|
|
775
|
-
get publicKey() {
|
|
776
|
-
return this._publicKey || null;
|
|
777
|
-
}
|
|
778
|
-
get privateExtendedKey() {
|
|
779
|
-
const priv = this._privateKey;
|
|
780
|
-
if (!priv) {
|
|
781
|
-
throw new Error("No private key");
|
|
782
|
-
}
|
|
783
|
-
return base58check2.encode(this.serialize(this.versions.private, concatBytes(Uint8Array.of(0), priv)));
|
|
784
|
-
}
|
|
785
|
-
get publicExtendedKey() {
|
|
786
|
-
if (!this._publicKey) {
|
|
787
|
-
throw new Error("No public key");
|
|
788
|
-
}
|
|
789
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
790
|
-
}
|
|
791
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
792
|
-
abytes(seed);
|
|
793
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
794
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
795
|
-
}
|
|
796
|
-
const I = hmac(sha512, MASTER_SECRET, seed);
|
|
797
|
-
const privateKey = I.slice(0, 32);
|
|
798
|
-
const chainCode = I.slice(32);
|
|
799
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
800
|
-
}
|
|
801
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
802
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
803
|
-
const keyView = createView(keyBuffer);
|
|
804
|
-
const version = keyView.getUint32(0, false);
|
|
805
|
-
const opt = {
|
|
806
|
-
versions,
|
|
807
|
-
depth: keyBuffer[4],
|
|
808
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
809
|
-
index: keyView.getUint32(9, false),
|
|
810
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
811
|
-
};
|
|
812
|
-
const key = keyBuffer.slice(45);
|
|
813
|
-
const isPriv = key[0] === 0;
|
|
814
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
815
|
-
throw new Error("Version mismatch");
|
|
816
|
-
}
|
|
817
|
-
if (isPriv) {
|
|
818
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
819
|
-
} else {
|
|
820
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
static fromJSON(json) {
|
|
824
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
825
|
-
}
|
|
826
|
-
versions;
|
|
827
|
-
depth = 0;
|
|
828
|
-
index = 0;
|
|
829
|
-
chainCode = null;
|
|
830
|
-
parentFingerprint = 0;
|
|
831
|
-
_privateKey;
|
|
832
|
-
_publicKey;
|
|
833
|
-
pubHash;
|
|
834
|
-
constructor(opt) {
|
|
835
|
-
if (!opt || typeof opt !== "object") {
|
|
836
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
837
|
-
}
|
|
838
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
839
|
-
this.depth = opt.depth || 0;
|
|
840
|
-
this.chainCode = opt.chainCode || null;
|
|
841
|
-
this.index = opt.index || 0;
|
|
842
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
843
|
-
if (!this.depth) {
|
|
844
|
-
if (this.parentFingerprint || this.index) {
|
|
845
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (this.depth > 255) {
|
|
849
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
850
|
-
}
|
|
851
|
-
if (opt.publicKey && opt.privateKey) {
|
|
852
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
853
|
-
}
|
|
854
|
-
if (opt.privateKey) {
|
|
855
|
-
if (!secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
856
|
-
throw new Error("Invalid private key");
|
|
857
|
-
this._privateKey = opt.privateKey;
|
|
858
|
-
this._publicKey = secp256k1.getPublicKey(opt.privateKey, true);
|
|
859
|
-
} else if (opt.publicKey) {
|
|
860
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
861
|
-
} else {
|
|
862
|
-
throw new Error("HDKey: no public or private key provided");
|
|
863
|
-
}
|
|
864
|
-
this.pubHash = hash160(this._publicKey);
|
|
865
|
-
}
|
|
866
|
-
derive(path) {
|
|
867
|
-
if (!/^[mM]'?/.test(path)) {
|
|
868
|
-
throw new Error('Path must start with "m" or "M"');
|
|
869
|
-
}
|
|
870
|
-
if (/^[mM]'?$/.test(path)) {
|
|
871
|
-
return this;
|
|
872
|
-
}
|
|
873
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
874
|
-
let child = this;
|
|
875
|
-
for (const c of parts) {
|
|
876
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
877
|
-
const m1 = m && m[1];
|
|
878
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
879
|
-
throw new Error("invalid child index: " + c);
|
|
880
|
-
let idx = +m1;
|
|
881
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
882
|
-
throw new Error("Invalid index");
|
|
883
|
-
}
|
|
884
|
-
if (m[2] === "'") {
|
|
885
|
-
idx += HARDENED_OFFSET;
|
|
886
|
-
}
|
|
887
|
-
child = child.deriveChild(idx);
|
|
888
|
-
}
|
|
889
|
-
return child;
|
|
890
|
-
}
|
|
891
|
-
deriveChild(index) {
|
|
892
|
-
if (!this._publicKey || !this.chainCode) {
|
|
893
|
-
throw new Error("No publicKey or chainCode set");
|
|
894
|
-
}
|
|
895
|
-
let data = toU32(index);
|
|
896
|
-
if (index >= HARDENED_OFFSET) {
|
|
897
|
-
const priv = this._privateKey;
|
|
898
|
-
if (!priv) {
|
|
899
|
-
throw new Error("Could not derive hardened child key");
|
|
900
|
-
}
|
|
901
|
-
data = concatBytes(Uint8Array.of(0), priv, data);
|
|
902
|
-
} else {
|
|
903
|
-
data = concatBytes(this._publicKey, data);
|
|
904
|
-
}
|
|
905
|
-
const I = hmac(sha512, this.chainCode, data);
|
|
906
|
-
const childTweak = I.slice(0, 32);
|
|
907
|
-
const chainCode = I.slice(32);
|
|
908
|
-
if (!secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
909
|
-
throw new Error("Tweak bigger than curve order");
|
|
910
|
-
}
|
|
911
|
-
const opt = {
|
|
912
|
-
versions: this.versions,
|
|
913
|
-
chainCode,
|
|
914
|
-
depth: this.depth + 1,
|
|
915
|
-
parentFingerprint: this.fingerprint,
|
|
916
|
-
index
|
|
917
|
-
};
|
|
918
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
919
|
-
try {
|
|
920
|
-
if (this._privateKey) {
|
|
921
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
922
|
-
if (!Fn.isValidNot0(added)) {
|
|
923
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
924
|
-
}
|
|
925
|
-
opt.privateKey = Fn.toBytes(added);
|
|
926
|
-
} else {
|
|
927
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
928
|
-
if (added.equals(Point.ZERO)) {
|
|
929
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
930
|
-
}
|
|
931
|
-
opt.publicKey = added.toBytes(true);
|
|
932
|
-
}
|
|
933
|
-
return new _HDKey(opt);
|
|
934
|
-
} catch (err) {
|
|
935
|
-
return this.deriveChild(index + 1);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
sign(hash) {
|
|
939
|
-
if (!this._privateKey) {
|
|
940
|
-
throw new Error("No privateKey set!");
|
|
941
|
-
}
|
|
942
|
-
abytes(hash, 32);
|
|
943
|
-
return secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
944
|
-
}
|
|
945
|
-
verify(hash, signature) {
|
|
946
|
-
abytes(hash, 32);
|
|
947
|
-
abytes(signature, 64);
|
|
948
|
-
if (!this._publicKey) {
|
|
949
|
-
throw new Error("No publicKey set!");
|
|
950
|
-
}
|
|
951
|
-
return secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
952
|
-
}
|
|
953
|
-
wipePrivateData() {
|
|
954
|
-
if (this._privateKey) {
|
|
955
|
-
this._privateKey.fill(0);
|
|
956
|
-
this._privateKey = void 0;
|
|
957
|
-
}
|
|
958
|
-
return this;
|
|
959
|
-
}
|
|
960
|
-
toJSON() {
|
|
961
|
-
return {
|
|
962
|
-
xpriv: this.privateExtendedKey,
|
|
963
|
-
xpub: this.publicExtendedKey
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
serialize(version, key) {
|
|
967
|
-
if (!this.chainCode) {
|
|
968
|
-
throw new Error("No chainCode set");
|
|
969
|
-
}
|
|
970
|
-
abytes(key, 33);
|
|
971
|
-
return concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
972
|
-
}
|
|
973
|
-
};
|
|
974
388
|
var DERIVATION_PATHS2 = {
|
|
975
389
|
ethereum: "m/44'/60'/0'/0/0",
|
|
976
390
|
bitcoin_mainnet: "m/84'/0'/0'/0/0",
|
|
@@ -993,7 +407,7 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
993
407
|
if (!child.publicKey) {
|
|
994
408
|
throw new Error("Failed to derive public key");
|
|
995
409
|
}
|
|
996
|
-
const pubKeyHash = ripemd160(sha256
|
|
410
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
997
411
|
const witnessVersion = 0;
|
|
998
412
|
const words = bech32.toWords(pubKeyHash);
|
|
999
413
|
words.unshift(witnessVersion);
|
|
@@ -1034,7 +448,7 @@ async function deriveTonAddress(seed) {
|
|
|
1034
448
|
const publicKey = keypair.publicKey;
|
|
1035
449
|
const workchain = 0;
|
|
1036
450
|
const flags = 17;
|
|
1037
|
-
const hash = sha256
|
|
451
|
+
const hash = sha256(publicKey);
|
|
1038
452
|
const addressData = new Uint8Array(34);
|
|
1039
453
|
addressData[0] = flags;
|
|
1040
454
|
addressData[1] = workchain;
|
|
@@ -1071,7 +485,7 @@ function deriveTronAddress(seed) {
|
|
|
1071
485
|
for (let i = 0; i < 20; i++) {
|
|
1072
486
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1073
487
|
}
|
|
1074
|
-
const tronBase58check = base58check(sha256
|
|
488
|
+
const tronBase58check = base58check(sha256);
|
|
1075
489
|
return tronBase58check.encode(addressBytes);
|
|
1076
490
|
} catch (error) {
|
|
1077
491
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1086,7 +500,7 @@ function deriveSparkAddress(seed, network = "mainnet") {
|
|
|
1086
500
|
if (!child.publicKey) {
|
|
1087
501
|
throw new Error("Failed to derive public key");
|
|
1088
502
|
}
|
|
1089
|
-
const pubKeyHash = ripemd160(sha256
|
|
503
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
1090
504
|
const witnessVersion = 0;
|
|
1091
505
|
const words = bech32.toWords(pubKeyHash);
|
|
1092
506
|
words.unshift(witnessVersion);
|
|
@@ -1187,9 +601,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1187
601
|
"no route": "NETWORK_ERROR"
|
|
1188
602
|
}
|
|
1189
603
|
};
|
|
1190
|
-
function parseChainError(
|
|
604
|
+
function parseChainError(chain, errorMessage) {
|
|
1191
605
|
const errorLower = errorMessage.toLowerCase();
|
|
1192
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
606
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1193
607
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1194
608
|
if (errorLower.includes(pattern)) {
|
|
1195
609
|
return code;
|
|
@@ -1327,38 +741,38 @@ var ZubariWdkService = class {
|
|
|
1327
741
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1328
742
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1329
743
|
*/
|
|
1330
|
-
async deriveAddress(seed,
|
|
744
|
+
async deriveAddress(seed, chain) {
|
|
1331
745
|
await this.initialize();
|
|
1332
|
-
const path = this.getDerivationPath(
|
|
746
|
+
const path = this.getDerivationPath(chain);
|
|
1333
747
|
try {
|
|
1334
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
748
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1335
749
|
if (response.success && response.address) {
|
|
1336
750
|
return {
|
|
1337
|
-
chain
|
|
751
|
+
chain,
|
|
1338
752
|
address: response.address,
|
|
1339
753
|
path: response.path || path
|
|
1340
754
|
};
|
|
1341
755
|
}
|
|
1342
756
|
} catch (error) {
|
|
1343
|
-
console.warn(`API address derivation failed for ${
|
|
1344
|
-
if (
|
|
1345
|
-
return this.deriveBrowserAddress(seed,
|
|
757
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
758
|
+
if (chain === "ethereum") {
|
|
759
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1346
760
|
}
|
|
1347
761
|
}
|
|
1348
762
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1349
763
|
try {
|
|
1350
764
|
const wdk = this.nativeWdkService;
|
|
1351
765
|
await wdk.initialize(seed);
|
|
1352
|
-
return await wdk.deriveAddress(
|
|
766
|
+
return await wdk.deriveAddress(chain);
|
|
1353
767
|
} catch (error) {
|
|
1354
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
768
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1355
769
|
}
|
|
1356
770
|
}
|
|
1357
|
-
if (
|
|
1358
|
-
return this.deriveBrowserAddress(seed,
|
|
771
|
+
if (chain === "ethereum") {
|
|
772
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1359
773
|
}
|
|
1360
774
|
throw new Error(
|
|
1361
|
-
`WDK API required for ${
|
|
775
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1362
776
|
);
|
|
1363
777
|
}
|
|
1364
778
|
/**
|
|
@@ -1438,13 +852,13 @@ var ZubariWdkService = class {
|
|
|
1438
852
|
/**
|
|
1439
853
|
* Get fee rates for a chain
|
|
1440
854
|
*/
|
|
1441
|
-
async getFeeRates(seed,
|
|
855
|
+
async getFeeRates(seed, chain) {
|
|
1442
856
|
await this.initialize();
|
|
1443
857
|
try {
|
|
1444
858
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1445
859
|
method: "POST",
|
|
1446
860
|
headers: { "Content-Type": "application/json" },
|
|
1447
|
-
body: JSON.stringify({ seed, chain
|
|
861
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1448
862
|
});
|
|
1449
863
|
if (response.ok) {
|
|
1450
864
|
const data = await response.json();
|
|
@@ -1453,20 +867,20 @@ var ZubariWdkService = class {
|
|
|
1453
867
|
}
|
|
1454
868
|
}
|
|
1455
869
|
} catch (error) {
|
|
1456
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
870
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1457
871
|
}
|
|
1458
872
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1459
873
|
}
|
|
1460
874
|
/**
|
|
1461
875
|
* Estimate transaction fee
|
|
1462
876
|
*/
|
|
1463
|
-
async estimateFee(seed,
|
|
877
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1464
878
|
await this.initialize();
|
|
1465
879
|
try {
|
|
1466
880
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1467
881
|
method: "POST",
|
|
1468
882
|
headers: { "Content-Type": "application/json" },
|
|
1469
|
-
body: JSON.stringify({ seed, chain
|
|
883
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1470
884
|
});
|
|
1471
885
|
if (response.ok) {
|
|
1472
886
|
const data = await response.json();
|
|
@@ -1475,9 +889,9 @@ var ZubariWdkService = class {
|
|
|
1475
889
|
}
|
|
1476
890
|
}
|
|
1477
891
|
} catch (error) {
|
|
1478
|
-
console.warn(`Failed to estimate fee for ${
|
|
892
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1479
893
|
}
|
|
1480
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
894
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1481
895
|
}
|
|
1482
896
|
/**
|
|
1483
897
|
* Send a transaction on any supported chain
|
|
@@ -1488,10 +902,10 @@ var ZubariWdkService = class {
|
|
|
1488
902
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1489
903
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1490
904
|
*/
|
|
1491
|
-
async sendTransaction(seed,
|
|
905
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1492
906
|
await this.initialize();
|
|
1493
907
|
const startTime = Date.now();
|
|
1494
|
-
console.log(`[ZubariWdkService] Sending ${
|
|
908
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
1495
909
|
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1496
910
|
amount,
|
|
1497
911
|
network: this.config.network
|
|
@@ -1500,7 +914,7 @@ var ZubariWdkService = class {
|
|
|
1500
914
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1501
915
|
method: "POST",
|
|
1502
916
|
headers: { "Content-Type": "application/json" },
|
|
1503
|
-
body: JSON.stringify({ seed, chain
|
|
917
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1504
918
|
});
|
|
1505
919
|
const elapsed = Date.now() - startTime;
|
|
1506
920
|
if (response.ok) {
|
|
@@ -1510,22 +924,22 @@ var ZubariWdkService = class {
|
|
|
1510
924
|
txHash = txHash.hash;
|
|
1511
925
|
}
|
|
1512
926
|
if (txHash) {
|
|
1513
|
-
const isValid = this.validateTxHash(
|
|
927
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1514
928
|
if (!isValid) {
|
|
1515
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
929
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1516
930
|
}
|
|
1517
931
|
}
|
|
1518
|
-
console.log(`[ZubariWdkService] ${
|
|
932
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1519
933
|
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1520
934
|
elapsed: `${elapsed}ms`
|
|
1521
935
|
});
|
|
1522
936
|
if (!data.success) {
|
|
1523
|
-
const errorCode2 = parseChainError(
|
|
937
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1524
938
|
return {
|
|
1525
939
|
success: false,
|
|
1526
940
|
error: data.error,
|
|
1527
941
|
errorCode: errorCode2,
|
|
1528
|
-
chain
|
|
942
|
+
chain
|
|
1529
943
|
};
|
|
1530
944
|
}
|
|
1531
945
|
return {
|
|
@@ -1534,14 +948,14 @@ var ZubariWdkService = class {
|
|
|
1534
948
|
from: data.from,
|
|
1535
949
|
to: data.to,
|
|
1536
950
|
amount: data.amount,
|
|
1537
|
-
chain: data.chain ||
|
|
951
|
+
chain: data.chain || chain,
|
|
1538
952
|
network: data.network || this.config.network
|
|
1539
953
|
};
|
|
1540
954
|
}
|
|
1541
955
|
const errorData = await response.json().catch(() => ({}));
|
|
1542
956
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1543
|
-
const errorCode = parseChainError(
|
|
1544
|
-
console.error(`[ZubariWdkService] ${
|
|
957
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
958
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
1545
959
|
status: response.status,
|
|
1546
960
|
error: errorMessage,
|
|
1547
961
|
errorCode,
|
|
@@ -1551,13 +965,13 @@ var ZubariWdkService = class {
|
|
|
1551
965
|
success: false,
|
|
1552
966
|
error: errorMessage,
|
|
1553
967
|
errorCode,
|
|
1554
|
-
chain
|
|
968
|
+
chain
|
|
1555
969
|
};
|
|
1556
970
|
} catch (error) {
|
|
1557
971
|
const elapsed = Date.now() - startTime;
|
|
1558
972
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1559
|
-
const errorCode = parseChainError(
|
|
1560
|
-
console.error(`[ZubariWdkService] ${
|
|
973
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
974
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
1561
975
|
error: errorMessage,
|
|
1562
976
|
errorCode,
|
|
1563
977
|
elapsed: `${elapsed}ms`
|
|
@@ -1566,15 +980,15 @@ var ZubariWdkService = class {
|
|
|
1566
980
|
success: false,
|
|
1567
981
|
error: errorMessage,
|
|
1568
982
|
errorCode,
|
|
1569
|
-
chain
|
|
983
|
+
chain
|
|
1570
984
|
};
|
|
1571
985
|
}
|
|
1572
986
|
}
|
|
1573
987
|
/**
|
|
1574
988
|
* Validate transaction hash format for a specific chain
|
|
1575
989
|
*/
|
|
1576
|
-
validateTxHash(
|
|
1577
|
-
switch (
|
|
990
|
+
validateTxHash(chain, txHash) {
|
|
991
|
+
switch (chain) {
|
|
1578
992
|
case "ethereum":
|
|
1579
993
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1580
994
|
case "bitcoin":
|
|
@@ -1606,7 +1020,7 @@ var ZubariWdkService = class {
|
|
|
1606
1020
|
// ==========================================
|
|
1607
1021
|
// Private Helper Methods
|
|
1608
1022
|
// ==========================================
|
|
1609
|
-
getDerivationPath(
|
|
1023
|
+
getDerivationPath(chain) {
|
|
1610
1024
|
const paths = {
|
|
1611
1025
|
bitcoin: this.config.network === "testnet" ? "m/84'/1'/0'/0/0" : "m/84'/0'/0'/0/0",
|
|
1612
1026
|
ethereum: "m/44'/60'/0'/0/0",
|
|
@@ -1615,9 +1029,9 @@ var ZubariWdkService = class {
|
|
|
1615
1029
|
solana: "m/44'/501'/0'/0'",
|
|
1616
1030
|
spark: "m/44'/998'/0'/0/0"
|
|
1617
1031
|
};
|
|
1618
|
-
return paths[
|
|
1032
|
+
return paths[chain];
|
|
1619
1033
|
}
|
|
1620
|
-
getChainSymbol(
|
|
1034
|
+
getChainSymbol(chain) {
|
|
1621
1035
|
const symbols = {
|
|
1622
1036
|
ethereum: "ETH",
|
|
1623
1037
|
bitcoin: "BTC",
|
|
@@ -1626,16 +1040,16 @@ var ZubariWdkService = class {
|
|
|
1626
1040
|
solana: "SOL",
|
|
1627
1041
|
spark: "SAT"
|
|
1628
1042
|
};
|
|
1629
|
-
return symbols[
|
|
1043
|
+
return symbols[chain];
|
|
1630
1044
|
}
|
|
1631
1045
|
/**
|
|
1632
1046
|
* Derive address using browser-compatible libraries
|
|
1633
1047
|
*/
|
|
1634
|
-
async deriveBrowserAddress(seed,
|
|
1635
|
-
const path = this.getDerivationPath(
|
|
1048
|
+
async deriveBrowserAddress(seed, chain) {
|
|
1049
|
+
const path = this.getDerivationPath(chain);
|
|
1636
1050
|
try {
|
|
1637
1051
|
let address;
|
|
1638
|
-
switch (
|
|
1052
|
+
switch (chain) {
|
|
1639
1053
|
case "ethereum":
|
|
1640
1054
|
address = deriveEthereumAddress(seed);
|
|
1641
1055
|
break;
|
|
@@ -1655,11 +1069,11 @@ var ZubariWdkService = class {
|
|
|
1655
1069
|
address = await deriveTonAddress(seed);
|
|
1656
1070
|
break;
|
|
1657
1071
|
default:
|
|
1658
|
-
throw new Error(`Unsupported chain: ${
|
|
1072
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1659
1073
|
}
|
|
1660
|
-
return { chain
|
|
1074
|
+
return { chain, address, path };
|
|
1661
1075
|
} catch (error) {
|
|
1662
|
-
console.error(`Browser derivation failed for ${
|
|
1076
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1663
1077
|
throw error;
|
|
1664
1078
|
}
|
|
1665
1079
|
}
|
|
@@ -1672,7 +1086,7 @@ var ZubariWdkService = class {
|
|
|
1672
1086
|
};
|
|
1673
1087
|
var defaultService = null;
|
|
1674
1088
|
function getZubariWdkService(config) {
|
|
1675
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1089
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1676
1090
|
defaultService = new ZubariWdkService(config);
|
|
1677
1091
|
}
|
|
1678
1092
|
return defaultService;
|
|
@@ -1725,12 +1139,12 @@ var ZubariWallet = class {
|
|
|
1725
1139
|
solana: "solana",
|
|
1726
1140
|
spark: "spark"
|
|
1727
1141
|
};
|
|
1728
|
-
const
|
|
1729
|
-
if (!
|
|
1142
|
+
const chain = chainMap[network];
|
|
1143
|
+
if (!chain) {
|
|
1730
1144
|
throw new Error(`Unsupported network: ${network}`);
|
|
1731
1145
|
}
|
|
1732
1146
|
try {
|
|
1733
|
-
const result = await this.wdkService.deriveAddress(this.seed,
|
|
1147
|
+
const result = await this.wdkService.deriveAddress(this.seed, chain);
|
|
1734
1148
|
const account = {
|
|
1735
1149
|
network,
|
|
1736
1150
|
address: result.address,
|
|
@@ -1785,13 +1199,13 @@ var ZubariWallet = class {
|
|
|
1785
1199
|
solana: "solana",
|
|
1786
1200
|
spark: "spark"
|
|
1787
1201
|
};
|
|
1788
|
-
const
|
|
1789
|
-
if (!
|
|
1202
|
+
const chain = chainMap[network];
|
|
1203
|
+
if (!chain) {
|
|
1790
1204
|
throw new Error(`Unsupported network: ${network}`);
|
|
1791
1205
|
}
|
|
1792
1206
|
try {
|
|
1793
1207
|
const balances = await this.wdkService.getAllBalances(this.seed);
|
|
1794
|
-
const chainBalance = balances[
|
|
1208
|
+
const chainBalance = balances[chain];
|
|
1795
1209
|
if (chainBalance) {
|
|
1796
1210
|
const balanceValue = BigInt(chainBalance.balance || "0");
|
|
1797
1211
|
const decimals = networkConfig.nativeCurrency.decimals;
|
|
@@ -1880,14 +1294,14 @@ var ZubariWallet = class {
|
|
|
1880
1294
|
solana: "solana",
|
|
1881
1295
|
spark: "spark"
|
|
1882
1296
|
};
|
|
1883
|
-
const
|
|
1884
|
-
if (!
|
|
1297
|
+
const chain = chainMap[network];
|
|
1298
|
+
if (!chain) {
|
|
1885
1299
|
throw new Error(`Unsupported network: ${network}`);
|
|
1886
1300
|
}
|
|
1887
1301
|
try {
|
|
1888
1302
|
const result = await this.wdkService.sendTransaction(
|
|
1889
1303
|
this.seed,
|
|
1890
|
-
|
|
1304
|
+
chain,
|
|
1891
1305
|
to,
|
|
1892
1306
|
amount.toString()
|
|
1893
1307
|
);
|
|
@@ -2562,8 +1976,8 @@ async function fetchPrices() {
|
|
|
2562
1976
|
if (response.ok) {
|
|
2563
1977
|
const data = await response.json();
|
|
2564
1978
|
const prices = {};
|
|
2565
|
-
for (const [
|
|
2566
|
-
prices[
|
|
1979
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1980
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2567
1981
|
}
|
|
2568
1982
|
priceCache = { prices, timestamp: Date.now() };
|
|
2569
1983
|
return prices;
|
|
@@ -2573,9 +1987,22 @@ async function fetchPrices() {
|
|
|
2573
1987
|
}
|
|
2574
1988
|
return priceCache?.prices || {};
|
|
2575
1989
|
}
|
|
2576
|
-
async function getPriceForChain(
|
|
1990
|
+
async function getPriceForChain(chain) {
|
|
2577
1991
|
const prices = await fetchPrices();
|
|
2578
|
-
return prices[
|
|
1992
|
+
return prices[chain] || 0;
|
|
1993
|
+
}
|
|
1994
|
+
function tonFriendlyToRaw(addr) {
|
|
1995
|
+
if (addr.includes(":")) return addr;
|
|
1996
|
+
try {
|
|
1997
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1998
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1999
|
+
if (bytes.length !== 36) return addr;
|
|
2000
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
2001
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2002
|
+
return `${workchain}:${hash}`;
|
|
2003
|
+
} catch {
|
|
2004
|
+
return addr;
|
|
2005
|
+
}
|
|
2579
2006
|
}
|
|
2580
2007
|
var STORAGE_KEYS = {
|
|
2581
2008
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2781,9 +2208,9 @@ var WalletManager = class _WalletManager {
|
|
|
2781
2208
|
if (!this.derivedAddress) {
|
|
2782
2209
|
throw new Error("Wallet not initialized");
|
|
2783
2210
|
}
|
|
2784
|
-
const
|
|
2211
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2785
2212
|
const client = createPublicClient({
|
|
2786
|
-
chain
|
|
2213
|
+
chain,
|
|
2787
2214
|
transport: http(this.config.rpcUrl, {
|
|
2788
2215
|
timeout: 15e3,
|
|
2789
2216
|
// 15 second timeout
|
|
@@ -2805,9 +2232,9 @@ var WalletManager = class _WalletManager {
|
|
|
2805
2232
|
* Create viem public client for the current network
|
|
2806
2233
|
*/
|
|
2807
2234
|
getPublicClient() {
|
|
2808
|
-
const
|
|
2235
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2809
2236
|
return createPublicClient({
|
|
2810
|
-
chain
|
|
2237
|
+
chain,
|
|
2811
2238
|
transport: http(this.config.rpcUrl, {
|
|
2812
2239
|
timeout: 15e3,
|
|
2813
2240
|
// 15 second timeout
|
|
@@ -2861,11 +2288,11 @@ var WalletManager = class _WalletManager {
|
|
|
2861
2288
|
*
|
|
2862
2289
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2863
2290
|
*/
|
|
2864
|
-
static async deriveAddressForChainAsync(seed,
|
|
2865
|
-
if (
|
|
2291
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
2292
|
+
if (chain === "ethereum") {
|
|
2866
2293
|
try {
|
|
2867
2294
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2868
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
2295
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2869
2296
|
return result2.address;
|
|
2870
2297
|
} catch (error) {
|
|
2871
2298
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2873,7 +2300,7 @@ var WalletManager = class _WalletManager {
|
|
|
2873
2300
|
}
|
|
2874
2301
|
}
|
|
2875
2302
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2876
|
-
const result = await wdkService.deriveAddress(seed,
|
|
2303
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2877
2304
|
return result.address;
|
|
2878
2305
|
}
|
|
2879
2306
|
/**
|
|
@@ -2882,14 +2309,14 @@ var WalletManager = class _WalletManager {
|
|
|
2882
2309
|
*
|
|
2883
2310
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2884
2311
|
*/
|
|
2885
|
-
static deriveAddressForChain(seed,
|
|
2886
|
-
if (
|
|
2312
|
+
static deriveAddressForChain(seed, chain) {
|
|
2313
|
+
if (chain === "ethereum") {
|
|
2887
2314
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2888
2315
|
const ethNode = HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2889
2316
|
return ethNode.address;
|
|
2890
2317
|
}
|
|
2891
2318
|
throw new Error(
|
|
2892
|
-
`Sync derivation not supported for ${
|
|
2319
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2893
2320
|
);
|
|
2894
2321
|
}
|
|
2895
2322
|
/**
|
|
@@ -2921,9 +2348,9 @@ var WalletManager = class _WalletManager {
|
|
|
2921
2348
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2922
2349
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2923
2350
|
const addresses = {};
|
|
2924
|
-
for (const [
|
|
2925
|
-
if (enabledChainsSet.has(
|
|
2926
|
-
addresses[
|
|
2351
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
2352
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
2353
|
+
addresses[chain] = address;
|
|
2927
2354
|
}
|
|
2928
2355
|
}
|
|
2929
2356
|
this.derivedAddresses = addresses;
|
|
@@ -2964,10 +2391,10 @@ var WalletManager = class _WalletManager {
|
|
|
2964
2391
|
*/
|
|
2965
2392
|
normalizeAddresses(addresses) {
|
|
2966
2393
|
const normalized = {};
|
|
2967
|
-
for (const [
|
|
2394
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2968
2395
|
const addr = this.normalizeAddress(value);
|
|
2969
2396
|
if (addr) {
|
|
2970
|
-
normalized[
|
|
2397
|
+
normalized[chain] = addr;
|
|
2971
2398
|
}
|
|
2972
2399
|
}
|
|
2973
2400
|
return normalized;
|
|
@@ -3020,20 +2447,20 @@ var WalletManager = class _WalletManager {
|
|
|
3020
2447
|
* Get address for a specific chain
|
|
3021
2448
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
3022
2449
|
*/
|
|
3023
|
-
getAddressForChain(
|
|
3024
|
-
const cachedValue = this.derivedAddresses[
|
|
2450
|
+
getAddressForChain(chain) {
|
|
2451
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
3025
2452
|
if (cachedValue) {
|
|
3026
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
2453
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
3027
2454
|
const addr = this.normalizeAddress(cachedValue);
|
|
3028
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
2455
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) normalized:`, addr);
|
|
3029
2456
|
if (addr) {
|
|
3030
|
-
this.derivedAddresses[
|
|
2457
|
+
this.derivedAddresses[chain] = addr;
|
|
3031
2458
|
return addr;
|
|
3032
2459
|
}
|
|
3033
2460
|
}
|
|
3034
|
-
if (
|
|
3035
|
-
this.derivedAddresses[
|
|
3036
|
-
return this.derivedAddresses[
|
|
2461
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
2462
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
2463
|
+
return this.derivedAddresses[chain];
|
|
3037
2464
|
}
|
|
3038
2465
|
return null;
|
|
3039
2466
|
}
|
|
@@ -3046,11 +2473,11 @@ var WalletManager = class _WalletManager {
|
|
|
3046
2473
|
/**
|
|
3047
2474
|
* Set the selected chain
|
|
3048
2475
|
*/
|
|
3049
|
-
setSelectedChain(
|
|
3050
|
-
if (!this.config.enabledChains.includes(
|
|
3051
|
-
throw new Error(`Chain ${
|
|
2476
|
+
setSelectedChain(chain) {
|
|
2477
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
2478
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
3052
2479
|
}
|
|
3053
|
-
this.selectedChain =
|
|
2480
|
+
this.selectedChain = chain;
|
|
3054
2481
|
}
|
|
3055
2482
|
/**
|
|
3056
2483
|
* Get the currently selected chain
|
|
@@ -3067,22 +2494,22 @@ var WalletManager = class _WalletManager {
|
|
|
3067
2494
|
/**
|
|
3068
2495
|
* Get chain configuration
|
|
3069
2496
|
*/
|
|
3070
|
-
getChainConfig(
|
|
3071
|
-
return getNetworkConfig(
|
|
2497
|
+
getChainConfig(chain) {
|
|
2498
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
3072
2499
|
}
|
|
3073
2500
|
/**
|
|
3074
2501
|
* Fetch balance for a specific chain
|
|
3075
2502
|
* Note: Currently only Ethereum is implemented
|
|
3076
2503
|
*/
|
|
3077
|
-
async fetchBalanceForChain(
|
|
3078
|
-
const address = this.getAddressForChain(
|
|
2504
|
+
async fetchBalanceForChain(chain) {
|
|
2505
|
+
const address = this.getAddressForChain(chain);
|
|
3079
2506
|
if (!address) {
|
|
3080
|
-
throw new Error(`No address for chain ${
|
|
2507
|
+
throw new Error(`No address for chain ${chain}`);
|
|
3081
2508
|
}
|
|
3082
|
-
const networkConfig = this.getChainConfig(
|
|
2509
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3083
2510
|
let balance = "0";
|
|
3084
2511
|
const tokenBalances = {};
|
|
3085
|
-
if (
|
|
2512
|
+
if (chain === "ethereum") {
|
|
3086
2513
|
const viemChain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
3087
2514
|
const isTestnet = this.config.network !== "mainnet";
|
|
3088
2515
|
const client = createPublicClient({
|
|
@@ -3129,7 +2556,7 @@ var WalletManager = class _WalletManager {
|
|
|
3129
2556
|
} else if (usdtResult.status === "rejected") {
|
|
3130
2557
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
3131
2558
|
}
|
|
3132
|
-
} else if (
|
|
2559
|
+
} else if (chain === "bitcoin") {
|
|
3133
2560
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
3134
2561
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
3135
2562
|
"https://mempool.space/testnet/api",
|
|
@@ -3161,7 +2588,7 @@ var WalletManager = class _WalletManager {
|
|
|
3161
2588
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
3162
2589
|
}
|
|
3163
2590
|
}
|
|
3164
|
-
} else if (
|
|
2591
|
+
} else if (chain === "solana") {
|
|
3165
2592
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
3166
2593
|
try {
|
|
3167
2594
|
const response = await fetch(rpcUrl, {
|
|
@@ -3181,7 +2608,7 @@ var WalletManager = class _WalletManager {
|
|
|
3181
2608
|
}
|
|
3182
2609
|
}
|
|
3183
2610
|
} catch (error) {
|
|
3184
|
-
console.warn(`Failed to fetch ${
|
|
2611
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3185
2612
|
}
|
|
3186
2613
|
const isTestnet = this.config.network !== "mainnet";
|
|
3187
2614
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -3215,7 +2642,7 @@ var WalletManager = class _WalletManager {
|
|
|
3215
2642
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
3216
2643
|
}
|
|
3217
2644
|
}
|
|
3218
|
-
} else if (
|
|
2645
|
+
} else if (chain === "tron") {
|
|
3219
2646
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
3220
2647
|
const baseUrl = tronConfig.rpcUrl;
|
|
3221
2648
|
try {
|
|
@@ -3244,9 +2671,9 @@ var WalletManager = class _WalletManager {
|
|
|
3244
2671
|
}
|
|
3245
2672
|
}
|
|
3246
2673
|
} catch (error) {
|
|
3247
|
-
console.warn(`Failed to fetch ${
|
|
2674
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3248
2675
|
}
|
|
3249
|
-
} else if (
|
|
2676
|
+
} else if (chain === "ton") {
|
|
3250
2677
|
const isTestnet = this.config.network !== "mainnet";
|
|
3251
2678
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
3252
2679
|
try {
|
|
@@ -3262,25 +2689,36 @@ var WalletManager = class _WalletManager {
|
|
|
3262
2689
|
}
|
|
3263
2690
|
}
|
|
3264
2691
|
} catch (error) {
|
|
3265
|
-
console.warn(`Failed to fetch ${
|
|
2692
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3266
2693
|
}
|
|
3267
2694
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
3268
2695
|
if (usdtJetton) {
|
|
3269
|
-
const
|
|
2696
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
3270
2697
|
try {
|
|
2698
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
3271
2699
|
const jettonResponse = await fetch(
|
|
3272
|
-
`${
|
|
2700
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
3273
2701
|
{ headers: { "Accept": "application/json" } }
|
|
3274
2702
|
);
|
|
3275
2703
|
if (jettonResponse.ok) {
|
|
3276
2704
|
const jettonData = await jettonResponse.json();
|
|
3277
|
-
const
|
|
3278
|
-
if (
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
2705
|
+
const balances = jettonData.balances;
|
|
2706
|
+
if (balances && balances.length > 0) {
|
|
2707
|
+
for (const jb of balances) {
|
|
2708
|
+
const jettonAddr = jb.jetton?.address;
|
|
2709
|
+
if (jettonAddr) {
|
|
2710
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2711
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2712
|
+
const rawBalance = jb.balance;
|
|
2713
|
+
if (rawBalance) {
|
|
2714
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2715
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2716
|
+
if (usdtAmount > 0) {
|
|
2717
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
break;
|
|
2721
|
+
}
|
|
3284
2722
|
}
|
|
3285
2723
|
}
|
|
3286
2724
|
}
|
|
@@ -3289,7 +2727,7 @@ var WalletManager = class _WalletManager {
|
|
|
3289
2727
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
3290
2728
|
}
|
|
3291
2729
|
}
|
|
3292
|
-
} else if (
|
|
2730
|
+
} else if (chain === "spark") {
|
|
3293
2731
|
try {
|
|
3294
2732
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
3295
2733
|
method: "POST",
|
|
@@ -3308,14 +2746,14 @@ var WalletManager = class _WalletManager {
|
|
|
3308
2746
|
}
|
|
3309
2747
|
}
|
|
3310
2748
|
} catch (error) {
|
|
3311
|
-
console.warn(`Failed to fetch ${
|
|
2749
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3312
2750
|
}
|
|
3313
2751
|
}
|
|
3314
|
-
const priceUsd = await getPriceForChain(
|
|
2752
|
+
const priceUsd = await getPriceForChain(chain);
|
|
3315
2753
|
const balanceNum = parseFloat(balance) || 0;
|
|
3316
2754
|
const balanceUsd = balanceNum * priceUsd;
|
|
3317
2755
|
return {
|
|
3318
|
-
chain
|
|
2756
|
+
chain,
|
|
3319
2757
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3320
2758
|
balance,
|
|
3321
2759
|
balanceUsd,
|
|
@@ -3329,19 +2767,19 @@ var WalletManager = class _WalletManager {
|
|
|
3329
2767
|
*/
|
|
3330
2768
|
async fetchAllBalances() {
|
|
3331
2769
|
const balances = [];
|
|
3332
|
-
for (const
|
|
2770
|
+
for (const chain of this.config.enabledChains) {
|
|
3333
2771
|
try {
|
|
3334
|
-
const balance = await this.fetchBalanceForChain(
|
|
2772
|
+
const balance = await this.fetchBalanceForChain(chain);
|
|
3335
2773
|
balances.push(balance);
|
|
3336
2774
|
} catch (error) {
|
|
3337
|
-
console.error(`Failed to fetch balance for ${
|
|
3338
|
-
const networkConfig = this.getChainConfig(
|
|
2775
|
+
console.error(`Failed to fetch balance for ${chain}:`, error);
|
|
2776
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3339
2777
|
balances.push({
|
|
3340
|
-
chain
|
|
2778
|
+
chain,
|
|
3341
2779
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3342
2780
|
balance: "0",
|
|
3343
2781
|
balanceUsd: 0,
|
|
3344
|
-
address: this.getAddressForChain(
|
|
2782
|
+
address: this.getAddressForChain(chain) || "",
|
|
3345
2783
|
decimals: networkConfig.nativeCurrency.decimals
|
|
3346
2784
|
});
|
|
3347
2785
|
}
|
|
@@ -3371,13 +2809,13 @@ var WalletManager = class _WalletManager {
|
|
|
3371
2809
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
3372
2810
|
* @returns Transaction result with hash and status
|
|
3373
2811
|
*/
|
|
3374
|
-
async sendTransaction(
|
|
2812
|
+
async sendTransaction(chain, to, amount, token) {
|
|
3375
2813
|
if (!this.currentSeed) {
|
|
3376
2814
|
return { success: false, error: "Wallet is locked" };
|
|
3377
2815
|
}
|
|
3378
|
-
const fromAddress = this.getAddressForChain(
|
|
2816
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
3379
2817
|
if (!fromAddress) {
|
|
3380
|
-
return { success: false, error: `No address for chain ${
|
|
2818
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
3381
2819
|
}
|
|
3382
2820
|
try {
|
|
3383
2821
|
const headers = {
|
|
@@ -3391,7 +2829,7 @@ var WalletManager = class _WalletManager {
|
|
|
3391
2829
|
headers,
|
|
3392
2830
|
body: JSON.stringify({
|
|
3393
2831
|
seed: this.currentSeed,
|
|
3394
|
-
chain
|
|
2832
|
+
chain,
|
|
3395
2833
|
to,
|
|
3396
2834
|
amount,
|
|
3397
2835
|
token,
|
|
@@ -3400,12 +2838,12 @@ var WalletManager = class _WalletManager {
|
|
|
3400
2838
|
});
|
|
3401
2839
|
if (response.ok) {
|
|
3402
2840
|
const data = await response.json();
|
|
3403
|
-
console.log(`Transaction sent on ${
|
|
2841
|
+
console.log(`Transaction sent on ${chain}:`, data);
|
|
3404
2842
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
3405
2843
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
3406
2844
|
txHash = txHash.hash;
|
|
3407
2845
|
}
|
|
3408
|
-
if (
|
|
2846
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
3409
2847
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
3410
2848
|
}
|
|
3411
2849
|
return {
|
|
@@ -3414,7 +2852,7 @@ var WalletManager = class _WalletManager {
|
|
|
3414
2852
|
from: fromAddress,
|
|
3415
2853
|
to,
|
|
3416
2854
|
amount,
|
|
3417
|
-
chain
|
|
2855
|
+
chain
|
|
3418
2856
|
};
|
|
3419
2857
|
}
|
|
3420
2858
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -3423,7 +2861,7 @@ var WalletManager = class _WalletManager {
|
|
|
3423
2861
|
error: errorData.error || `HTTP ${response.status}`
|
|
3424
2862
|
};
|
|
3425
2863
|
} catch (error) {
|
|
3426
|
-
console.error(`Transaction failed on ${
|
|
2864
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
3427
2865
|
return {
|
|
3428
2866
|
success: false,
|
|
3429
2867
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -3433,7 +2871,7 @@ var WalletManager = class _WalletManager {
|
|
|
3433
2871
|
/**
|
|
3434
2872
|
* Estimate transaction fee using Tether WDK
|
|
3435
2873
|
*/
|
|
3436
|
-
async estimateFee(
|
|
2874
|
+
async estimateFee(chain, to, amount, token) {
|
|
3437
2875
|
try {
|
|
3438
2876
|
const headers = {
|
|
3439
2877
|
"Content-Type": "application/json"
|
|
@@ -3445,7 +2883,7 @@ var WalletManager = class _WalletManager {
|
|
|
3445
2883
|
method: "POST",
|
|
3446
2884
|
headers,
|
|
3447
2885
|
body: JSON.stringify({
|
|
3448
|
-
chain
|
|
2886
|
+
chain,
|
|
3449
2887
|
to,
|
|
3450
2888
|
amount,
|
|
3451
2889
|
token,
|
|
@@ -3469,14 +2907,6 @@ var WalletManager = class _WalletManager {
|
|
|
3469
2907
|
}
|
|
3470
2908
|
}
|
|
3471
2909
|
};
|
|
3472
|
-
/*! Bundled license information:
|
|
3473
|
-
|
|
3474
|
-
@scure/base/index.js:
|
|
3475
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3476
|
-
|
|
3477
|
-
@scure/bip32/index.js:
|
|
3478
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
3479
|
-
*/
|
|
3480
2910
|
|
|
3481
2911
|
export { SUPPORTED_CHAINS, WalletManager, ZubariWallet };
|
|
3482
2912
|
//# sourceMappingURL=index.mjs.map
|