@zubari/sdk 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PayoutsProtocol-B5z8SEA-.d.ts → PayoutsProtocol-DAa-9A5C.d.ts} +8 -1
- package/dist/{PayoutsProtocol-CLiMFe54.d.mts → PayoutsProtocol-DKEQhwYH.d.mts} +8 -1
- package/dist/{TransactionService-BtWUjKt_.d.ts → TransactionService-BEkgF1T6.d.ts} +12 -2
- package/dist/{TransactionService-Lr_WS6iR.d.mts → TransactionService-CF_C3Kqm.d.mts} +12 -2
- package/dist/{WalletManager-DQQwVkoa.d.ts → WalletManager-CeLlZo2y.d.ts} +23 -2
- package/dist/{WalletManager-Sbpx4E1-.d.mts → WalletManager-DIx8nENh.d.mts} +23 -2
- package/dist/{contracts-B842YprC.d.mts → contracts-JfZDzaV7.d.ts} +11 -2
- package/dist/{contracts-s_CDIruh.d.ts → contracts-pugJnFzl.d.mts} +11 -2
- package/dist/{index-CTyZlHKg.d.mts → index-c90msmwW.d.mts} +2 -1
- package/dist/{index-CTyZlHKg.d.ts → index-c90msmwW.d.ts} +2 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +339 -916
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +337 -914
- package/dist/index.mjs.map +1 -1
- package/dist/protocols/index.d.mts +2 -2
- package/dist/protocols/index.d.ts +2 -2
- package/dist/protocols/index.js +24 -11
- package/dist/protocols/index.js.map +1 -1
- package/dist/protocols/index.mjs +24 -11
- package/dist/protocols/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +255 -826
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +253 -824
- package/dist/react/index.mjs.map +1 -1
- package/dist/services/index.d.mts +2 -2
- package/dist/services/index.d.ts +2 -2
- package/dist/services/index.js +179 -767
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +177 -765
- package/dist/services/index.mjs.map +1 -1
- package/dist/storage/index.js +5 -2
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +5 -2
- package/dist/storage/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +3 -3
- package/dist/wallet/index.d.ts +3 -3
- package/dist/wallet/index.js +262 -854
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +260 -852
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
var ethers = require('ethers');
|
|
4
4
|
var bip39 = require('@scure/bip39');
|
|
5
5
|
var english = require('@scure/bip39/wordlists/english');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var legacy_js = require('@noble/hashes/legacy.js');
|
|
9
|
-
var sha2_js = require('@noble/hashes/sha2.js');
|
|
10
|
-
var utils_js = require('@noble/hashes/utils.js');
|
|
6
|
+
var bip32 = require('@scure/bip32');
|
|
7
|
+
var base = require('@scure/base');
|
|
11
8
|
var sha256 = require('@noble/hashes/sha256');
|
|
12
9
|
var ripemd160 = require('@noble/hashes/ripemd160');
|
|
13
10
|
var viem = require('viem');
|
|
@@ -140,8 +137,8 @@ var TESTNET_NETWORKS = {
|
|
|
140
137
|
var USDT_ADDRESSES = {
|
|
141
138
|
ethereum: {
|
|
142
139
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
143
|
-
testnet: "
|
|
144
|
-
// Sepolia
|
|
140
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
141
|
+
// Sepolia (Test Tether USD)
|
|
145
142
|
},
|
|
146
143
|
tron: {
|
|
147
144
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -159,11 +156,11 @@ var USDT_ADDRESSES = {
|
|
|
159
156
|
}
|
|
160
157
|
};
|
|
161
158
|
var DERIVATION_PATHS = {
|
|
162
|
-
bitcoin: "m/
|
|
159
|
+
bitcoin: "m/84'/0'/0'/0",
|
|
163
160
|
ethereum: "m/44'/60'/0'/0",
|
|
164
|
-
ton: "m/44'/607'/0'
|
|
161
|
+
ton: "m/44'/607'/0'",
|
|
165
162
|
tron: "m/44'/195'/0'/0",
|
|
166
|
-
solana: "m/44'/501'/0'
|
|
163
|
+
solana: "m/44'/501'/0'",
|
|
167
164
|
spark: "m/44'/998'/0'/0"
|
|
168
165
|
};
|
|
169
166
|
function getNetworkConfig(network, isTestnet2 = false) {
|
|
@@ -398,8 +395,8 @@ var TESTNET_FEE_WALLETS = {
|
|
|
398
395
|
network: "tron-nile"
|
|
399
396
|
}
|
|
400
397
|
};
|
|
401
|
-
function getFeeWallet(
|
|
402
|
-
return isMainnet2 ? MAINNET_FEE_WALLETS[
|
|
398
|
+
function getFeeWallet(chain, isMainnet2 = true) {
|
|
399
|
+
return isMainnet2 ? MAINNET_FEE_WALLETS[chain] : TESTNET_FEE_WALLETS[chain];
|
|
403
400
|
}
|
|
404
401
|
function getAllFeeWallets(useMainnet = false) {
|
|
405
402
|
return useMainnet ? MAINNET_FEE_WALLETS : TESTNET_FEE_WALLETS;
|
|
@@ -416,8 +413,8 @@ function getDefaultSubscriptionAddress() {
|
|
|
416
413
|
function getCurrentFeeWallets() {
|
|
417
414
|
return isMainnet() ? MAINNET_FEE_WALLETS : TESTNET_FEE_WALLETS;
|
|
418
415
|
}
|
|
419
|
-
function getCurrentFeeWallet(
|
|
420
|
-
return getCurrentFeeWallets()[
|
|
416
|
+
function getCurrentFeeWallet(chain) {
|
|
417
|
+
return getCurrentFeeWallets()[chain];
|
|
421
418
|
}
|
|
422
419
|
function getCurrentCurrencyAddresses() {
|
|
423
420
|
return CURRENCY_ADDRESSES[getZubariNetwork()];
|
|
@@ -429,8 +426,27 @@ var WdkApiClient = class {
|
|
|
429
426
|
constructor(config) {
|
|
430
427
|
this.config = {
|
|
431
428
|
baseUrl: config.baseUrl,
|
|
432
|
-
timeout: config.timeout || 3e4
|
|
429
|
+
timeout: config.timeout || 3e4,
|
|
430
|
+
authToken: config.authToken
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Set or update the auth token for authenticated requests
|
|
435
|
+
*/
|
|
436
|
+
setAuthToken(token) {
|
|
437
|
+
this.config.authToken = token;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Build headers for API requests, including Authorization when available
|
|
441
|
+
*/
|
|
442
|
+
getHeaders() {
|
|
443
|
+
const headers = {
|
|
444
|
+
"Content-Type": "application/json"
|
|
433
445
|
};
|
|
446
|
+
if (this.config.authToken) {
|
|
447
|
+
headers["Authorization"] = `Bearer ${this.config.authToken}`;
|
|
448
|
+
}
|
|
449
|
+
return headers;
|
|
434
450
|
}
|
|
435
451
|
/**
|
|
436
452
|
* Generate a new BIP-39 seed phrase using Tether WDK
|
|
@@ -439,9 +455,7 @@ var WdkApiClient = class {
|
|
|
439
455
|
try {
|
|
440
456
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
|
|
441
457
|
method: "POST",
|
|
442
|
-
headers:
|
|
443
|
-
"Content-Type": "application/json"
|
|
444
|
-
}
|
|
458
|
+
headers: this.getHeaders()
|
|
445
459
|
});
|
|
446
460
|
return await response.json();
|
|
447
461
|
} catch (error) {
|
|
@@ -458,9 +472,7 @@ var WdkApiClient = class {
|
|
|
458
472
|
try {
|
|
459
473
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
|
|
460
474
|
method: "POST",
|
|
461
|
-
headers:
|
|
462
|
-
"Content-Type": "application/json"
|
|
463
|
-
},
|
|
475
|
+
headers: this.getHeaders(),
|
|
464
476
|
body: JSON.stringify({ seed })
|
|
465
477
|
});
|
|
466
478
|
return await response.json();
|
|
@@ -474,14 +486,12 @@ var WdkApiClient = class {
|
|
|
474
486
|
/**
|
|
475
487
|
* Derive address for a specific chain using Tether WDK
|
|
476
488
|
*/
|
|
477
|
-
async deriveAddress(seed,
|
|
489
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
478
490
|
try {
|
|
479
491
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
480
492
|
method: "POST",
|
|
481
|
-
headers:
|
|
482
|
-
|
|
483
|
-
},
|
|
484
|
-
body: JSON.stringify({ seed, chain: chain2, network })
|
|
493
|
+
headers: this.getHeaders(),
|
|
494
|
+
body: JSON.stringify({ seed, chain, network })
|
|
485
495
|
});
|
|
486
496
|
return await response.json();
|
|
487
497
|
} catch (error) {
|
|
@@ -498,9 +508,7 @@ var WdkApiClient = class {
|
|
|
498
508
|
try {
|
|
499
509
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
|
|
500
510
|
method: "POST",
|
|
501
|
-
headers:
|
|
502
|
-
"Content-Type": "application/json"
|
|
503
|
-
},
|
|
511
|
+
headers: this.getHeaders(),
|
|
504
512
|
body: JSON.stringify({ seed, network })
|
|
505
513
|
});
|
|
506
514
|
return await response.json();
|
|
@@ -514,14 +522,12 @@ var WdkApiClient = class {
|
|
|
514
522
|
/**
|
|
515
523
|
* Send a transaction on a specific chain using Tether WDK
|
|
516
524
|
*/
|
|
517
|
-
async sendTransaction(seed,
|
|
525
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
518
526
|
try {
|
|
519
527
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
520
528
|
method: "POST",
|
|
521
|
-
headers:
|
|
522
|
-
|
|
523
|
-
},
|
|
524
|
-
body: JSON.stringify({ seed, chain: chain2, to, amount, network })
|
|
529
|
+
headers: this.getHeaders(),
|
|
530
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
525
531
|
});
|
|
526
532
|
return await response.json();
|
|
527
533
|
} catch (error) {
|
|
@@ -535,14 +541,12 @@ var WdkApiClient = class {
|
|
|
535
541
|
* Get transaction history for an address on a specific chain
|
|
536
542
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
537
543
|
*/
|
|
538
|
-
async getTransactionHistory(seed,
|
|
544
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
539
545
|
try {
|
|
540
546
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
541
547
|
method: "POST",
|
|
542
|
-
headers:
|
|
543
|
-
|
|
544
|
-
},
|
|
545
|
-
body: JSON.stringify({ seed, chain: chain2, network, limit })
|
|
548
|
+
headers: this.getHeaders(),
|
|
549
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
546
550
|
});
|
|
547
551
|
return await response.json();
|
|
548
552
|
} catch (error) {
|
|
@@ -556,14 +560,12 @@ var WdkApiClient = class {
|
|
|
556
560
|
* Get transaction status by hash
|
|
557
561
|
* Fetches from blockchain explorers to check confirmation status
|
|
558
562
|
*/
|
|
559
|
-
async getTransactionStatus(txHash,
|
|
563
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
560
564
|
try {
|
|
561
565
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
562
566
|
method: "POST",
|
|
563
|
-
headers:
|
|
564
|
-
|
|
565
|
-
},
|
|
566
|
-
body: JSON.stringify({ txHash, chain: chain2, network })
|
|
567
|
+
headers: this.getHeaders(),
|
|
568
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
567
569
|
});
|
|
568
570
|
return await response.json();
|
|
569
571
|
} catch (error) {
|
|
@@ -576,11 +578,14 @@ var WdkApiClient = class {
|
|
|
576
578
|
};
|
|
577
579
|
var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
578
580
|
var wdkApiClient = null;
|
|
579
|
-
function getWdkApiClient(baseUrl) {
|
|
581
|
+
function getWdkApiClient(baseUrl, authToken) {
|
|
580
582
|
if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
|
|
581
583
|
wdkApiClient = new WdkApiClient({
|
|
582
|
-
baseUrl: baseUrl || DEFAULT_API_URL
|
|
584
|
+
baseUrl: baseUrl || DEFAULT_API_URL,
|
|
585
|
+
authToken
|
|
583
586
|
});
|
|
587
|
+
} else if (authToken !== void 0) {
|
|
588
|
+
wdkApiClient.setAuthToken(authToken);
|
|
584
589
|
}
|
|
585
590
|
return wdkApiClient;
|
|
586
591
|
}
|
|
@@ -598,597 +603,14 @@ __export(BrowserAddressDerivation_exports, {
|
|
|
598
603
|
generateSeedPhrase: () => generateSeedPhrase,
|
|
599
604
|
isValidSeed: () => isValidSeed
|
|
600
605
|
});
|
|
601
|
-
|
|
602
|
-
// node_modules/@scure/base/index.js
|
|
603
|
-
function isBytes(a) {
|
|
604
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
605
|
-
}
|
|
606
|
-
function isArrayOf(isString, arr) {
|
|
607
|
-
if (!Array.isArray(arr))
|
|
608
|
-
return false;
|
|
609
|
-
if (arr.length === 0)
|
|
610
|
-
return true;
|
|
611
|
-
if (isString) {
|
|
612
|
-
return arr.every((item) => typeof item === "string");
|
|
613
|
-
} else {
|
|
614
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
function afn(input) {
|
|
618
|
-
if (typeof input !== "function")
|
|
619
|
-
throw new Error("function expected");
|
|
620
|
-
return true;
|
|
621
|
-
}
|
|
622
|
-
function astr(label, input) {
|
|
623
|
-
if (typeof input !== "string")
|
|
624
|
-
throw new Error(`${label}: string expected`);
|
|
625
|
-
return true;
|
|
626
|
-
}
|
|
627
|
-
function anumber(n) {
|
|
628
|
-
if (!Number.isSafeInteger(n))
|
|
629
|
-
throw new Error(`invalid integer: ${n}`);
|
|
630
|
-
}
|
|
631
|
-
function aArr(input) {
|
|
632
|
-
if (!Array.isArray(input))
|
|
633
|
-
throw new Error("array expected");
|
|
634
|
-
}
|
|
635
|
-
function astrArr(label, input) {
|
|
636
|
-
if (!isArrayOf(true, input))
|
|
637
|
-
throw new Error(`${label}: array of strings expected`);
|
|
638
|
-
}
|
|
639
|
-
function anumArr(label, input) {
|
|
640
|
-
if (!isArrayOf(false, input))
|
|
641
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
642
|
-
}
|
|
643
|
-
// @__NO_SIDE_EFFECTS__
|
|
644
|
-
function chain(...args) {
|
|
645
|
-
const id = (a) => a;
|
|
646
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
647
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
648
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
649
|
-
return { encode, decode };
|
|
650
|
-
}
|
|
651
|
-
// @__NO_SIDE_EFFECTS__
|
|
652
|
-
function alphabet(letters) {
|
|
653
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
654
|
-
const len = lettersA.length;
|
|
655
|
-
astrArr("alphabet", lettersA);
|
|
656
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
657
|
-
return {
|
|
658
|
-
encode: (digits) => {
|
|
659
|
-
aArr(digits);
|
|
660
|
-
return digits.map((i) => {
|
|
661
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
662
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
663
|
-
return lettersA[i];
|
|
664
|
-
});
|
|
665
|
-
},
|
|
666
|
-
decode: (input) => {
|
|
667
|
-
aArr(input);
|
|
668
|
-
return input.map((letter) => {
|
|
669
|
-
astr("alphabet.decode", letter);
|
|
670
|
-
const i = indexes.get(letter);
|
|
671
|
-
if (i === void 0)
|
|
672
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
673
|
-
return i;
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
// @__NO_SIDE_EFFECTS__
|
|
679
|
-
function join(separator = "") {
|
|
680
|
-
astr("join", separator);
|
|
681
|
-
return {
|
|
682
|
-
encode: (from) => {
|
|
683
|
-
astrArr("join.decode", from);
|
|
684
|
-
return from.join(separator);
|
|
685
|
-
},
|
|
686
|
-
decode: (to) => {
|
|
687
|
-
astr("join.decode", to);
|
|
688
|
-
return to.split(separator);
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
function convertRadix(data, from, to) {
|
|
693
|
-
if (from < 2)
|
|
694
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
695
|
-
if (to < 2)
|
|
696
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
697
|
-
aArr(data);
|
|
698
|
-
if (!data.length)
|
|
699
|
-
return [];
|
|
700
|
-
let pos = 0;
|
|
701
|
-
const res = [];
|
|
702
|
-
const digits = Array.from(data, (d) => {
|
|
703
|
-
anumber(d);
|
|
704
|
-
if (d < 0 || d >= from)
|
|
705
|
-
throw new Error(`invalid integer: ${d}`);
|
|
706
|
-
return d;
|
|
707
|
-
});
|
|
708
|
-
const dlen = digits.length;
|
|
709
|
-
while (true) {
|
|
710
|
-
let carry = 0;
|
|
711
|
-
let done = true;
|
|
712
|
-
for (let i = pos; i < dlen; i++) {
|
|
713
|
-
const digit = digits[i];
|
|
714
|
-
const fromCarry = from * carry;
|
|
715
|
-
const digitBase = fromCarry + digit;
|
|
716
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
717
|
-
throw new Error("convertRadix: carry overflow");
|
|
718
|
-
}
|
|
719
|
-
const div = digitBase / to;
|
|
720
|
-
carry = digitBase % to;
|
|
721
|
-
const rounded = Math.floor(div);
|
|
722
|
-
digits[i] = rounded;
|
|
723
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
724
|
-
throw new Error("convertRadix: carry overflow");
|
|
725
|
-
if (!done)
|
|
726
|
-
continue;
|
|
727
|
-
else if (!rounded)
|
|
728
|
-
pos = i;
|
|
729
|
-
else
|
|
730
|
-
done = false;
|
|
731
|
-
}
|
|
732
|
-
res.push(carry);
|
|
733
|
-
if (done)
|
|
734
|
-
break;
|
|
735
|
-
}
|
|
736
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
737
|
-
res.push(0);
|
|
738
|
-
return res.reverse();
|
|
739
|
-
}
|
|
740
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
741
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
742
|
-
var powers = /* @__PURE__ */ (() => {
|
|
743
|
-
let res = [];
|
|
744
|
-
for (let i = 0; i < 40; i++)
|
|
745
|
-
res.push(2 ** i);
|
|
746
|
-
return res;
|
|
747
|
-
})();
|
|
748
|
-
function convertRadix2(data, from, to, padding) {
|
|
749
|
-
aArr(data);
|
|
750
|
-
if (from <= 0 || from > 32)
|
|
751
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
752
|
-
if (to <= 0 || to > 32)
|
|
753
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
754
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
755
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
756
|
-
}
|
|
757
|
-
let carry = 0;
|
|
758
|
-
let pos = 0;
|
|
759
|
-
const max = powers[from];
|
|
760
|
-
const mask = powers[to] - 1;
|
|
761
|
-
const res = [];
|
|
762
|
-
for (const n of data) {
|
|
763
|
-
anumber(n);
|
|
764
|
-
if (n >= max)
|
|
765
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
766
|
-
carry = carry << from | n;
|
|
767
|
-
if (pos + from > 32)
|
|
768
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
769
|
-
pos += from;
|
|
770
|
-
for (; pos >= to; pos -= to)
|
|
771
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
772
|
-
const pow = powers[pos];
|
|
773
|
-
if (pow === void 0)
|
|
774
|
-
throw new Error("invalid carry");
|
|
775
|
-
carry &= pow - 1;
|
|
776
|
-
}
|
|
777
|
-
carry = carry << to - pos & mask;
|
|
778
|
-
if (!padding && pos >= from)
|
|
779
|
-
throw new Error("Excess padding");
|
|
780
|
-
if (!padding && carry > 0)
|
|
781
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
782
|
-
if (padding && pos > 0)
|
|
783
|
-
res.push(carry >>> 0);
|
|
784
|
-
return res;
|
|
785
|
-
}
|
|
786
|
-
// @__NO_SIDE_EFFECTS__
|
|
787
|
-
function radix(num) {
|
|
788
|
-
anumber(num);
|
|
789
|
-
const _256 = 2 ** 8;
|
|
790
|
-
return {
|
|
791
|
-
encode: (bytes) => {
|
|
792
|
-
if (!isBytes(bytes))
|
|
793
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
794
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
795
|
-
},
|
|
796
|
-
decode: (digits) => {
|
|
797
|
-
anumArr("radix.decode", digits);
|
|
798
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
// @__NO_SIDE_EFFECTS__
|
|
803
|
-
function radix2(bits, revPadding = false) {
|
|
804
|
-
anumber(bits);
|
|
805
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
806
|
-
throw new Error("radix2: carry overflow");
|
|
807
|
-
return {
|
|
808
|
-
encode: (bytes) => {
|
|
809
|
-
if (!isBytes(bytes))
|
|
810
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
811
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
812
|
-
},
|
|
813
|
-
decode: (digits) => {
|
|
814
|
-
anumArr("radix2.decode", digits);
|
|
815
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
816
|
-
}
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
function unsafeWrapper(fn) {
|
|
820
|
-
afn(fn);
|
|
821
|
-
return function(...args) {
|
|
822
|
-
try {
|
|
823
|
-
return fn.apply(null, args);
|
|
824
|
-
} catch (e) {
|
|
825
|
-
}
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
function checksum(len, fn) {
|
|
829
|
-
anumber(len);
|
|
830
|
-
afn(fn);
|
|
831
|
-
return {
|
|
832
|
-
encode(data) {
|
|
833
|
-
if (!isBytes(data))
|
|
834
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
835
|
-
const sum = fn(data).slice(0, len);
|
|
836
|
-
const res = new Uint8Array(data.length + len);
|
|
837
|
-
res.set(data);
|
|
838
|
-
res.set(sum, data.length);
|
|
839
|
-
return res;
|
|
840
|
-
},
|
|
841
|
-
decode(data) {
|
|
842
|
-
if (!isBytes(data))
|
|
843
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
844
|
-
const payload = data.slice(0, -len);
|
|
845
|
-
const oldChecksum = data.slice(-len);
|
|
846
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
847
|
-
for (let i = 0; i < len; i++)
|
|
848
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
849
|
-
throw new Error("Invalid checksum");
|
|
850
|
-
return payload;
|
|
851
|
-
}
|
|
852
|
-
};
|
|
853
|
-
}
|
|
854
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
855
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
856
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
857
|
-
var base58check = createBase58check;
|
|
858
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
859
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
860
|
-
function bech32Polymod(pre) {
|
|
861
|
-
const b = pre >> 25;
|
|
862
|
-
let chk = (pre & 33554431) << 5;
|
|
863
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
864
|
-
if ((b >> i & 1) === 1)
|
|
865
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
866
|
-
}
|
|
867
|
-
return chk;
|
|
868
|
-
}
|
|
869
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
870
|
-
const len = prefix.length;
|
|
871
|
-
let chk = 1;
|
|
872
|
-
for (let i = 0; i < len; i++) {
|
|
873
|
-
const c = prefix.charCodeAt(i);
|
|
874
|
-
if (c < 33 || c > 126)
|
|
875
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
876
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
877
|
-
}
|
|
878
|
-
chk = bech32Polymod(chk);
|
|
879
|
-
for (let i = 0; i < len; i++)
|
|
880
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
881
|
-
for (let v of words)
|
|
882
|
-
chk = bech32Polymod(chk) ^ v;
|
|
883
|
-
for (let i = 0; i < 6; i++)
|
|
884
|
-
chk = bech32Polymod(chk);
|
|
885
|
-
chk ^= encodingConst;
|
|
886
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
887
|
-
}
|
|
888
|
-
// @__NO_SIDE_EFFECTS__
|
|
889
|
-
function genBech32(encoding) {
|
|
890
|
-
const ENCODING_CONST = 1 ;
|
|
891
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
892
|
-
const fromWords = _words.decode;
|
|
893
|
-
const toWords = _words.encode;
|
|
894
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
895
|
-
function encode(prefix, words, limit = 90) {
|
|
896
|
-
astr("bech32.encode prefix", prefix);
|
|
897
|
-
if (isBytes(words))
|
|
898
|
-
words = Array.from(words);
|
|
899
|
-
anumArr("bech32.encode", words);
|
|
900
|
-
const plen = prefix.length;
|
|
901
|
-
if (plen === 0)
|
|
902
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
903
|
-
const actualLength = plen + 7 + words.length;
|
|
904
|
-
if (limit !== false && actualLength > limit)
|
|
905
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
906
|
-
const lowered = prefix.toLowerCase();
|
|
907
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
908
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
909
|
-
}
|
|
910
|
-
function decode(str, limit = 90) {
|
|
911
|
-
astr("bech32.decode input", str);
|
|
912
|
-
const slen = str.length;
|
|
913
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
914
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
915
|
-
const lowered = str.toLowerCase();
|
|
916
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
917
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
918
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
919
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
920
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
921
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
922
|
-
const data = lowered.slice(sepIndex + 1);
|
|
923
|
-
if (data.length < 6)
|
|
924
|
-
throw new Error("Data must be at least 6 characters long");
|
|
925
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
926
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
927
|
-
if (!data.endsWith(sum))
|
|
928
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
929
|
-
return { prefix, words };
|
|
930
|
-
}
|
|
931
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
932
|
-
function decodeToBytes(str) {
|
|
933
|
-
const { prefix, words } = decode(str, false);
|
|
934
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
935
|
-
}
|
|
936
|
-
function encodeFromBytes(prefix, bytes) {
|
|
937
|
-
return encode(prefix, toWords(bytes));
|
|
938
|
-
}
|
|
939
|
-
return {
|
|
940
|
-
encode,
|
|
941
|
-
decode,
|
|
942
|
-
encodeFromBytes,
|
|
943
|
-
decodeToBytes,
|
|
944
|
-
decodeUnsafe,
|
|
945
|
-
fromWords,
|
|
946
|
-
fromWordsUnsafe,
|
|
947
|
-
toWords
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
951
|
-
|
|
952
|
-
// node_modules/@scure/bip32/index.js
|
|
953
|
-
var Point = secp256k1_js.secp256k1.Point;
|
|
954
|
-
var { Fn } = Point;
|
|
955
|
-
var base58check2 = createBase58check(sha2_js.sha256);
|
|
956
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
957
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
958
|
-
var HARDENED_OFFSET = 2147483648;
|
|
959
|
-
var hash160 = (data) => legacy_js.ripemd160(sha2_js.sha256(data));
|
|
960
|
-
var fromU32 = (data) => utils_js.createView(data).getUint32(0, false);
|
|
961
|
-
var toU32 = (n) => {
|
|
962
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
963
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
964
|
-
}
|
|
965
|
-
const buf = new Uint8Array(4);
|
|
966
|
-
utils_js.createView(buf).setUint32(0, n, false);
|
|
967
|
-
return buf;
|
|
968
|
-
};
|
|
969
|
-
var HDKey = class _HDKey {
|
|
970
|
-
get fingerprint() {
|
|
971
|
-
if (!this.pubHash) {
|
|
972
|
-
throw new Error("No publicKey set!");
|
|
973
|
-
}
|
|
974
|
-
return fromU32(this.pubHash);
|
|
975
|
-
}
|
|
976
|
-
get identifier() {
|
|
977
|
-
return this.pubHash;
|
|
978
|
-
}
|
|
979
|
-
get pubKeyHash() {
|
|
980
|
-
return this.pubHash;
|
|
981
|
-
}
|
|
982
|
-
get privateKey() {
|
|
983
|
-
return this._privateKey || null;
|
|
984
|
-
}
|
|
985
|
-
get publicKey() {
|
|
986
|
-
return this._publicKey || null;
|
|
987
|
-
}
|
|
988
|
-
get privateExtendedKey() {
|
|
989
|
-
const priv = this._privateKey;
|
|
990
|
-
if (!priv) {
|
|
991
|
-
throw new Error("No private key");
|
|
992
|
-
}
|
|
993
|
-
return base58check2.encode(this.serialize(this.versions.private, utils_js.concatBytes(Uint8Array.of(0), priv)));
|
|
994
|
-
}
|
|
995
|
-
get publicExtendedKey() {
|
|
996
|
-
if (!this._publicKey) {
|
|
997
|
-
throw new Error("No public key");
|
|
998
|
-
}
|
|
999
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
1000
|
-
}
|
|
1001
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
1002
|
-
utils_js.abytes(seed);
|
|
1003
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
1004
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
1005
|
-
}
|
|
1006
|
-
const I = hmac_js.hmac(sha2_js.sha512, MASTER_SECRET, seed);
|
|
1007
|
-
const privateKey = I.slice(0, 32);
|
|
1008
|
-
const chainCode = I.slice(32);
|
|
1009
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
1010
|
-
}
|
|
1011
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
1012
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
1013
|
-
const keyView = utils_js.createView(keyBuffer);
|
|
1014
|
-
const version = keyView.getUint32(0, false);
|
|
1015
|
-
const opt = {
|
|
1016
|
-
versions,
|
|
1017
|
-
depth: keyBuffer[4],
|
|
1018
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
1019
|
-
index: keyView.getUint32(9, false),
|
|
1020
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
1021
|
-
};
|
|
1022
|
-
const key = keyBuffer.slice(45);
|
|
1023
|
-
const isPriv = key[0] === 0;
|
|
1024
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
1025
|
-
throw new Error("Version mismatch");
|
|
1026
|
-
}
|
|
1027
|
-
if (isPriv) {
|
|
1028
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
1029
|
-
} else {
|
|
1030
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
static fromJSON(json) {
|
|
1034
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
1035
|
-
}
|
|
1036
|
-
versions;
|
|
1037
|
-
depth = 0;
|
|
1038
|
-
index = 0;
|
|
1039
|
-
chainCode = null;
|
|
1040
|
-
parentFingerprint = 0;
|
|
1041
|
-
_privateKey;
|
|
1042
|
-
_publicKey;
|
|
1043
|
-
pubHash;
|
|
1044
|
-
constructor(opt) {
|
|
1045
|
-
if (!opt || typeof opt !== "object") {
|
|
1046
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
1047
|
-
}
|
|
1048
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
1049
|
-
this.depth = opt.depth || 0;
|
|
1050
|
-
this.chainCode = opt.chainCode || null;
|
|
1051
|
-
this.index = opt.index || 0;
|
|
1052
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
1053
|
-
if (!this.depth) {
|
|
1054
|
-
if (this.parentFingerprint || this.index) {
|
|
1055
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
if (this.depth > 255) {
|
|
1059
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
1060
|
-
}
|
|
1061
|
-
if (opt.publicKey && opt.privateKey) {
|
|
1062
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
1063
|
-
}
|
|
1064
|
-
if (opt.privateKey) {
|
|
1065
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
1066
|
-
throw new Error("Invalid private key");
|
|
1067
|
-
this._privateKey = opt.privateKey;
|
|
1068
|
-
this._publicKey = secp256k1_js.secp256k1.getPublicKey(opt.privateKey, true);
|
|
1069
|
-
} else if (opt.publicKey) {
|
|
1070
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
1071
|
-
} else {
|
|
1072
|
-
throw new Error("HDKey: no public or private key provided");
|
|
1073
|
-
}
|
|
1074
|
-
this.pubHash = hash160(this._publicKey);
|
|
1075
|
-
}
|
|
1076
|
-
derive(path) {
|
|
1077
|
-
if (!/^[mM]'?/.test(path)) {
|
|
1078
|
-
throw new Error('Path must start with "m" or "M"');
|
|
1079
|
-
}
|
|
1080
|
-
if (/^[mM]'?$/.test(path)) {
|
|
1081
|
-
return this;
|
|
1082
|
-
}
|
|
1083
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
1084
|
-
let child = this;
|
|
1085
|
-
for (const c of parts) {
|
|
1086
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
1087
|
-
const m1 = m && m[1];
|
|
1088
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
1089
|
-
throw new Error("invalid child index: " + c);
|
|
1090
|
-
let idx = +m1;
|
|
1091
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
1092
|
-
throw new Error("Invalid index");
|
|
1093
|
-
}
|
|
1094
|
-
if (m[2] === "'") {
|
|
1095
|
-
idx += HARDENED_OFFSET;
|
|
1096
|
-
}
|
|
1097
|
-
child = child.deriveChild(idx);
|
|
1098
|
-
}
|
|
1099
|
-
return child;
|
|
1100
|
-
}
|
|
1101
|
-
deriveChild(index) {
|
|
1102
|
-
if (!this._publicKey || !this.chainCode) {
|
|
1103
|
-
throw new Error("No publicKey or chainCode set");
|
|
1104
|
-
}
|
|
1105
|
-
let data = toU32(index);
|
|
1106
|
-
if (index >= HARDENED_OFFSET) {
|
|
1107
|
-
const priv = this._privateKey;
|
|
1108
|
-
if (!priv) {
|
|
1109
|
-
throw new Error("Could not derive hardened child key");
|
|
1110
|
-
}
|
|
1111
|
-
data = utils_js.concatBytes(Uint8Array.of(0), priv, data);
|
|
1112
|
-
} else {
|
|
1113
|
-
data = utils_js.concatBytes(this._publicKey, data);
|
|
1114
|
-
}
|
|
1115
|
-
const I = hmac_js.hmac(sha2_js.sha512, this.chainCode, data);
|
|
1116
|
-
const childTweak = I.slice(0, 32);
|
|
1117
|
-
const chainCode = I.slice(32);
|
|
1118
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
1119
|
-
throw new Error("Tweak bigger than curve order");
|
|
1120
|
-
}
|
|
1121
|
-
const opt = {
|
|
1122
|
-
versions: this.versions,
|
|
1123
|
-
chainCode,
|
|
1124
|
-
depth: this.depth + 1,
|
|
1125
|
-
parentFingerprint: this.fingerprint,
|
|
1126
|
-
index
|
|
1127
|
-
};
|
|
1128
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
1129
|
-
try {
|
|
1130
|
-
if (this._privateKey) {
|
|
1131
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
1132
|
-
if (!Fn.isValidNot0(added)) {
|
|
1133
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
1134
|
-
}
|
|
1135
|
-
opt.privateKey = Fn.toBytes(added);
|
|
1136
|
-
} else {
|
|
1137
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
1138
|
-
if (added.equals(Point.ZERO)) {
|
|
1139
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
1140
|
-
}
|
|
1141
|
-
opt.publicKey = added.toBytes(true);
|
|
1142
|
-
}
|
|
1143
|
-
return new _HDKey(opt);
|
|
1144
|
-
} catch (err) {
|
|
1145
|
-
return this.deriveChild(index + 1);
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
sign(hash) {
|
|
1149
|
-
if (!this._privateKey) {
|
|
1150
|
-
throw new Error("No privateKey set!");
|
|
1151
|
-
}
|
|
1152
|
-
utils_js.abytes(hash, 32);
|
|
1153
|
-
return secp256k1_js.secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
1154
|
-
}
|
|
1155
|
-
verify(hash, signature) {
|
|
1156
|
-
utils_js.abytes(hash, 32);
|
|
1157
|
-
utils_js.abytes(signature, 64);
|
|
1158
|
-
if (!this._publicKey) {
|
|
1159
|
-
throw new Error("No publicKey set!");
|
|
1160
|
-
}
|
|
1161
|
-
return secp256k1_js.secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
1162
|
-
}
|
|
1163
|
-
wipePrivateData() {
|
|
1164
|
-
if (this._privateKey) {
|
|
1165
|
-
this._privateKey.fill(0);
|
|
1166
|
-
this._privateKey = void 0;
|
|
1167
|
-
}
|
|
1168
|
-
return this;
|
|
1169
|
-
}
|
|
1170
|
-
toJSON() {
|
|
1171
|
-
return {
|
|
1172
|
-
xpriv: this.privateExtendedKey,
|
|
1173
|
-
xpub: this.publicExtendedKey
|
|
1174
|
-
};
|
|
1175
|
-
}
|
|
1176
|
-
serialize(version, key) {
|
|
1177
|
-
if (!this.chainCode) {
|
|
1178
|
-
throw new Error("No chainCode set");
|
|
1179
|
-
}
|
|
1180
|
-
utils_js.abytes(key, 33);
|
|
1181
|
-
return utils_js.concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
1182
|
-
}
|
|
1183
|
-
};
|
|
1184
606
|
var DERIVATION_PATHS2 = {
|
|
1185
|
-
ethereum:
|
|
1186
|
-
bitcoin_mainnet:
|
|
607
|
+
ethereum: `${DERIVATION_PATHS.ethereum}/0`,
|
|
608
|
+
bitcoin_mainnet: `${DERIVATION_PATHS.bitcoin}/0`,
|
|
1187
609
|
bitcoin_testnet: "m/84'/1'/0'/0/0",
|
|
1188
|
-
ton:
|
|
1189
|
-
tron:
|
|
1190
|
-
solana:
|
|
1191
|
-
spark:
|
|
610
|
+
ton: `${DERIVATION_PATHS.ton}/0'/0'`,
|
|
611
|
+
tron: `${DERIVATION_PATHS.tron}/0`,
|
|
612
|
+
solana: `${DERIVATION_PATHS.solana}/0'`,
|
|
613
|
+
spark: `${DERIVATION_PATHS.spark}/0`
|
|
1192
614
|
};
|
|
1193
615
|
function deriveEthereumAddress(seed) {
|
|
1194
616
|
const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
|
|
@@ -1197,7 +619,7 @@ function deriveEthereumAddress(seed) {
|
|
|
1197
619
|
function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
1198
620
|
try {
|
|
1199
621
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
1200
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
622
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
1201
623
|
const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
|
|
1202
624
|
const child = hdKey.derive(path);
|
|
1203
625
|
if (!child.publicKey) {
|
|
@@ -1205,10 +627,10 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
1205
627
|
}
|
|
1206
628
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
1207
629
|
const witnessVersion = 0;
|
|
1208
|
-
const words = bech32.toWords(pubKeyHash);
|
|
630
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1209
631
|
words.unshift(witnessVersion);
|
|
1210
632
|
const hrp = network === "testnet" ? "tb" : "bc";
|
|
1211
|
-
const address = bech32.encode(hrp, words);
|
|
633
|
+
const address = base.bech32.encode(hrp, words);
|
|
1212
634
|
return address;
|
|
1213
635
|
} catch (error) {
|
|
1214
636
|
console.error("Bitcoin address derivation failed:", error);
|
|
@@ -1281,7 +703,7 @@ function deriveTronAddress(seed) {
|
|
|
1281
703
|
for (let i = 0; i < 20; i++) {
|
|
1282
704
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1283
705
|
}
|
|
1284
|
-
const tronBase58check = base58check(sha256.sha256);
|
|
706
|
+
const tronBase58check = base.base58check(sha256.sha256);
|
|
1285
707
|
return tronBase58check.encode(addressBytes);
|
|
1286
708
|
} catch (error) {
|
|
1287
709
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1291,17 +713,17 @@ function deriveTronAddress(seed) {
|
|
|
1291
713
|
function deriveSparkAddress(seed, network = "mainnet") {
|
|
1292
714
|
try {
|
|
1293
715
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
1294
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
716
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
1295
717
|
const child = hdKey.derive(DERIVATION_PATHS2.spark);
|
|
1296
718
|
if (!child.publicKey) {
|
|
1297
719
|
throw new Error("Failed to derive public key");
|
|
1298
720
|
}
|
|
1299
721
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
1300
722
|
const witnessVersion = 0;
|
|
1301
|
-
const words = bech32.toWords(pubKeyHash);
|
|
723
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1302
724
|
words.unshift(witnessVersion);
|
|
1303
725
|
const hrp = network === "testnet" ? "tsp" : "sp";
|
|
1304
|
-
const address = bech32.encode(hrp, words);
|
|
726
|
+
const address = base.bech32.encode(hrp, words);
|
|
1305
727
|
return address;
|
|
1306
728
|
} catch (error) {
|
|
1307
729
|
console.error("Spark address derivation failed:", error);
|
|
@@ -1397,9 +819,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1397
819
|
"no route": "NETWORK_ERROR"
|
|
1398
820
|
}
|
|
1399
821
|
};
|
|
1400
|
-
function parseChainError(
|
|
822
|
+
function parseChainError(chain, errorMessage) {
|
|
1401
823
|
const errorLower = errorMessage.toLowerCase();
|
|
1402
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
824
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1403
825
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1404
826
|
if (errorLower.includes(pattern)) {
|
|
1405
827
|
return code;
|
|
@@ -1537,38 +959,38 @@ var ZubariWdkService = class {
|
|
|
1537
959
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1538
960
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1539
961
|
*/
|
|
1540
|
-
async deriveAddress(seed,
|
|
962
|
+
async deriveAddress(seed, chain) {
|
|
1541
963
|
await this.initialize();
|
|
1542
|
-
const path = this.getDerivationPath(
|
|
964
|
+
const path = this.getDerivationPath(chain);
|
|
1543
965
|
try {
|
|
1544
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
966
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1545
967
|
if (response.success && response.address) {
|
|
1546
968
|
return {
|
|
1547
|
-
chain
|
|
969
|
+
chain,
|
|
1548
970
|
address: response.address,
|
|
1549
971
|
path: response.path || path
|
|
1550
972
|
};
|
|
1551
973
|
}
|
|
1552
974
|
} catch (error) {
|
|
1553
|
-
console.warn(`API address derivation failed for ${
|
|
1554
|
-
if (
|
|
1555
|
-
return this.deriveBrowserAddress(seed,
|
|
975
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
976
|
+
if (chain === "ethereum") {
|
|
977
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1556
978
|
}
|
|
1557
979
|
}
|
|
1558
980
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1559
981
|
try {
|
|
1560
982
|
const wdk = this.nativeWdkService;
|
|
1561
983
|
await wdk.initialize(seed);
|
|
1562
|
-
return await wdk.deriveAddress(
|
|
984
|
+
return await wdk.deriveAddress(chain);
|
|
1563
985
|
} catch (error) {
|
|
1564
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
986
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1565
987
|
}
|
|
1566
988
|
}
|
|
1567
|
-
if (
|
|
1568
|
-
return this.deriveBrowserAddress(seed,
|
|
989
|
+
if (chain === "ethereum") {
|
|
990
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1569
991
|
}
|
|
1570
992
|
throw new Error(
|
|
1571
|
-
`WDK API required for ${
|
|
993
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1572
994
|
);
|
|
1573
995
|
}
|
|
1574
996
|
/**
|
|
@@ -1648,13 +1070,13 @@ var ZubariWdkService = class {
|
|
|
1648
1070
|
/**
|
|
1649
1071
|
* Get fee rates for a chain
|
|
1650
1072
|
*/
|
|
1651
|
-
async getFeeRates(seed,
|
|
1073
|
+
async getFeeRates(seed, chain) {
|
|
1652
1074
|
await this.initialize();
|
|
1653
1075
|
try {
|
|
1654
1076
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1655
1077
|
method: "POST",
|
|
1656
1078
|
headers: { "Content-Type": "application/json" },
|
|
1657
|
-
body: JSON.stringify({ seed, chain
|
|
1079
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1658
1080
|
});
|
|
1659
1081
|
if (response.ok) {
|
|
1660
1082
|
const data = await response.json();
|
|
@@ -1663,20 +1085,20 @@ var ZubariWdkService = class {
|
|
|
1663
1085
|
}
|
|
1664
1086
|
}
|
|
1665
1087
|
} catch (error) {
|
|
1666
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
1088
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1667
1089
|
}
|
|
1668
1090
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1669
1091
|
}
|
|
1670
1092
|
/**
|
|
1671
1093
|
* Estimate transaction fee
|
|
1672
1094
|
*/
|
|
1673
|
-
async estimateFee(seed,
|
|
1095
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1674
1096
|
await this.initialize();
|
|
1675
1097
|
try {
|
|
1676
1098
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1677
1099
|
method: "POST",
|
|
1678
1100
|
headers: { "Content-Type": "application/json" },
|
|
1679
|
-
body: JSON.stringify({ seed, chain
|
|
1101
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1680
1102
|
});
|
|
1681
1103
|
if (response.ok) {
|
|
1682
1104
|
const data = await response.json();
|
|
@@ -1685,9 +1107,9 @@ var ZubariWdkService = class {
|
|
|
1685
1107
|
}
|
|
1686
1108
|
}
|
|
1687
1109
|
} catch (error) {
|
|
1688
|
-
console.warn(`Failed to estimate fee for ${
|
|
1110
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1689
1111
|
}
|
|
1690
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
1112
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1691
1113
|
}
|
|
1692
1114
|
/**
|
|
1693
1115
|
* Send a transaction on any supported chain
|
|
@@ -1698,19 +1120,14 @@ var ZubariWdkService = class {
|
|
|
1698
1120
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1699
1121
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1700
1122
|
*/
|
|
1701
|
-
async sendTransaction(seed,
|
|
1123
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1702
1124
|
await this.initialize();
|
|
1703
1125
|
const startTime = Date.now();
|
|
1704
|
-
console.log(`[ZubariWdkService] Sending ${chain2} transaction`, {
|
|
1705
|
-
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1706
|
-
amount,
|
|
1707
|
-
network: this.config.network
|
|
1708
|
-
});
|
|
1709
1126
|
try {
|
|
1710
1127
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1711
1128
|
method: "POST",
|
|
1712
1129
|
headers: { "Content-Type": "application/json" },
|
|
1713
|
-
body: JSON.stringify({ seed, chain
|
|
1130
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1714
1131
|
});
|
|
1715
1132
|
const elapsed = Date.now() - startTime;
|
|
1716
1133
|
if (response.ok) {
|
|
@@ -1720,22 +1137,18 @@ var ZubariWdkService = class {
|
|
|
1720
1137
|
txHash = txHash.hash;
|
|
1721
1138
|
}
|
|
1722
1139
|
if (txHash) {
|
|
1723
|
-
const isValid = this.validateTxHash(
|
|
1140
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1724
1141
|
if (!isValid) {
|
|
1725
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
1142
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1726
1143
|
}
|
|
1727
1144
|
}
|
|
1728
|
-
console.log(`[ZubariWdkService] ${chain2} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1729
|
-
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1730
|
-
elapsed: `${elapsed}ms`
|
|
1731
|
-
});
|
|
1732
1145
|
if (!data.success) {
|
|
1733
|
-
const errorCode2 = parseChainError(
|
|
1146
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1734
1147
|
return {
|
|
1735
1148
|
success: false,
|
|
1736
1149
|
error: data.error,
|
|
1737
1150
|
errorCode: errorCode2,
|
|
1738
|
-
chain
|
|
1151
|
+
chain
|
|
1739
1152
|
};
|
|
1740
1153
|
}
|
|
1741
1154
|
return {
|
|
@@ -1744,47 +1157,35 @@ var ZubariWdkService = class {
|
|
|
1744
1157
|
from: data.from,
|
|
1745
1158
|
to: data.to,
|
|
1746
1159
|
amount: data.amount,
|
|
1747
|
-
chain: data.chain ||
|
|
1160
|
+
chain: data.chain || chain,
|
|
1748
1161
|
network: data.network || this.config.network
|
|
1749
1162
|
};
|
|
1750
1163
|
}
|
|
1751
1164
|
const errorData = await response.json().catch(() => ({}));
|
|
1752
1165
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1753
|
-
const errorCode = parseChainError(
|
|
1754
|
-
console.error(`[ZubariWdkService] ${chain2} transaction FAILED`, {
|
|
1755
|
-
status: response.status,
|
|
1756
|
-
error: errorMessage,
|
|
1757
|
-
errorCode,
|
|
1758
|
-
elapsed: `${elapsed}ms`
|
|
1759
|
-
});
|
|
1166
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1760
1167
|
return {
|
|
1761
1168
|
success: false,
|
|
1762
1169
|
error: errorMessage,
|
|
1763
1170
|
errorCode,
|
|
1764
|
-
chain
|
|
1171
|
+
chain
|
|
1765
1172
|
};
|
|
1766
1173
|
} catch (error) {
|
|
1767
|
-
const elapsed = Date.now() - startTime;
|
|
1768
1174
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1769
|
-
const errorCode = parseChainError(
|
|
1770
|
-
console.error(`[ZubariWdkService] ${chain2} transaction ERROR`, {
|
|
1771
|
-
error: errorMessage,
|
|
1772
|
-
errorCode,
|
|
1773
|
-
elapsed: `${elapsed}ms`
|
|
1774
|
-
});
|
|
1175
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1775
1176
|
return {
|
|
1776
1177
|
success: false,
|
|
1777
1178
|
error: errorMessage,
|
|
1778
1179
|
errorCode,
|
|
1779
|
-
chain
|
|
1180
|
+
chain
|
|
1780
1181
|
};
|
|
1781
1182
|
}
|
|
1782
1183
|
}
|
|
1783
1184
|
/**
|
|
1784
1185
|
* Validate transaction hash format for a specific chain
|
|
1785
1186
|
*/
|
|
1786
|
-
validateTxHash(
|
|
1787
|
-
switch (
|
|
1187
|
+
validateTxHash(chain, txHash) {
|
|
1188
|
+
switch (chain) {
|
|
1788
1189
|
case "ethereum":
|
|
1789
1190
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1790
1191
|
case "bitcoin":
|
|
@@ -1816,18 +1217,25 @@ var ZubariWdkService = class {
|
|
|
1816
1217
|
// ==========================================
|
|
1817
1218
|
// Private Helper Methods
|
|
1818
1219
|
// ==========================================
|
|
1819
|
-
getDerivationPath(
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1220
|
+
getDerivationPath(chain) {
|
|
1221
|
+
const basePath = DERIVATION_PATHS[chain];
|
|
1222
|
+
if (chain === "bitcoin" && this.config.network === "testnet") {
|
|
1223
|
+
return "m/84'/1'/0'/0/0";
|
|
1224
|
+
}
|
|
1225
|
+
switch (chain) {
|
|
1226
|
+
case "ton":
|
|
1227
|
+
return `${basePath}/0'/0'`;
|
|
1228
|
+
case "solana":
|
|
1229
|
+
return `${basePath}/0'`;
|
|
1230
|
+
case "bitcoin":
|
|
1231
|
+
case "ethereum":
|
|
1232
|
+
case "tron":
|
|
1233
|
+
case "spark":
|
|
1234
|
+
default:
|
|
1235
|
+
return `${basePath}/0`;
|
|
1236
|
+
}
|
|
1829
1237
|
}
|
|
1830
|
-
getChainSymbol(
|
|
1238
|
+
getChainSymbol(chain) {
|
|
1831
1239
|
const symbols = {
|
|
1832
1240
|
ethereum: "ETH",
|
|
1833
1241
|
bitcoin: "BTC",
|
|
@@ -1836,16 +1244,16 @@ var ZubariWdkService = class {
|
|
|
1836
1244
|
solana: "SOL",
|
|
1837
1245
|
spark: "SAT"
|
|
1838
1246
|
};
|
|
1839
|
-
return symbols[
|
|
1247
|
+
return symbols[chain];
|
|
1840
1248
|
}
|
|
1841
1249
|
/**
|
|
1842
1250
|
* Derive address using browser-compatible libraries
|
|
1843
1251
|
*/
|
|
1844
|
-
async deriveBrowserAddress(seed,
|
|
1845
|
-
const path = this.getDerivationPath(
|
|
1252
|
+
async deriveBrowserAddress(seed, chain) {
|
|
1253
|
+
const path = this.getDerivationPath(chain);
|
|
1846
1254
|
try {
|
|
1847
1255
|
let address;
|
|
1848
|
-
switch (
|
|
1256
|
+
switch (chain) {
|
|
1849
1257
|
case "ethereum":
|
|
1850
1258
|
address = deriveEthereumAddress(seed);
|
|
1851
1259
|
break;
|
|
@@ -1865,11 +1273,11 @@ var ZubariWdkService = class {
|
|
|
1865
1273
|
address = await deriveTonAddress(seed);
|
|
1866
1274
|
break;
|
|
1867
1275
|
default:
|
|
1868
|
-
throw new Error(`Unsupported chain: ${
|
|
1276
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1869
1277
|
}
|
|
1870
|
-
return { chain
|
|
1278
|
+
return { chain, address, path };
|
|
1871
1279
|
} catch (error) {
|
|
1872
|
-
console.error(`Browser derivation failed for ${
|
|
1280
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1873
1281
|
throw error;
|
|
1874
1282
|
}
|
|
1875
1283
|
}
|
|
@@ -1882,7 +1290,7 @@ var ZubariWdkService = class {
|
|
|
1882
1290
|
};
|
|
1883
1291
|
var defaultService = null;
|
|
1884
1292
|
function getZubariWdkService(config) {
|
|
1885
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1293
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1886
1294
|
defaultService = new ZubariWdkService(config);
|
|
1887
1295
|
}
|
|
1888
1296
|
return defaultService;
|
|
@@ -1892,12 +1300,21 @@ function createZubariWdkService(config) {
|
|
|
1892
1300
|
}
|
|
1893
1301
|
|
|
1894
1302
|
// src/wallet/ZubariWallet.ts
|
|
1895
|
-
var ZubariWallet = class {
|
|
1303
|
+
var ZubariWallet = class _ZubariWallet {
|
|
1896
1304
|
seed;
|
|
1897
1305
|
config;
|
|
1898
1306
|
accounts = /* @__PURE__ */ new Map();
|
|
1899
1307
|
wdkService;
|
|
1900
1308
|
initialized = false;
|
|
1309
|
+
/** Mapping from NetworkType to SupportedChain (identity map, shared across methods) */
|
|
1310
|
+
static CHAIN_MAP = {
|
|
1311
|
+
ethereum: "ethereum",
|
|
1312
|
+
bitcoin: "bitcoin",
|
|
1313
|
+
ton: "ton",
|
|
1314
|
+
tron: "tron",
|
|
1315
|
+
solana: "solana",
|
|
1316
|
+
spark: "spark"
|
|
1317
|
+
};
|
|
1901
1318
|
constructor(seed, config) {
|
|
1902
1319
|
this.seed = seed;
|
|
1903
1320
|
this.config = {
|
|
@@ -1930,20 +1347,12 @@ var ZubariWallet = class {
|
|
|
1930
1347
|
async deriveAccount(network, index = 0) {
|
|
1931
1348
|
const basePath = DERIVATION_PATHS[network];
|
|
1932
1349
|
const derivationPath = `${basePath}/${index}`;
|
|
1933
|
-
const
|
|
1934
|
-
|
|
1935
|
-
bitcoin: "bitcoin",
|
|
1936
|
-
ton: "ton",
|
|
1937
|
-
tron: "tron",
|
|
1938
|
-
solana: "solana",
|
|
1939
|
-
spark: "spark"
|
|
1940
|
-
};
|
|
1941
|
-
const chain2 = chainMap[network];
|
|
1942
|
-
if (!chain2) {
|
|
1350
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1351
|
+
if (!chain) {
|
|
1943
1352
|
throw new Error(`Unsupported network: ${network}`);
|
|
1944
1353
|
}
|
|
1945
1354
|
try {
|
|
1946
|
-
const result = await this.wdkService.deriveAddress(this.seed,
|
|
1355
|
+
const result = await this.wdkService.deriveAddress(this.seed, chain);
|
|
1947
1356
|
const account = {
|
|
1948
1357
|
network,
|
|
1949
1358
|
address: result.address,
|
|
@@ -1990,21 +1399,13 @@ var ZubariWallet = class {
|
|
|
1990
1399
|
*/
|
|
1991
1400
|
async getBalance(network) {
|
|
1992
1401
|
const networkConfig = getNetworkConfig(network, this.config.network === "testnet");
|
|
1993
|
-
const
|
|
1994
|
-
|
|
1995
|
-
bitcoin: "bitcoin",
|
|
1996
|
-
ton: "ton",
|
|
1997
|
-
tron: "tron",
|
|
1998
|
-
solana: "solana",
|
|
1999
|
-
spark: "spark"
|
|
2000
|
-
};
|
|
2001
|
-
const chain2 = chainMap[network];
|
|
2002
|
-
if (!chain2) {
|
|
1402
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1403
|
+
if (!chain) {
|
|
2003
1404
|
throw new Error(`Unsupported network: ${network}`);
|
|
2004
1405
|
}
|
|
2005
1406
|
try {
|
|
2006
1407
|
const balances = await this.wdkService.getAllBalances(this.seed);
|
|
2007
|
-
const chainBalance = balances[
|
|
1408
|
+
const chainBalance = balances[chain];
|
|
2008
1409
|
if (chainBalance) {
|
|
2009
1410
|
const balanceValue = BigInt(chainBalance.balance || "0");
|
|
2010
1411
|
const decimals = networkConfig.nativeCurrency.decimals;
|
|
@@ -2085,22 +1486,14 @@ var ZubariWallet = class {
|
|
|
2085
1486
|
*/
|
|
2086
1487
|
async send(network, params) {
|
|
2087
1488
|
const { to, amount } = params;
|
|
2088
|
-
const
|
|
2089
|
-
|
|
2090
|
-
bitcoin: "bitcoin",
|
|
2091
|
-
ton: "ton",
|
|
2092
|
-
tron: "tron",
|
|
2093
|
-
solana: "solana",
|
|
2094
|
-
spark: "spark"
|
|
2095
|
-
};
|
|
2096
|
-
const chain2 = chainMap[network];
|
|
2097
|
-
if (!chain2) {
|
|
1489
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1490
|
+
if (!chain) {
|
|
2098
1491
|
throw new Error(`Unsupported network: ${network}`);
|
|
2099
1492
|
}
|
|
2100
1493
|
try {
|
|
2101
1494
|
const result = await this.wdkService.sendTransaction(
|
|
2102
1495
|
this.seed,
|
|
2103
|
-
|
|
1496
|
+
chain,
|
|
2104
1497
|
to,
|
|
2105
1498
|
amount.toString()
|
|
2106
1499
|
);
|
|
@@ -2398,7 +1791,10 @@ var KeyManager = class {
|
|
|
2398
1791
|
static KEY_LENGTH = 256;
|
|
2399
1792
|
static IV_LENGTH = 12;
|
|
2400
1793
|
static SALT_LENGTH = 16;
|
|
2401
|
-
|
|
1794
|
+
// OWASP 2023 recommends 600,000 iterations for PBKDF2-SHA256 to resist
|
|
1795
|
+
// brute-force attacks with modern GPU hardware.
|
|
1796
|
+
// See: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
|
|
1797
|
+
static PBKDF2_ITERATIONS = 6e5;
|
|
2402
1798
|
/**
|
|
2403
1799
|
* Encrypt a seed phrase with a password
|
|
2404
1800
|
*/
|
|
@@ -2637,7 +2033,7 @@ var WebEncryptedStorageAdapter = class {
|
|
|
2637
2033
|
{
|
|
2638
2034
|
name: "PBKDF2",
|
|
2639
2035
|
salt: salt.buffer,
|
|
2640
|
-
iterations:
|
|
2036
|
+
iterations: 6e5,
|
|
2641
2037
|
hash: "SHA-256"
|
|
2642
2038
|
},
|
|
2643
2039
|
keyMaterial,
|
|
@@ -2775,8 +2171,8 @@ async function fetchPrices() {
|
|
|
2775
2171
|
if (response.ok) {
|
|
2776
2172
|
const data = await response.json();
|
|
2777
2173
|
const prices = {};
|
|
2778
|
-
for (const [
|
|
2779
|
-
prices[
|
|
2174
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
2175
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2780
2176
|
}
|
|
2781
2177
|
priceCache = { prices, timestamp: Date.now() };
|
|
2782
2178
|
return prices;
|
|
@@ -2786,9 +2182,22 @@ async function fetchPrices() {
|
|
|
2786
2182
|
}
|
|
2787
2183
|
return priceCache?.prices || {};
|
|
2788
2184
|
}
|
|
2789
|
-
async function getPriceForChain(
|
|
2185
|
+
async function getPriceForChain(chain) {
|
|
2790
2186
|
const prices = await fetchPrices();
|
|
2791
|
-
return prices[
|
|
2187
|
+
return prices[chain] || 0;
|
|
2188
|
+
}
|
|
2189
|
+
function tonFriendlyToRaw(addr) {
|
|
2190
|
+
if (addr.includes(":")) return addr;
|
|
2191
|
+
try {
|
|
2192
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
2193
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
2194
|
+
if (bytes.length !== 36) return addr;
|
|
2195
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
2196
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2197
|
+
return `${workchain}:${hash}`;
|
|
2198
|
+
} catch {
|
|
2199
|
+
return addr;
|
|
2200
|
+
}
|
|
2792
2201
|
}
|
|
2793
2202
|
var STORAGE_KEYS = {
|
|
2794
2203
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2937,6 +2346,16 @@ var WalletManager = class _WalletManager {
|
|
|
2937
2346
|
}
|
|
2938
2347
|
/**
|
|
2939
2348
|
* Lock wallet (clear seed from memory)
|
|
2349
|
+
*
|
|
2350
|
+
* SECURITY NOTE: JavaScript strings are immutable and cannot be overwritten
|
|
2351
|
+
* in place. Setting `this.currentSeed = null` removes the reference, but
|
|
2352
|
+
* the original string may persist in memory until garbage collected.
|
|
2353
|
+
* There is no reliable way to zero out a JS string.
|
|
2354
|
+
*
|
|
2355
|
+
* TODO: In a future version, store the seed as a Uint8Array instead of a
|
|
2356
|
+
* string. Uint8Array contents can be explicitly zeroed (e.g.,
|
|
2357
|
+
* `seedBytes.fill(0)`) before releasing the reference, which provides
|
|
2358
|
+
* stronger guarantees that sensitive material is scrubbed from memory.
|
|
2940
2359
|
*/
|
|
2941
2360
|
lock() {
|
|
2942
2361
|
this.currentSeed = null;
|
|
@@ -2994,9 +2413,9 @@ var WalletManager = class _WalletManager {
|
|
|
2994
2413
|
if (!this.derivedAddress) {
|
|
2995
2414
|
throw new Error("Wallet not initialized");
|
|
2996
2415
|
}
|
|
2997
|
-
const
|
|
2416
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2998
2417
|
const client = viem.createPublicClient({
|
|
2999
|
-
chain
|
|
2418
|
+
chain,
|
|
3000
2419
|
transport: viem.http(this.config.rpcUrl, {
|
|
3001
2420
|
timeout: 15e3,
|
|
3002
2421
|
// 15 second timeout
|
|
@@ -3018,9 +2437,9 @@ var WalletManager = class _WalletManager {
|
|
|
3018
2437
|
* Create viem public client for the current network
|
|
3019
2438
|
*/
|
|
3020
2439
|
getPublicClient() {
|
|
3021
|
-
const
|
|
2440
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
3022
2441
|
return viem.createPublicClient({
|
|
3023
|
-
chain
|
|
2442
|
+
chain,
|
|
3024
2443
|
transport: viem.http(this.config.rpcUrl, {
|
|
3025
2444
|
timeout: 15e3,
|
|
3026
2445
|
// 15 second timeout
|
|
@@ -3074,11 +2493,11 @@ var WalletManager = class _WalletManager {
|
|
|
3074
2493
|
*
|
|
3075
2494
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
3076
2495
|
*/
|
|
3077
|
-
static async deriveAddressForChainAsync(seed,
|
|
3078
|
-
if (
|
|
2496
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
2497
|
+
if (chain === "ethereum") {
|
|
3079
2498
|
try {
|
|
3080
2499
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
3081
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
2500
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
3082
2501
|
return result2.address;
|
|
3083
2502
|
} catch (error) {
|
|
3084
2503
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -3086,7 +2505,7 @@ var WalletManager = class _WalletManager {
|
|
|
3086
2505
|
}
|
|
3087
2506
|
}
|
|
3088
2507
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
3089
|
-
const result = await wdkService.deriveAddress(seed,
|
|
2508
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
3090
2509
|
return result.address;
|
|
3091
2510
|
}
|
|
3092
2511
|
/**
|
|
@@ -3095,14 +2514,14 @@ var WalletManager = class _WalletManager {
|
|
|
3095
2514
|
*
|
|
3096
2515
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
3097
2516
|
*/
|
|
3098
|
-
static deriveAddressForChain(seed,
|
|
3099
|
-
if (
|
|
2517
|
+
static deriveAddressForChain(seed, chain) {
|
|
2518
|
+
if (chain === "ethereum") {
|
|
3100
2519
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
3101
2520
|
const ethNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
3102
2521
|
return ethNode.address;
|
|
3103
2522
|
}
|
|
3104
2523
|
throw new Error(
|
|
3105
|
-
`Sync derivation not supported for ${
|
|
2524
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
3106
2525
|
);
|
|
3107
2526
|
}
|
|
3108
2527
|
/**
|
|
@@ -3134,9 +2553,9 @@ var WalletManager = class _WalletManager {
|
|
|
3134
2553
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
3135
2554
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
3136
2555
|
const addresses = {};
|
|
3137
|
-
for (const [
|
|
3138
|
-
if (enabledChainsSet.has(
|
|
3139
|
-
addresses[
|
|
2556
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
2557
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
2558
|
+
addresses[chain] = address;
|
|
3140
2559
|
}
|
|
3141
2560
|
}
|
|
3142
2561
|
this.derivedAddresses = addresses;
|
|
@@ -3153,7 +2572,6 @@ var WalletManager = class _WalletManager {
|
|
|
3153
2572
|
async saveAddressesToStorage(addresses) {
|
|
3154
2573
|
try {
|
|
3155
2574
|
await this.storage.setItem(STORAGE_KEYS.DERIVED_ADDRESSES, JSON.stringify(addresses));
|
|
3156
|
-
console.log("Saved derived addresses to storage:", Object.keys(addresses));
|
|
3157
2575
|
} catch (error) {
|
|
3158
2576
|
console.warn("Failed to save addresses to storage:", error);
|
|
3159
2577
|
}
|
|
@@ -3177,10 +2595,10 @@ var WalletManager = class _WalletManager {
|
|
|
3177
2595
|
*/
|
|
3178
2596
|
normalizeAddresses(addresses) {
|
|
3179
2597
|
const normalized = {};
|
|
3180
|
-
for (const [
|
|
2598
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
3181
2599
|
const addr = this.normalizeAddress(value);
|
|
3182
2600
|
if (addr) {
|
|
3183
|
-
normalized[
|
|
2601
|
+
normalized[chain] = addr;
|
|
3184
2602
|
}
|
|
3185
2603
|
}
|
|
3186
2604
|
return normalized;
|
|
@@ -3193,9 +2611,7 @@ var WalletManager = class _WalletManager {
|
|
|
3193
2611
|
const stored = await this.storage.getItem(STORAGE_KEYS.DERIVED_ADDRESSES);
|
|
3194
2612
|
if (stored) {
|
|
3195
2613
|
const rawAddresses = JSON.parse(stored);
|
|
3196
|
-
console.log("[WalletManager] Raw addresses from storage:", rawAddresses);
|
|
3197
2614
|
const addresses = this.normalizeAddresses(rawAddresses);
|
|
3198
|
-
console.log("[WalletManager] Normalized addresses:", addresses);
|
|
3199
2615
|
await this.saveAddressesToStorage(addresses);
|
|
3200
2616
|
return addresses;
|
|
3201
2617
|
}
|
|
@@ -3220,11 +2636,8 @@ var WalletManager = class _WalletManager {
|
|
|
3220
2636
|
if (storedAddresses && Object.keys(storedAddresses).length > 1) {
|
|
3221
2637
|
const expectedEthAddress = _WalletManager.deriveAddress(this.currentSeed);
|
|
3222
2638
|
if (storedAddresses.ethereum === expectedEthAddress) {
|
|
3223
|
-
console.log("Using addresses from storage (verified by Ethereum address)");
|
|
3224
2639
|
this.derivedAddresses = storedAddresses;
|
|
3225
2640
|
return storedAddresses;
|
|
3226
|
-
} else {
|
|
3227
|
-
console.log("Stored addresses do not match current seed, re-deriving...");
|
|
3228
2641
|
}
|
|
3229
2642
|
}
|
|
3230
2643
|
return await this.deriveAllAddressesWithWdk();
|
|
@@ -3233,20 +2646,18 @@ var WalletManager = class _WalletManager {
|
|
|
3233
2646
|
* Get address for a specific chain
|
|
3234
2647
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
3235
2648
|
*/
|
|
3236
|
-
getAddressForChain(
|
|
3237
|
-
const cachedValue = this.derivedAddresses[
|
|
2649
|
+
getAddressForChain(chain) {
|
|
2650
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
3238
2651
|
if (cachedValue) {
|
|
3239
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
3240
2652
|
const addr = this.normalizeAddress(cachedValue);
|
|
3241
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) normalized:`, addr);
|
|
3242
2653
|
if (addr) {
|
|
3243
|
-
this.derivedAddresses[
|
|
2654
|
+
this.derivedAddresses[chain] = addr;
|
|
3244
2655
|
return addr;
|
|
3245
2656
|
}
|
|
3246
2657
|
}
|
|
3247
|
-
if (
|
|
3248
|
-
this.derivedAddresses[
|
|
3249
|
-
return this.derivedAddresses[
|
|
2658
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
2659
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
2660
|
+
return this.derivedAddresses[chain];
|
|
3250
2661
|
}
|
|
3251
2662
|
return null;
|
|
3252
2663
|
}
|
|
@@ -3259,11 +2670,11 @@ var WalletManager = class _WalletManager {
|
|
|
3259
2670
|
/**
|
|
3260
2671
|
* Set the selected chain
|
|
3261
2672
|
*/
|
|
3262
|
-
setSelectedChain(
|
|
3263
|
-
if (!this.config.enabledChains.includes(
|
|
3264
|
-
throw new Error(`Chain ${
|
|
2673
|
+
setSelectedChain(chain) {
|
|
2674
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
2675
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
3265
2676
|
}
|
|
3266
|
-
this.selectedChain =
|
|
2677
|
+
this.selectedChain = chain;
|
|
3267
2678
|
}
|
|
3268
2679
|
/**
|
|
3269
2680
|
* Get the currently selected chain
|
|
@@ -3280,22 +2691,22 @@ var WalletManager = class _WalletManager {
|
|
|
3280
2691
|
/**
|
|
3281
2692
|
* Get chain configuration
|
|
3282
2693
|
*/
|
|
3283
|
-
getChainConfig(
|
|
3284
|
-
return getNetworkConfig(
|
|
2694
|
+
getChainConfig(chain) {
|
|
2695
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
3285
2696
|
}
|
|
3286
2697
|
/**
|
|
3287
2698
|
* Fetch balance for a specific chain
|
|
3288
2699
|
* Note: Currently only Ethereum is implemented
|
|
3289
2700
|
*/
|
|
3290
|
-
async fetchBalanceForChain(
|
|
3291
|
-
const address = this.getAddressForChain(
|
|
2701
|
+
async fetchBalanceForChain(chain) {
|
|
2702
|
+
const address = this.getAddressForChain(chain);
|
|
3292
2703
|
if (!address) {
|
|
3293
|
-
throw new Error(`No address for chain ${
|
|
2704
|
+
throw new Error(`No address for chain ${chain}`);
|
|
3294
2705
|
}
|
|
3295
|
-
const networkConfig = this.getChainConfig(
|
|
2706
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3296
2707
|
let balance = "0";
|
|
3297
2708
|
const tokenBalances = {};
|
|
3298
|
-
if (
|
|
2709
|
+
if (chain === "ethereum") {
|
|
3299
2710
|
const viemChain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
3300
2711
|
const isTestnet2 = this.config.network !== "mainnet";
|
|
3301
2712
|
const client = viem.createPublicClient({
|
|
@@ -3342,7 +2753,7 @@ var WalletManager = class _WalletManager {
|
|
|
3342
2753
|
} else if (usdtResult.status === "rejected") {
|
|
3343
2754
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
3344
2755
|
}
|
|
3345
|
-
} else if (
|
|
2756
|
+
} else if (chain === "bitcoin") {
|
|
3346
2757
|
const isMainnet2 = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
3347
2758
|
const apisToTry = isMainnet2 ? ["https://mempool.space/api"] : [
|
|
3348
2759
|
"https://mempool.space/testnet/api",
|
|
@@ -3365,16 +2776,14 @@ var WalletManager = class _WalletManager {
|
|
|
3365
2776
|
const mempoolSpent = data.mempool_stats?.spent_txo_sum || 0;
|
|
3366
2777
|
const satoshis = chainFunded - chainSpent + (mempoolFunded - mempoolSpent);
|
|
3367
2778
|
balance = (satoshis / 1e8).toFixed(8);
|
|
3368
|
-
console.log(`Bitcoin balance for ${address}: ${balance} BTC (${satoshis} sats) via ${apiUrl}`);
|
|
3369
2779
|
break;
|
|
3370
2780
|
}
|
|
3371
|
-
console.log(`No transactions found on ${apiUrl}, trying next...`);
|
|
3372
2781
|
}
|
|
3373
2782
|
} catch (error) {
|
|
3374
2783
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
3375
2784
|
}
|
|
3376
2785
|
}
|
|
3377
|
-
} else if (
|
|
2786
|
+
} else if (chain === "solana") {
|
|
3378
2787
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
3379
2788
|
try {
|
|
3380
2789
|
const response = await fetch(rpcUrl, {
|
|
@@ -3394,7 +2803,7 @@ var WalletManager = class _WalletManager {
|
|
|
3394
2803
|
}
|
|
3395
2804
|
}
|
|
3396
2805
|
} catch (error) {
|
|
3397
|
-
console.warn(`Failed to fetch ${
|
|
2806
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3398
2807
|
}
|
|
3399
2808
|
const isTestnet2 = this.config.network !== "mainnet";
|
|
3400
2809
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet2 ? "testnet" : "mainnet"];
|
|
@@ -3428,7 +2837,7 @@ var WalletManager = class _WalletManager {
|
|
|
3428
2837
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
3429
2838
|
}
|
|
3430
2839
|
}
|
|
3431
|
-
} else if (
|
|
2840
|
+
} else if (chain === "tron") {
|
|
3432
2841
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
3433
2842
|
const baseUrl = tronConfig.rpcUrl;
|
|
3434
2843
|
try {
|
|
@@ -3457,9 +2866,9 @@ var WalletManager = class _WalletManager {
|
|
|
3457
2866
|
}
|
|
3458
2867
|
}
|
|
3459
2868
|
} catch (error) {
|
|
3460
|
-
console.warn(`Failed to fetch ${
|
|
2869
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3461
2870
|
}
|
|
3462
|
-
} else if (
|
|
2871
|
+
} else if (chain === "ton") {
|
|
3463
2872
|
const isTestnet2 = this.config.network !== "mainnet";
|
|
3464
2873
|
const baseUrl = isTestnet2 ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
3465
2874
|
try {
|
|
@@ -3471,29 +2880,39 @@ var WalletManager = class _WalletManager {
|
|
|
3471
2880
|
if (data.ok && data.result !== void 0) {
|
|
3472
2881
|
const nanotons = BigInt(data.result);
|
|
3473
2882
|
balance = (Number(nanotons) / 1e9).toFixed(9);
|
|
3474
|
-
console.log(`TON balance for ${address}: ${balance} TON`);
|
|
3475
2883
|
}
|
|
3476
2884
|
}
|
|
3477
2885
|
} catch (error) {
|
|
3478
|
-
console.warn(`Failed to fetch ${
|
|
2886
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3479
2887
|
}
|
|
3480
2888
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet2 ? "testnet" : "mainnet"];
|
|
3481
2889
|
if (usdtJetton) {
|
|
3482
|
-
const
|
|
2890
|
+
const tonapiBaseUrl = isTestnet2 ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
3483
2891
|
try {
|
|
2892
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
3484
2893
|
const jettonResponse = await fetch(
|
|
3485
|
-
`${
|
|
2894
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
3486
2895
|
{ headers: { "Accept": "application/json" } }
|
|
3487
2896
|
);
|
|
3488
2897
|
if (jettonResponse.ok) {
|
|
3489
2898
|
const jettonData = await jettonResponse.json();
|
|
3490
|
-
const
|
|
3491
|
-
if (
|
|
3492
|
-
const
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
2899
|
+
const balances = jettonData.balances;
|
|
2900
|
+
if (balances && balances.length > 0) {
|
|
2901
|
+
for (const jb of balances) {
|
|
2902
|
+
const jettonAddr = jb.jetton?.address;
|
|
2903
|
+
if (jettonAddr) {
|
|
2904
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2905
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2906
|
+
const rawBalance = jb.balance;
|
|
2907
|
+
if (rawBalance) {
|
|
2908
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2909
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2910
|
+
if (usdtAmount > 0) {
|
|
2911
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
break;
|
|
2915
|
+
}
|
|
3497
2916
|
}
|
|
3498
2917
|
}
|
|
3499
2918
|
}
|
|
@@ -3502,7 +2921,7 @@ var WalletManager = class _WalletManager {
|
|
|
3502
2921
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
3503
2922
|
}
|
|
3504
2923
|
}
|
|
3505
|
-
} else if (
|
|
2924
|
+
} else if (chain === "spark") {
|
|
3506
2925
|
try {
|
|
3507
2926
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
3508
2927
|
method: "POST",
|
|
@@ -3517,18 +2936,17 @@ var WalletManager = class _WalletManager {
|
|
|
3517
2936
|
const data = await response.json();
|
|
3518
2937
|
if (data.success && data.balance !== void 0) {
|
|
3519
2938
|
balance = (parseFloat(data.balance) / 1e8).toFixed(8);
|
|
3520
|
-
console.log(`Spark balance for ${address}: ${balance} BTC`);
|
|
3521
2939
|
}
|
|
3522
2940
|
}
|
|
3523
2941
|
} catch (error) {
|
|
3524
|
-
console.warn(`Failed to fetch ${
|
|
2942
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3525
2943
|
}
|
|
3526
2944
|
}
|
|
3527
|
-
const priceUsd = await getPriceForChain(
|
|
2945
|
+
const priceUsd = await getPriceForChain(chain);
|
|
3528
2946
|
const balanceNum = parseFloat(balance) || 0;
|
|
3529
2947
|
const balanceUsd = balanceNum * priceUsd;
|
|
3530
2948
|
return {
|
|
3531
|
-
chain
|
|
2949
|
+
chain,
|
|
3532
2950
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3533
2951
|
balance,
|
|
3534
2952
|
balanceUsd,
|
|
@@ -3538,28 +2956,29 @@ var WalletManager = class _WalletManager {
|
|
|
3538
2956
|
};
|
|
3539
2957
|
}
|
|
3540
2958
|
/**
|
|
3541
|
-
* Fetch balances for all enabled chains
|
|
2959
|
+
* Fetch balances for all enabled chains in parallel.
|
|
2960
|
+
* Uses Promise.allSettled so that one chain failing does not block others.
|
|
3542
2961
|
*/
|
|
3543
2962
|
async fetchAllBalances() {
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
const networkConfig = this.getChainConfig(chain2);
|
|
3552
|
-
balances.push({
|
|
3553
|
-
chain: chain2,
|
|
3554
|
-
symbol: networkConfig.nativeCurrency.symbol,
|
|
3555
|
-
balance: "0",
|
|
3556
|
-
balanceUsd: 0,
|
|
3557
|
-
address: this.getAddressForChain(chain2) || "",
|
|
3558
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
3559
|
-
});
|
|
2963
|
+
const results = await Promise.allSettled(
|
|
2964
|
+
this.config.enabledChains.map((chain) => this.fetchBalanceForChain(chain))
|
|
2965
|
+
);
|
|
2966
|
+
return results.map((result, index) => {
|
|
2967
|
+
const chain = this.config.enabledChains[index];
|
|
2968
|
+
if (result.status === "fulfilled") {
|
|
2969
|
+
return result.value;
|
|
3560
2970
|
}
|
|
3561
|
-
|
|
3562
|
-
|
|
2971
|
+
console.error(`Failed to fetch balance for ${chain}:`, result.reason);
|
|
2972
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2973
|
+
return {
|
|
2974
|
+
chain,
|
|
2975
|
+
symbol: networkConfig.nativeCurrency.symbol,
|
|
2976
|
+
balance: "0",
|
|
2977
|
+
balanceUsd: 0,
|
|
2978
|
+
address: this.getAddressForChain(chain) || "",
|
|
2979
|
+
decimals: networkConfig.nativeCurrency.decimals
|
|
2980
|
+
};
|
|
2981
|
+
});
|
|
3563
2982
|
}
|
|
3564
2983
|
/**
|
|
3565
2984
|
* Get extended wallet state with multi-chain info
|
|
@@ -3584,13 +3003,13 @@ var WalletManager = class _WalletManager {
|
|
|
3584
3003
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
3585
3004
|
* @returns Transaction result with hash and status
|
|
3586
3005
|
*/
|
|
3587
|
-
async sendTransaction(
|
|
3006
|
+
async sendTransaction(chain, to, amount, token) {
|
|
3588
3007
|
if (!this.currentSeed) {
|
|
3589
3008
|
return { success: false, error: "Wallet is locked" };
|
|
3590
3009
|
}
|
|
3591
|
-
const fromAddress = this.getAddressForChain(
|
|
3010
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
3592
3011
|
if (!fromAddress) {
|
|
3593
|
-
return { success: false, error: `No address for chain ${
|
|
3012
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
3594
3013
|
}
|
|
3595
3014
|
try {
|
|
3596
3015
|
const headers = {
|
|
@@ -3604,7 +3023,7 @@ var WalletManager = class _WalletManager {
|
|
|
3604
3023
|
headers,
|
|
3605
3024
|
body: JSON.stringify({
|
|
3606
3025
|
seed: this.currentSeed,
|
|
3607
|
-
chain
|
|
3026
|
+
chain,
|
|
3608
3027
|
to,
|
|
3609
3028
|
amount,
|
|
3610
3029
|
token,
|
|
@@ -3613,12 +3032,11 @@ var WalletManager = class _WalletManager {
|
|
|
3613
3032
|
});
|
|
3614
3033
|
if (response.ok) {
|
|
3615
3034
|
const data = await response.json();
|
|
3616
|
-
console.log(`Transaction sent on ${chain2}:`, data);
|
|
3617
3035
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
3618
3036
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
3619
3037
|
txHash = txHash.hash;
|
|
3620
3038
|
}
|
|
3621
|
-
if (
|
|
3039
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
3622
3040
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
3623
3041
|
}
|
|
3624
3042
|
return {
|
|
@@ -3627,7 +3045,7 @@ var WalletManager = class _WalletManager {
|
|
|
3627
3045
|
from: fromAddress,
|
|
3628
3046
|
to,
|
|
3629
3047
|
amount,
|
|
3630
|
-
chain
|
|
3048
|
+
chain
|
|
3631
3049
|
};
|
|
3632
3050
|
}
|
|
3633
3051
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -3636,7 +3054,7 @@ var WalletManager = class _WalletManager {
|
|
|
3636
3054
|
error: errorData.error || `HTTP ${response.status}`
|
|
3637
3055
|
};
|
|
3638
3056
|
} catch (error) {
|
|
3639
|
-
console.error(`Transaction failed on ${
|
|
3057
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
3640
3058
|
return {
|
|
3641
3059
|
success: false,
|
|
3642
3060
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -3646,7 +3064,7 @@ var WalletManager = class _WalletManager {
|
|
|
3646
3064
|
/**
|
|
3647
3065
|
* Estimate transaction fee using Tether WDK
|
|
3648
3066
|
*/
|
|
3649
|
-
async estimateFee(
|
|
3067
|
+
async estimateFee(chain, to, amount, token) {
|
|
3650
3068
|
try {
|
|
3651
3069
|
const headers = {
|
|
3652
3070
|
"Content-Type": "application/json"
|
|
@@ -3658,7 +3076,7 @@ var WalletManager = class _WalletManager {
|
|
|
3658
3076
|
method: "POST",
|
|
3659
3077
|
headers,
|
|
3660
3078
|
body: JSON.stringify({
|
|
3661
|
-
chain
|
|
3079
|
+
chain,
|
|
3662
3080
|
to,
|
|
3663
3081
|
amount,
|
|
3664
3082
|
token,
|
|
@@ -7228,10 +6646,23 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7228
6646
|
contractAddress;
|
|
7229
6647
|
chainId;
|
|
7230
6648
|
abi = ZubariSubscription_default;
|
|
6649
|
+
/** Cached ethers Interface instance (lazy-initialized) */
|
|
6650
|
+
_iface = null;
|
|
7231
6651
|
constructor(contractAddress, chainId) {
|
|
7232
6652
|
this.contractAddress = contractAddress;
|
|
7233
6653
|
this.chainId = chainId;
|
|
7234
6654
|
}
|
|
6655
|
+
/**
|
|
6656
|
+
* Get or create the cached ethers Interface for encoding/decoding contract calls.
|
|
6657
|
+
* The Interface is created once on first use and reused for all subsequent calls.
|
|
6658
|
+
*/
|
|
6659
|
+
async getInterface() {
|
|
6660
|
+
if (!this._iface) {
|
|
6661
|
+
const { Interface } = await import('ethers');
|
|
6662
|
+
this._iface = new Interface(this.abi);
|
|
6663
|
+
}
|
|
6664
|
+
return this._iface;
|
|
6665
|
+
}
|
|
7235
6666
|
/**
|
|
7236
6667
|
* Get the contract ABI
|
|
7237
6668
|
*/
|
|
@@ -7259,7 +6690,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7259
6690
|
if (plan.duration <= 0) {
|
|
7260
6691
|
throw new Error("Plan duration must be greater than 0");
|
|
7261
6692
|
}
|
|
7262
|
-
const iface =
|
|
6693
|
+
const iface = await this.getInterface();
|
|
7263
6694
|
const durationDays = Math.ceil(plan.duration / (24 * 60 * 60));
|
|
7264
6695
|
const data = iface.encodeFunctionData("createPlan", [
|
|
7265
6696
|
plan.name,
|
|
@@ -7284,7 +6715,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7284
6715
|
* @param signer Wallet signer
|
|
7285
6716
|
*/
|
|
7286
6717
|
async deactivatePlan(planId, signer) {
|
|
7287
|
-
const iface =
|
|
6718
|
+
const iface = await this.getInterface();
|
|
7288
6719
|
const data = iface.encodeFunctionData("deactivatePlan", [planId]);
|
|
7289
6720
|
const result = await signer.sendTransaction({
|
|
7290
6721
|
to: this.contractAddress,
|
|
@@ -7308,7 +6739,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7308
6739
|
if (months <= 0) {
|
|
7309
6740
|
throw new Error("Subscription duration must be at least 1 month");
|
|
7310
6741
|
}
|
|
7311
|
-
const iface =
|
|
6742
|
+
const iface = await this.getInterface();
|
|
7312
6743
|
const data = iface.encodeFunctionData("subscribe", [planId, months]);
|
|
7313
6744
|
const result = await signer.sendTransaction({
|
|
7314
6745
|
to: this.contractAddress,
|
|
@@ -7327,7 +6758,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7327
6758
|
* @param signer Wallet signer
|
|
7328
6759
|
*/
|
|
7329
6760
|
async cancel(subscriptionId, signer) {
|
|
7330
|
-
const iface =
|
|
6761
|
+
const iface = await this.getInterface();
|
|
7331
6762
|
const data = iface.encodeFunctionData("cancel", [subscriptionId]);
|
|
7332
6763
|
const result = await signer.sendTransaction({
|
|
7333
6764
|
to: this.contractAddress,
|
|
@@ -7347,7 +6778,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7347
6778
|
* @param signer Wallet signer
|
|
7348
6779
|
*/
|
|
7349
6780
|
async setAutoRenew(subscriptionId, autoRenew, signer) {
|
|
7350
|
-
const iface =
|
|
6781
|
+
const iface = await this.getInterface();
|
|
7351
6782
|
const data = iface.encodeFunctionData("setAutoRenew", [subscriptionId, autoRenew]);
|
|
7352
6783
|
const result = await signer.sendTransaction({
|
|
7353
6784
|
to: this.contractAddress,
|
|
@@ -7367,7 +6798,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7367
6798
|
* @param provider JSON-RPC provider
|
|
7368
6799
|
*/
|
|
7369
6800
|
async isSubscribed(subscriber, creator, provider) {
|
|
7370
|
-
const iface =
|
|
6801
|
+
const iface = await this.getInterface();
|
|
7371
6802
|
const data = iface.encodeFunctionData("isSubscribed", [subscriber, creator]);
|
|
7372
6803
|
try {
|
|
7373
6804
|
const result = await provider.call({
|
|
@@ -7387,7 +6818,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7387
6818
|
* @param provider JSON-RPC provider
|
|
7388
6819
|
*/
|
|
7389
6820
|
async getActiveSubscriptionId(subscriber, creator, provider) {
|
|
7390
|
-
const iface =
|
|
6821
|
+
const iface = await this.getInterface();
|
|
7391
6822
|
const data = iface.encodeFunctionData("activeSubscription", [subscriber, creator]);
|
|
7392
6823
|
try {
|
|
7393
6824
|
const result = await provider.call({
|
|
@@ -7410,7 +6841,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7410
6841
|
* @param provider JSON-RPC provider
|
|
7411
6842
|
*/
|
|
7412
6843
|
async getSubscription(subscriptionId, provider) {
|
|
7413
|
-
const iface =
|
|
6844
|
+
const iface = await this.getInterface();
|
|
7414
6845
|
const data = iface.encodeFunctionData("getSubscription", [subscriptionId]);
|
|
7415
6846
|
try {
|
|
7416
6847
|
const result = await provider.call({
|
|
@@ -7456,7 +6887,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7456
6887
|
* @param provider JSON-RPC provider
|
|
7457
6888
|
*/
|
|
7458
6889
|
async getPlan(planId, provider) {
|
|
7459
|
-
const iface =
|
|
6890
|
+
const iface = await this.getInterface();
|
|
7460
6891
|
const data = iface.encodeFunctionData("getPlan", [planId]);
|
|
7461
6892
|
try {
|
|
7462
6893
|
const result = await provider.call({
|
|
@@ -7492,7 +6923,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7492
6923
|
* @param provider JSON-RPC provider
|
|
7493
6924
|
*/
|
|
7494
6925
|
async getCreatorPlanIds(creator, provider) {
|
|
7495
|
-
const iface =
|
|
6926
|
+
const iface = await this.getInterface();
|
|
7496
6927
|
const data = iface.encodeFunctionData("getCreatorPlans", [creator]);
|
|
7497
6928
|
try {
|
|
7498
6929
|
const result = await provider.call({
|
|
@@ -7526,7 +6957,7 @@ var ZubariSubscriptionProtocol = class {
|
|
|
7526
6957
|
* @param provider JSON-RPC provider
|
|
7527
6958
|
*/
|
|
7528
6959
|
async getPlatformFeeBps(provider) {
|
|
7529
|
-
const iface =
|
|
6960
|
+
const iface = await this.getInterface();
|
|
7530
6961
|
const data = iface.encodeFunctionData("platformFeeBps", []);
|
|
7531
6962
|
try {
|
|
7532
6963
|
const result = await provider.call({
|
|
@@ -8142,8 +7573,8 @@ async function fetchPrices2() {
|
|
|
8142
7573
|
if (response.ok) {
|
|
8143
7574
|
const data = await response.json();
|
|
8144
7575
|
const prices = {};
|
|
8145
|
-
for (const [
|
|
8146
|
-
prices[
|
|
7576
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS2)) {
|
|
7577
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
8147
7578
|
}
|
|
8148
7579
|
priceCache2 = { prices, timestamp: Date.now() };
|
|
8149
7580
|
return prices;
|
|
@@ -8153,9 +7584,9 @@ async function fetchPrices2() {
|
|
|
8153
7584
|
}
|
|
8154
7585
|
return priceCache2?.prices || {};
|
|
8155
7586
|
}
|
|
8156
|
-
async function getPriceForChain2(
|
|
7587
|
+
async function getPriceForChain2(chain) {
|
|
8157
7588
|
const prices = await fetchPrices2();
|
|
8158
|
-
return prices[
|
|
7589
|
+
return prices[chain] || 0;
|
|
8159
7590
|
}
|
|
8160
7591
|
var dynamicImport2 = new Function("specifier", "return import(specifier)");
|
|
8161
7592
|
async function loadWdkModules() {
|
|
@@ -8245,19 +7676,19 @@ var TransactionService = class {
|
|
|
8245
7676
|
/**
|
|
8246
7677
|
* Get RPC URL for a chain
|
|
8247
7678
|
*/
|
|
8248
|
-
getRpcUrl(
|
|
7679
|
+
getRpcUrl(chain) {
|
|
8249
7680
|
const networkUrls = DEFAULT_RPC_URLS[this.config.network];
|
|
8250
|
-
if (this.config.rpcUrls?.[
|
|
8251
|
-
return this.config.rpcUrls[
|
|
7681
|
+
if (this.config.rpcUrls?.[chain]) {
|
|
7682
|
+
return this.config.rpcUrls[chain];
|
|
8252
7683
|
}
|
|
8253
|
-
return networkUrls[
|
|
7684
|
+
return networkUrls[chain] || "";
|
|
8254
7685
|
}
|
|
8255
7686
|
/**
|
|
8256
7687
|
* Get explorer URL for a transaction
|
|
8257
7688
|
*/
|
|
8258
|
-
getExplorerUrl(
|
|
7689
|
+
getExplorerUrl(chain, txHash) {
|
|
8259
7690
|
const explorers = EXPLORER_URLS[this.config.network];
|
|
8260
|
-
const baseUrl = explorers[
|
|
7691
|
+
const baseUrl = explorers[chain] || "";
|
|
8261
7692
|
return `${baseUrl}${txHash}`;
|
|
8262
7693
|
}
|
|
8263
7694
|
/**
|
|
@@ -8281,27 +7712,27 @@ var TransactionService = class {
|
|
|
8281
7712
|
* Get or create wallet instance for a specific chain
|
|
8282
7713
|
*/
|
|
8283
7714
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8284
|
-
async getWallet(
|
|
7715
|
+
async getWallet(chain) {
|
|
8285
7716
|
if (!this.seed) {
|
|
8286
7717
|
throw new Error("TransactionService not initialized. Call initialize() first.");
|
|
8287
7718
|
}
|
|
8288
|
-
if (this.wallets[
|
|
8289
|
-
return this.wallets[
|
|
7719
|
+
if (this.wallets[chain]) {
|
|
7720
|
+
return this.wallets[chain];
|
|
8290
7721
|
}
|
|
8291
7722
|
const isTestnet2 = this.config.network === "testnet";
|
|
8292
7723
|
try {
|
|
8293
|
-
switch (
|
|
7724
|
+
switch (chain) {
|
|
8294
7725
|
case "ethereum": {
|
|
8295
7726
|
const rpcUrl = this.getRpcUrl("ethereum");
|
|
8296
7727
|
const wallet = new WalletManagerEvm(this.seed, { provider: rpcUrl });
|
|
8297
|
-
this.wallets[
|
|
7728
|
+
this.wallets[chain] = wallet;
|
|
8298
7729
|
return wallet;
|
|
8299
7730
|
}
|
|
8300
7731
|
case "bitcoin": {
|
|
8301
7732
|
const wallet = new WalletManagerBtc(this.seed, {
|
|
8302
7733
|
network: isTestnet2 ? "testnet" : "bitcoin"
|
|
8303
7734
|
});
|
|
8304
|
-
this.wallets[
|
|
7735
|
+
this.wallets[chain] = wallet;
|
|
8305
7736
|
return wallet;
|
|
8306
7737
|
}
|
|
8307
7738
|
case "solana": {
|
|
@@ -8309,7 +7740,7 @@ var TransactionService = class {
|
|
|
8309
7740
|
const wallet = new WalletManagerSolana(this.seed, {
|
|
8310
7741
|
rpcUrl
|
|
8311
7742
|
});
|
|
8312
|
-
this.wallets[
|
|
7743
|
+
this.wallets[chain] = wallet;
|
|
8313
7744
|
return wallet;
|
|
8314
7745
|
}
|
|
8315
7746
|
case "ton": {
|
|
@@ -8317,7 +7748,7 @@ var TransactionService = class {
|
|
|
8317
7748
|
const wallet = new WalletManagerTon(this.seed, {
|
|
8318
7749
|
tonClient: { url }
|
|
8319
7750
|
});
|
|
8320
|
-
this.wallets[
|
|
7751
|
+
this.wallets[chain] = wallet;
|
|
8321
7752
|
return wallet;
|
|
8322
7753
|
}
|
|
8323
7754
|
case "tron": {
|
|
@@ -8325,32 +7756,32 @@ var TransactionService = class {
|
|
|
8325
7756
|
const wallet = new WalletManagerTron(this.seed, {
|
|
8326
7757
|
provider: fullHost
|
|
8327
7758
|
});
|
|
8328
|
-
this.wallets[
|
|
7759
|
+
this.wallets[chain] = wallet;
|
|
8329
7760
|
return wallet;
|
|
8330
7761
|
}
|
|
8331
7762
|
case "spark": {
|
|
8332
7763
|
const wallet = new WalletManagerSpark(this.seed, {
|
|
8333
7764
|
network: isTestnet2 ? "TESTNET" : "MAINNET"
|
|
8334
7765
|
});
|
|
8335
|
-
this.wallets[
|
|
7766
|
+
this.wallets[chain] = wallet;
|
|
8336
7767
|
return wallet;
|
|
8337
7768
|
}
|
|
8338
7769
|
default:
|
|
8339
|
-
throw new Error(`Unsupported chain: ${
|
|
7770
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
8340
7771
|
}
|
|
8341
7772
|
} catch (error) {
|
|
8342
|
-
console.error(`Failed to initialize ${
|
|
7773
|
+
console.error(`Failed to initialize ${chain} wallet:`, error);
|
|
8343
7774
|
throw error;
|
|
8344
7775
|
}
|
|
8345
7776
|
}
|
|
8346
7777
|
/**
|
|
8347
7778
|
* Estimate transaction fee
|
|
8348
7779
|
*/
|
|
8349
|
-
async estimateFee(
|
|
8350
|
-
const wallet = await this.getWallet(
|
|
7780
|
+
async estimateFee(chain, params) {
|
|
7781
|
+
const wallet = await this.getWallet(chain);
|
|
8351
7782
|
try {
|
|
8352
7783
|
const feeRates = await wallet.getFeeRates();
|
|
8353
|
-
if (
|
|
7784
|
+
if (chain === "ethereum") {
|
|
8354
7785
|
return {
|
|
8355
7786
|
slow: {
|
|
8356
7787
|
fee: `${feeRates.slow || "0"} Gwei`,
|
|
@@ -8365,7 +7796,7 @@ var TransactionService = class {
|
|
|
8365
7796
|
estimatedTime: "~30 sec"
|
|
8366
7797
|
}
|
|
8367
7798
|
};
|
|
8368
|
-
} else if (
|
|
7799
|
+
} else if (chain === "bitcoin") {
|
|
8369
7800
|
return {
|
|
8370
7801
|
slow: {
|
|
8371
7802
|
fee: `${feeRates.slow || feeRates.low || "0"} sat/vB`,
|
|
@@ -8397,7 +7828,7 @@ var TransactionService = class {
|
|
|
8397
7828
|
};
|
|
8398
7829
|
}
|
|
8399
7830
|
} catch (error) {
|
|
8400
|
-
console.error(`Error estimating fee for ${
|
|
7831
|
+
console.error(`Error estimating fee for ${chain}:`, error);
|
|
8401
7832
|
return {
|
|
8402
7833
|
slow: { fee: "0", estimatedTime: "Unknown" },
|
|
8403
7834
|
medium: { fee: "0", estimatedTime: "Unknown" },
|
|
@@ -8408,8 +7839,8 @@ var TransactionService = class {
|
|
|
8408
7839
|
/**
|
|
8409
7840
|
* Send a transaction
|
|
8410
7841
|
*/
|
|
8411
|
-
async send(
|
|
8412
|
-
const wallet = await this.getWallet(
|
|
7842
|
+
async send(chain, params) {
|
|
7843
|
+
const wallet = await this.getWallet(chain);
|
|
8413
7844
|
const account = await wallet.getAccount(0);
|
|
8414
7845
|
const timestamp = Date.now();
|
|
8415
7846
|
try {
|
|
@@ -8429,17 +7860,17 @@ var TransactionService = class {
|
|
|
8429
7860
|
}
|
|
8430
7861
|
return {
|
|
8431
7862
|
hash: txHash,
|
|
8432
|
-
network:
|
|
7863
|
+
network: chain,
|
|
8433
7864
|
status: "pending",
|
|
8434
|
-
explorerUrl: this.getExplorerUrl(
|
|
7865
|
+
explorerUrl: this.getExplorerUrl(chain, txHash),
|
|
8435
7866
|
timestamp
|
|
8436
7867
|
};
|
|
8437
7868
|
} catch (error) {
|
|
8438
7869
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
8439
|
-
console.error(`Transaction failed on ${
|
|
7870
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
8440
7871
|
return {
|
|
8441
7872
|
hash: "",
|
|
8442
|
-
network:
|
|
7873
|
+
network: chain,
|
|
8443
7874
|
status: "failed",
|
|
8444
7875
|
error: errorMessage,
|
|
8445
7876
|
timestamp
|
|
@@ -8449,27 +7880,27 @@ var TransactionService = class {
|
|
|
8449
7880
|
/**
|
|
8450
7881
|
* Get transaction status
|
|
8451
7882
|
*/
|
|
8452
|
-
async getTransactionStatus(
|
|
8453
|
-
const wallet = await this.getWallet(
|
|
7883
|
+
async getTransactionStatus(chain, txHash) {
|
|
7884
|
+
const wallet = await this.getWallet(chain);
|
|
8454
7885
|
try {
|
|
8455
7886
|
const tx = await wallet.getTransaction(txHash);
|
|
8456
7887
|
return {
|
|
8457
7888
|
hash: txHash,
|
|
8458
|
-
network:
|
|
7889
|
+
network: chain,
|
|
8459
7890
|
status: tx.confirmed ? "confirmed" : "pending",
|
|
8460
7891
|
blockNumber: tx.blockNumber,
|
|
8461
7892
|
gasUsed: tx.gasUsed?.toString(),
|
|
8462
7893
|
fee: tx.fee?.toString(),
|
|
8463
|
-
explorerUrl: this.getExplorerUrl(
|
|
7894
|
+
explorerUrl: this.getExplorerUrl(chain, txHash),
|
|
8464
7895
|
timestamp: tx.timestamp || Date.now()
|
|
8465
7896
|
};
|
|
8466
7897
|
} catch (error) {
|
|
8467
7898
|
console.error(`Error getting transaction status for ${txHash}:`, error);
|
|
8468
7899
|
return {
|
|
8469
7900
|
hash: txHash,
|
|
8470
|
-
network:
|
|
7901
|
+
network: chain,
|
|
8471
7902
|
status: "pending",
|
|
8472
|
-
explorerUrl: this.getExplorerUrl(
|
|
7903
|
+
explorerUrl: this.getExplorerUrl(chain, txHash),
|
|
8473
7904
|
timestamp: Date.now()
|
|
8474
7905
|
};
|
|
8475
7906
|
}
|
|
@@ -8477,14 +7908,14 @@ var TransactionService = class {
|
|
|
8477
7908
|
/**
|
|
8478
7909
|
* Get transaction history for an address
|
|
8479
7910
|
*/
|
|
8480
|
-
async getTransactionHistory(
|
|
8481
|
-
const wallet = await this.getWallet(
|
|
7911
|
+
async getTransactionHistory(chain, limit = 10) {
|
|
7912
|
+
const wallet = await this.getWallet(chain);
|
|
8482
7913
|
const account = await wallet.getAccount(0);
|
|
8483
7914
|
try {
|
|
8484
7915
|
const history = await account.getTransactions({ limit });
|
|
8485
7916
|
return history.map((tx) => ({
|
|
8486
7917
|
hash: tx.hash || tx.txHash,
|
|
8487
|
-
network:
|
|
7918
|
+
network: chain,
|
|
8488
7919
|
type: tx.type || (tx.from === account.address ? "send" : "receive"),
|
|
8489
7920
|
from: tx.from,
|
|
8490
7921
|
to: tx.to,
|
|
@@ -8496,20 +7927,20 @@ var TransactionService = class {
|
|
|
8496
7927
|
blockNumber: tx.blockNumber
|
|
8497
7928
|
}));
|
|
8498
7929
|
} catch (error) {
|
|
8499
|
-
console.error(`Error getting transaction history for ${
|
|
7930
|
+
console.error(`Error getting transaction history for ${chain}:`, error);
|
|
8500
7931
|
return [];
|
|
8501
7932
|
}
|
|
8502
7933
|
}
|
|
8503
7934
|
/**
|
|
8504
7935
|
* Get balance for a specific chain
|
|
8505
7936
|
*/
|
|
8506
|
-
async getBalance(
|
|
8507
|
-
const wallet = await this.getWallet(
|
|
7937
|
+
async getBalance(chain) {
|
|
7938
|
+
const wallet = await this.getWallet(chain);
|
|
8508
7939
|
const account = await wallet.getAccount(0);
|
|
8509
7940
|
try {
|
|
8510
7941
|
const balance = await account.getBalance();
|
|
8511
7942
|
const balanceStr = balance.toString();
|
|
8512
|
-
const priceUsd = await getPriceForChain2(
|
|
7943
|
+
const priceUsd = await getPriceForChain2(chain);
|
|
8513
7944
|
const balanceNum = parseFloat(balanceStr) || 0;
|
|
8514
7945
|
const balanceUsd = balanceNum * priceUsd;
|
|
8515
7946
|
return {
|
|
@@ -8517,7 +7948,7 @@ var TransactionService = class {
|
|
|
8517
7948
|
balanceUsd
|
|
8518
7949
|
};
|
|
8519
7950
|
} catch (error) {
|
|
8520
|
-
console.error(`Error getting balance for ${
|
|
7951
|
+
console.error(`Error getting balance for ${chain}:`, error);
|
|
8521
7952
|
return { balance: "0", balanceUsd: 0 };
|
|
8522
7953
|
}
|
|
8523
7954
|
}
|
|
@@ -8585,14 +8016,6 @@ function normalizeAddress(address) {
|
|
|
8585
8016
|
}
|
|
8586
8017
|
return address.toLowerCase();
|
|
8587
8018
|
}
|
|
8588
|
-
/*! Bundled license information:
|
|
8589
|
-
|
|
8590
|
-
@scure/base/index.js:
|
|
8591
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
8592
|
-
|
|
8593
|
-
@scure/bip32/index.js:
|
|
8594
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
8595
|
-
*/
|
|
8596
8019
|
|
|
8597
8020
|
exports.BrowserAddressDerivation = BrowserAddressDerivation_exports;
|
|
8598
8021
|
exports.CURRENCY_ADDRESSES = CURRENCY_ADDRESSES;
|