@zubari/sdk 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +227 -797
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +225 -795
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +175 -745
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +173 -743
- package/dist/react/index.mjs.map +1 -1
- package/dist/services/index.js +113 -707
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +111 -705
- package/dist/services/index.mjs.map +1 -1
- package/dist/wallet/index.js +176 -746
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +174 -744
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -2,12 +2,9 @@ import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
|
2
2
|
import { Wallet, HDNodeWallet } from 'ethers';
|
|
3
3
|
import { generateMnemonic, validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';
|
|
4
4
|
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
9
|
-
import { createView, concatBytes, abytes } from '@noble/hashes/utils.js';
|
|
10
|
-
import { sha256 as sha256$1 } from '@noble/hashes/sha256';
|
|
5
|
+
import { HDKey } from '@scure/bip32';
|
|
6
|
+
import { bech32, base58check } from '@scure/base';
|
|
7
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
11
8
|
import { ripemd160 } from '@noble/hashes/ripemd160';
|
|
12
9
|
import { createPublicClient, http, formatEther, getAddress } from 'viem';
|
|
13
10
|
import { mainnet, sepolia } from 'viem/chains';
|
|
@@ -135,8 +132,8 @@ var TESTNET_NETWORKS = {
|
|
|
135
132
|
var USDT_ADDRESSES = {
|
|
136
133
|
ethereum: {
|
|
137
134
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
138
|
-
testnet: "
|
|
139
|
-
// Sepolia
|
|
135
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
136
|
+
// Sepolia (Test Tether USD)
|
|
140
137
|
},
|
|
141
138
|
tron: {
|
|
142
139
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -217,14 +214,14 @@ var WdkApiClient = class {
|
|
|
217
214
|
/**
|
|
218
215
|
* Derive address for a specific chain using Tether WDK
|
|
219
216
|
*/
|
|
220
|
-
async deriveAddress(seed,
|
|
217
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
221
218
|
try {
|
|
222
219
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
223
220
|
method: "POST",
|
|
224
221
|
headers: {
|
|
225
222
|
"Content-Type": "application/json"
|
|
226
223
|
},
|
|
227
|
-
body: JSON.stringify({ seed, chain
|
|
224
|
+
body: JSON.stringify({ seed, chain, network })
|
|
228
225
|
});
|
|
229
226
|
return await response.json();
|
|
230
227
|
} catch (error) {
|
|
@@ -257,14 +254,14 @@ var WdkApiClient = class {
|
|
|
257
254
|
/**
|
|
258
255
|
* Send a transaction on a specific chain using Tether WDK
|
|
259
256
|
*/
|
|
260
|
-
async sendTransaction(seed,
|
|
257
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
261
258
|
try {
|
|
262
259
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
263
260
|
method: "POST",
|
|
264
261
|
headers: {
|
|
265
262
|
"Content-Type": "application/json"
|
|
266
263
|
},
|
|
267
|
-
body: JSON.stringify({ seed, chain
|
|
264
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
268
265
|
});
|
|
269
266
|
return await response.json();
|
|
270
267
|
} catch (error) {
|
|
@@ -278,14 +275,14 @@ var WdkApiClient = class {
|
|
|
278
275
|
* Get transaction history for an address on a specific chain
|
|
279
276
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
280
277
|
*/
|
|
281
|
-
async getTransactionHistory(seed,
|
|
278
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
282
279
|
try {
|
|
283
280
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
284
281
|
method: "POST",
|
|
285
282
|
headers: {
|
|
286
283
|
"Content-Type": "application/json"
|
|
287
284
|
},
|
|
288
|
-
body: JSON.stringify({ seed, chain
|
|
285
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
289
286
|
});
|
|
290
287
|
return await response.json();
|
|
291
288
|
} catch (error) {
|
|
@@ -299,14 +296,14 @@ var WdkApiClient = class {
|
|
|
299
296
|
* Get transaction status by hash
|
|
300
297
|
* Fetches from blockchain explorers to check confirmation status
|
|
301
298
|
*/
|
|
302
|
-
async getTransactionStatus(txHash,
|
|
299
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
303
300
|
try {
|
|
304
301
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
305
302
|
method: "POST",
|
|
306
303
|
headers: {
|
|
307
304
|
"Content-Type": "application/json"
|
|
308
305
|
},
|
|
309
|
-
body: JSON.stringify({ txHash, chain
|
|
306
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
310
307
|
});
|
|
311
308
|
return await response.json();
|
|
312
309
|
} catch (error) {
|
|
@@ -327,589 +324,6 @@ function getWdkApiClient(baseUrl) {
|
|
|
327
324
|
}
|
|
328
325
|
return wdkApiClient;
|
|
329
326
|
}
|
|
330
|
-
|
|
331
|
-
// node_modules/@scure/base/index.js
|
|
332
|
-
function isBytes(a) {
|
|
333
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
334
|
-
}
|
|
335
|
-
function isArrayOf(isString, arr) {
|
|
336
|
-
if (!Array.isArray(arr))
|
|
337
|
-
return false;
|
|
338
|
-
if (arr.length === 0)
|
|
339
|
-
return true;
|
|
340
|
-
if (isString) {
|
|
341
|
-
return arr.every((item) => typeof item === "string");
|
|
342
|
-
} else {
|
|
343
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
function afn(input) {
|
|
347
|
-
if (typeof input !== "function")
|
|
348
|
-
throw new Error("function expected");
|
|
349
|
-
return true;
|
|
350
|
-
}
|
|
351
|
-
function astr(label, input) {
|
|
352
|
-
if (typeof input !== "string")
|
|
353
|
-
throw new Error(`${label}: string expected`);
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
function anumber(n) {
|
|
357
|
-
if (!Number.isSafeInteger(n))
|
|
358
|
-
throw new Error(`invalid integer: ${n}`);
|
|
359
|
-
}
|
|
360
|
-
function aArr(input) {
|
|
361
|
-
if (!Array.isArray(input))
|
|
362
|
-
throw new Error("array expected");
|
|
363
|
-
}
|
|
364
|
-
function astrArr(label, input) {
|
|
365
|
-
if (!isArrayOf(true, input))
|
|
366
|
-
throw new Error(`${label}: array of strings expected`);
|
|
367
|
-
}
|
|
368
|
-
function anumArr(label, input) {
|
|
369
|
-
if (!isArrayOf(false, input))
|
|
370
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
371
|
-
}
|
|
372
|
-
// @__NO_SIDE_EFFECTS__
|
|
373
|
-
function chain(...args) {
|
|
374
|
-
const id = (a) => a;
|
|
375
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
376
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
377
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
378
|
-
return { encode, decode };
|
|
379
|
-
}
|
|
380
|
-
// @__NO_SIDE_EFFECTS__
|
|
381
|
-
function alphabet(letters) {
|
|
382
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
383
|
-
const len = lettersA.length;
|
|
384
|
-
astrArr("alphabet", lettersA);
|
|
385
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
386
|
-
return {
|
|
387
|
-
encode: (digits) => {
|
|
388
|
-
aArr(digits);
|
|
389
|
-
return digits.map((i) => {
|
|
390
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
391
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
392
|
-
return lettersA[i];
|
|
393
|
-
});
|
|
394
|
-
},
|
|
395
|
-
decode: (input) => {
|
|
396
|
-
aArr(input);
|
|
397
|
-
return input.map((letter) => {
|
|
398
|
-
astr("alphabet.decode", letter);
|
|
399
|
-
const i = indexes.get(letter);
|
|
400
|
-
if (i === void 0)
|
|
401
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
402
|
-
return i;
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
// @__NO_SIDE_EFFECTS__
|
|
408
|
-
function join(separator = "") {
|
|
409
|
-
astr("join", separator);
|
|
410
|
-
return {
|
|
411
|
-
encode: (from) => {
|
|
412
|
-
astrArr("join.decode", from);
|
|
413
|
-
return from.join(separator);
|
|
414
|
-
},
|
|
415
|
-
decode: (to) => {
|
|
416
|
-
astr("join.decode", to);
|
|
417
|
-
return to.split(separator);
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
function convertRadix(data, from, to) {
|
|
422
|
-
if (from < 2)
|
|
423
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
424
|
-
if (to < 2)
|
|
425
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
426
|
-
aArr(data);
|
|
427
|
-
if (!data.length)
|
|
428
|
-
return [];
|
|
429
|
-
let pos = 0;
|
|
430
|
-
const res = [];
|
|
431
|
-
const digits = Array.from(data, (d) => {
|
|
432
|
-
anumber(d);
|
|
433
|
-
if (d < 0 || d >= from)
|
|
434
|
-
throw new Error(`invalid integer: ${d}`);
|
|
435
|
-
return d;
|
|
436
|
-
});
|
|
437
|
-
const dlen = digits.length;
|
|
438
|
-
while (true) {
|
|
439
|
-
let carry = 0;
|
|
440
|
-
let done = true;
|
|
441
|
-
for (let i = pos; i < dlen; i++) {
|
|
442
|
-
const digit = digits[i];
|
|
443
|
-
const fromCarry = from * carry;
|
|
444
|
-
const digitBase = fromCarry + digit;
|
|
445
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
446
|
-
throw new Error("convertRadix: carry overflow");
|
|
447
|
-
}
|
|
448
|
-
const div = digitBase / to;
|
|
449
|
-
carry = digitBase % to;
|
|
450
|
-
const rounded = Math.floor(div);
|
|
451
|
-
digits[i] = rounded;
|
|
452
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
453
|
-
throw new Error("convertRadix: carry overflow");
|
|
454
|
-
if (!done)
|
|
455
|
-
continue;
|
|
456
|
-
else if (!rounded)
|
|
457
|
-
pos = i;
|
|
458
|
-
else
|
|
459
|
-
done = false;
|
|
460
|
-
}
|
|
461
|
-
res.push(carry);
|
|
462
|
-
if (done)
|
|
463
|
-
break;
|
|
464
|
-
}
|
|
465
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
466
|
-
res.push(0);
|
|
467
|
-
return res.reverse();
|
|
468
|
-
}
|
|
469
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
470
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
471
|
-
var powers = /* @__PURE__ */ (() => {
|
|
472
|
-
let res = [];
|
|
473
|
-
for (let i = 0; i < 40; i++)
|
|
474
|
-
res.push(2 ** i);
|
|
475
|
-
return res;
|
|
476
|
-
})();
|
|
477
|
-
function convertRadix2(data, from, to, padding) {
|
|
478
|
-
aArr(data);
|
|
479
|
-
if (from <= 0 || from > 32)
|
|
480
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
481
|
-
if (to <= 0 || to > 32)
|
|
482
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
483
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
484
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
485
|
-
}
|
|
486
|
-
let carry = 0;
|
|
487
|
-
let pos = 0;
|
|
488
|
-
const max = powers[from];
|
|
489
|
-
const mask = powers[to] - 1;
|
|
490
|
-
const res = [];
|
|
491
|
-
for (const n of data) {
|
|
492
|
-
anumber(n);
|
|
493
|
-
if (n >= max)
|
|
494
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
495
|
-
carry = carry << from | n;
|
|
496
|
-
if (pos + from > 32)
|
|
497
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
498
|
-
pos += from;
|
|
499
|
-
for (; pos >= to; pos -= to)
|
|
500
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
501
|
-
const pow = powers[pos];
|
|
502
|
-
if (pow === void 0)
|
|
503
|
-
throw new Error("invalid carry");
|
|
504
|
-
carry &= pow - 1;
|
|
505
|
-
}
|
|
506
|
-
carry = carry << to - pos & mask;
|
|
507
|
-
if (!padding && pos >= from)
|
|
508
|
-
throw new Error("Excess padding");
|
|
509
|
-
if (!padding && carry > 0)
|
|
510
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
511
|
-
if (padding && pos > 0)
|
|
512
|
-
res.push(carry >>> 0);
|
|
513
|
-
return res;
|
|
514
|
-
}
|
|
515
|
-
// @__NO_SIDE_EFFECTS__
|
|
516
|
-
function radix(num) {
|
|
517
|
-
anumber(num);
|
|
518
|
-
const _256 = 2 ** 8;
|
|
519
|
-
return {
|
|
520
|
-
encode: (bytes) => {
|
|
521
|
-
if (!isBytes(bytes))
|
|
522
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
523
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
524
|
-
},
|
|
525
|
-
decode: (digits) => {
|
|
526
|
-
anumArr("radix.decode", digits);
|
|
527
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
// @__NO_SIDE_EFFECTS__
|
|
532
|
-
function radix2(bits, revPadding = false) {
|
|
533
|
-
anumber(bits);
|
|
534
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
535
|
-
throw new Error("radix2: carry overflow");
|
|
536
|
-
return {
|
|
537
|
-
encode: (bytes) => {
|
|
538
|
-
if (!isBytes(bytes))
|
|
539
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
540
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
541
|
-
},
|
|
542
|
-
decode: (digits) => {
|
|
543
|
-
anumArr("radix2.decode", digits);
|
|
544
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
function unsafeWrapper(fn) {
|
|
549
|
-
afn(fn);
|
|
550
|
-
return function(...args) {
|
|
551
|
-
try {
|
|
552
|
-
return fn.apply(null, args);
|
|
553
|
-
} catch (e) {
|
|
554
|
-
}
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
function checksum(len, fn) {
|
|
558
|
-
anumber(len);
|
|
559
|
-
afn(fn);
|
|
560
|
-
return {
|
|
561
|
-
encode(data) {
|
|
562
|
-
if (!isBytes(data))
|
|
563
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
564
|
-
const sum = fn(data).slice(0, len);
|
|
565
|
-
const res = new Uint8Array(data.length + len);
|
|
566
|
-
res.set(data);
|
|
567
|
-
res.set(sum, data.length);
|
|
568
|
-
return res;
|
|
569
|
-
},
|
|
570
|
-
decode(data) {
|
|
571
|
-
if (!isBytes(data))
|
|
572
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
573
|
-
const payload = data.slice(0, -len);
|
|
574
|
-
const oldChecksum = data.slice(-len);
|
|
575
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
576
|
-
for (let i = 0; i < len; i++)
|
|
577
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
578
|
-
throw new Error("Invalid checksum");
|
|
579
|
-
return payload;
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
584
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
585
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
586
|
-
var base58check = createBase58check;
|
|
587
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
588
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
589
|
-
function bech32Polymod(pre) {
|
|
590
|
-
const b = pre >> 25;
|
|
591
|
-
let chk = (pre & 33554431) << 5;
|
|
592
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
593
|
-
if ((b >> i & 1) === 1)
|
|
594
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
595
|
-
}
|
|
596
|
-
return chk;
|
|
597
|
-
}
|
|
598
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
599
|
-
const len = prefix.length;
|
|
600
|
-
let chk = 1;
|
|
601
|
-
for (let i = 0; i < len; i++) {
|
|
602
|
-
const c = prefix.charCodeAt(i);
|
|
603
|
-
if (c < 33 || c > 126)
|
|
604
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
605
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
606
|
-
}
|
|
607
|
-
chk = bech32Polymod(chk);
|
|
608
|
-
for (let i = 0; i < len; i++)
|
|
609
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
610
|
-
for (let v of words)
|
|
611
|
-
chk = bech32Polymod(chk) ^ v;
|
|
612
|
-
for (let i = 0; i < 6; i++)
|
|
613
|
-
chk = bech32Polymod(chk);
|
|
614
|
-
chk ^= encodingConst;
|
|
615
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
616
|
-
}
|
|
617
|
-
// @__NO_SIDE_EFFECTS__
|
|
618
|
-
function genBech32(encoding) {
|
|
619
|
-
const ENCODING_CONST = 1 ;
|
|
620
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
621
|
-
const fromWords = _words.decode;
|
|
622
|
-
const toWords = _words.encode;
|
|
623
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
624
|
-
function encode(prefix, words, limit = 90) {
|
|
625
|
-
astr("bech32.encode prefix", prefix);
|
|
626
|
-
if (isBytes(words))
|
|
627
|
-
words = Array.from(words);
|
|
628
|
-
anumArr("bech32.encode", words);
|
|
629
|
-
const plen = prefix.length;
|
|
630
|
-
if (plen === 0)
|
|
631
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
632
|
-
const actualLength = plen + 7 + words.length;
|
|
633
|
-
if (limit !== false && actualLength > limit)
|
|
634
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
635
|
-
const lowered = prefix.toLowerCase();
|
|
636
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
637
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
638
|
-
}
|
|
639
|
-
function decode(str, limit = 90) {
|
|
640
|
-
astr("bech32.decode input", str);
|
|
641
|
-
const slen = str.length;
|
|
642
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
643
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
644
|
-
const lowered = str.toLowerCase();
|
|
645
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
646
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
647
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
648
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
649
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
650
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
651
|
-
const data = lowered.slice(sepIndex + 1);
|
|
652
|
-
if (data.length < 6)
|
|
653
|
-
throw new Error("Data must be at least 6 characters long");
|
|
654
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
655
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
656
|
-
if (!data.endsWith(sum))
|
|
657
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
658
|
-
return { prefix, words };
|
|
659
|
-
}
|
|
660
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
661
|
-
function decodeToBytes(str) {
|
|
662
|
-
const { prefix, words } = decode(str, false);
|
|
663
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
664
|
-
}
|
|
665
|
-
function encodeFromBytes(prefix, bytes) {
|
|
666
|
-
return encode(prefix, toWords(bytes));
|
|
667
|
-
}
|
|
668
|
-
return {
|
|
669
|
-
encode,
|
|
670
|
-
decode,
|
|
671
|
-
encodeFromBytes,
|
|
672
|
-
decodeToBytes,
|
|
673
|
-
decodeUnsafe,
|
|
674
|
-
fromWords,
|
|
675
|
-
fromWordsUnsafe,
|
|
676
|
-
toWords
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
680
|
-
|
|
681
|
-
// node_modules/@scure/bip32/index.js
|
|
682
|
-
var Point = secp256k1.Point;
|
|
683
|
-
var { Fn } = Point;
|
|
684
|
-
var base58check2 = createBase58check(sha256);
|
|
685
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
686
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
687
|
-
var HARDENED_OFFSET = 2147483648;
|
|
688
|
-
var hash160 = (data) => ripemd160$1(sha256(data));
|
|
689
|
-
var fromU32 = (data) => createView(data).getUint32(0, false);
|
|
690
|
-
var toU32 = (n) => {
|
|
691
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
692
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
693
|
-
}
|
|
694
|
-
const buf = new Uint8Array(4);
|
|
695
|
-
createView(buf).setUint32(0, n, false);
|
|
696
|
-
return buf;
|
|
697
|
-
};
|
|
698
|
-
var HDKey = class _HDKey {
|
|
699
|
-
get fingerprint() {
|
|
700
|
-
if (!this.pubHash) {
|
|
701
|
-
throw new Error("No publicKey set!");
|
|
702
|
-
}
|
|
703
|
-
return fromU32(this.pubHash);
|
|
704
|
-
}
|
|
705
|
-
get identifier() {
|
|
706
|
-
return this.pubHash;
|
|
707
|
-
}
|
|
708
|
-
get pubKeyHash() {
|
|
709
|
-
return this.pubHash;
|
|
710
|
-
}
|
|
711
|
-
get privateKey() {
|
|
712
|
-
return this._privateKey || null;
|
|
713
|
-
}
|
|
714
|
-
get publicKey() {
|
|
715
|
-
return this._publicKey || null;
|
|
716
|
-
}
|
|
717
|
-
get privateExtendedKey() {
|
|
718
|
-
const priv = this._privateKey;
|
|
719
|
-
if (!priv) {
|
|
720
|
-
throw new Error("No private key");
|
|
721
|
-
}
|
|
722
|
-
return base58check2.encode(this.serialize(this.versions.private, concatBytes(Uint8Array.of(0), priv)));
|
|
723
|
-
}
|
|
724
|
-
get publicExtendedKey() {
|
|
725
|
-
if (!this._publicKey) {
|
|
726
|
-
throw new Error("No public key");
|
|
727
|
-
}
|
|
728
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
729
|
-
}
|
|
730
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
731
|
-
abytes(seed);
|
|
732
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
733
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
734
|
-
}
|
|
735
|
-
const I = hmac(sha512, MASTER_SECRET, seed);
|
|
736
|
-
const privateKey = I.slice(0, 32);
|
|
737
|
-
const chainCode = I.slice(32);
|
|
738
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
739
|
-
}
|
|
740
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
741
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
742
|
-
const keyView = createView(keyBuffer);
|
|
743
|
-
const version = keyView.getUint32(0, false);
|
|
744
|
-
const opt = {
|
|
745
|
-
versions,
|
|
746
|
-
depth: keyBuffer[4],
|
|
747
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
748
|
-
index: keyView.getUint32(9, false),
|
|
749
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
750
|
-
};
|
|
751
|
-
const key = keyBuffer.slice(45);
|
|
752
|
-
const isPriv = key[0] === 0;
|
|
753
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
754
|
-
throw new Error("Version mismatch");
|
|
755
|
-
}
|
|
756
|
-
if (isPriv) {
|
|
757
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
758
|
-
} else {
|
|
759
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
static fromJSON(json) {
|
|
763
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
764
|
-
}
|
|
765
|
-
versions;
|
|
766
|
-
depth = 0;
|
|
767
|
-
index = 0;
|
|
768
|
-
chainCode = null;
|
|
769
|
-
parentFingerprint = 0;
|
|
770
|
-
_privateKey;
|
|
771
|
-
_publicKey;
|
|
772
|
-
pubHash;
|
|
773
|
-
constructor(opt) {
|
|
774
|
-
if (!opt || typeof opt !== "object") {
|
|
775
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
776
|
-
}
|
|
777
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
778
|
-
this.depth = opt.depth || 0;
|
|
779
|
-
this.chainCode = opt.chainCode || null;
|
|
780
|
-
this.index = opt.index || 0;
|
|
781
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
782
|
-
if (!this.depth) {
|
|
783
|
-
if (this.parentFingerprint || this.index) {
|
|
784
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
if (this.depth > 255) {
|
|
788
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
789
|
-
}
|
|
790
|
-
if (opt.publicKey && opt.privateKey) {
|
|
791
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
792
|
-
}
|
|
793
|
-
if (opt.privateKey) {
|
|
794
|
-
if (!secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
795
|
-
throw new Error("Invalid private key");
|
|
796
|
-
this._privateKey = opt.privateKey;
|
|
797
|
-
this._publicKey = secp256k1.getPublicKey(opt.privateKey, true);
|
|
798
|
-
} else if (opt.publicKey) {
|
|
799
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
800
|
-
} else {
|
|
801
|
-
throw new Error("HDKey: no public or private key provided");
|
|
802
|
-
}
|
|
803
|
-
this.pubHash = hash160(this._publicKey);
|
|
804
|
-
}
|
|
805
|
-
derive(path) {
|
|
806
|
-
if (!/^[mM]'?/.test(path)) {
|
|
807
|
-
throw new Error('Path must start with "m" or "M"');
|
|
808
|
-
}
|
|
809
|
-
if (/^[mM]'?$/.test(path)) {
|
|
810
|
-
return this;
|
|
811
|
-
}
|
|
812
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
813
|
-
let child = this;
|
|
814
|
-
for (const c of parts) {
|
|
815
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
816
|
-
const m1 = m && m[1];
|
|
817
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
818
|
-
throw new Error("invalid child index: " + c);
|
|
819
|
-
let idx = +m1;
|
|
820
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
821
|
-
throw new Error("Invalid index");
|
|
822
|
-
}
|
|
823
|
-
if (m[2] === "'") {
|
|
824
|
-
idx += HARDENED_OFFSET;
|
|
825
|
-
}
|
|
826
|
-
child = child.deriveChild(idx);
|
|
827
|
-
}
|
|
828
|
-
return child;
|
|
829
|
-
}
|
|
830
|
-
deriveChild(index) {
|
|
831
|
-
if (!this._publicKey || !this.chainCode) {
|
|
832
|
-
throw new Error("No publicKey or chainCode set");
|
|
833
|
-
}
|
|
834
|
-
let data = toU32(index);
|
|
835
|
-
if (index >= HARDENED_OFFSET) {
|
|
836
|
-
const priv = this._privateKey;
|
|
837
|
-
if (!priv) {
|
|
838
|
-
throw new Error("Could not derive hardened child key");
|
|
839
|
-
}
|
|
840
|
-
data = concatBytes(Uint8Array.of(0), priv, data);
|
|
841
|
-
} else {
|
|
842
|
-
data = concatBytes(this._publicKey, data);
|
|
843
|
-
}
|
|
844
|
-
const I = hmac(sha512, this.chainCode, data);
|
|
845
|
-
const childTweak = I.slice(0, 32);
|
|
846
|
-
const chainCode = I.slice(32);
|
|
847
|
-
if (!secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
848
|
-
throw new Error("Tweak bigger than curve order");
|
|
849
|
-
}
|
|
850
|
-
const opt = {
|
|
851
|
-
versions: this.versions,
|
|
852
|
-
chainCode,
|
|
853
|
-
depth: this.depth + 1,
|
|
854
|
-
parentFingerprint: this.fingerprint,
|
|
855
|
-
index
|
|
856
|
-
};
|
|
857
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
858
|
-
try {
|
|
859
|
-
if (this._privateKey) {
|
|
860
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
861
|
-
if (!Fn.isValidNot0(added)) {
|
|
862
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
863
|
-
}
|
|
864
|
-
opt.privateKey = Fn.toBytes(added);
|
|
865
|
-
} else {
|
|
866
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
867
|
-
if (added.equals(Point.ZERO)) {
|
|
868
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
869
|
-
}
|
|
870
|
-
opt.publicKey = added.toBytes(true);
|
|
871
|
-
}
|
|
872
|
-
return new _HDKey(opt);
|
|
873
|
-
} catch (err) {
|
|
874
|
-
return this.deriveChild(index + 1);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
sign(hash) {
|
|
878
|
-
if (!this._privateKey) {
|
|
879
|
-
throw new Error("No privateKey set!");
|
|
880
|
-
}
|
|
881
|
-
abytes(hash, 32);
|
|
882
|
-
return secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
883
|
-
}
|
|
884
|
-
verify(hash, signature) {
|
|
885
|
-
abytes(hash, 32);
|
|
886
|
-
abytes(signature, 64);
|
|
887
|
-
if (!this._publicKey) {
|
|
888
|
-
throw new Error("No publicKey set!");
|
|
889
|
-
}
|
|
890
|
-
return secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
891
|
-
}
|
|
892
|
-
wipePrivateData() {
|
|
893
|
-
if (this._privateKey) {
|
|
894
|
-
this._privateKey.fill(0);
|
|
895
|
-
this._privateKey = void 0;
|
|
896
|
-
}
|
|
897
|
-
return this;
|
|
898
|
-
}
|
|
899
|
-
toJSON() {
|
|
900
|
-
return {
|
|
901
|
-
xpriv: this.privateExtendedKey,
|
|
902
|
-
xpub: this.publicExtendedKey
|
|
903
|
-
};
|
|
904
|
-
}
|
|
905
|
-
serialize(version, key) {
|
|
906
|
-
if (!this.chainCode) {
|
|
907
|
-
throw new Error("No chainCode set");
|
|
908
|
-
}
|
|
909
|
-
abytes(key, 33);
|
|
910
|
-
return concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
327
|
var DERIVATION_PATHS2 = {
|
|
914
328
|
ethereum: "m/44'/60'/0'/0/0",
|
|
915
329
|
bitcoin_mainnet: "m/84'/0'/0'/0/0",
|
|
@@ -932,7 +346,7 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
932
346
|
if (!child.publicKey) {
|
|
933
347
|
throw new Error("Failed to derive public key");
|
|
934
348
|
}
|
|
935
|
-
const pubKeyHash = ripemd160(sha256
|
|
349
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
936
350
|
const witnessVersion = 0;
|
|
937
351
|
const words = bech32.toWords(pubKeyHash);
|
|
938
352
|
words.unshift(witnessVersion);
|
|
@@ -973,7 +387,7 @@ async function deriveTonAddress(seed) {
|
|
|
973
387
|
const publicKey = keypair.publicKey;
|
|
974
388
|
const workchain = 0;
|
|
975
389
|
const flags = 17;
|
|
976
|
-
const hash = sha256
|
|
390
|
+
const hash = sha256(publicKey);
|
|
977
391
|
const addressData = new Uint8Array(34);
|
|
978
392
|
addressData[0] = flags;
|
|
979
393
|
addressData[1] = workchain;
|
|
@@ -1010,7 +424,7 @@ function deriveTronAddress(seed) {
|
|
|
1010
424
|
for (let i = 0; i < 20; i++) {
|
|
1011
425
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1012
426
|
}
|
|
1013
|
-
const tronBase58check = base58check(sha256
|
|
427
|
+
const tronBase58check = base58check(sha256);
|
|
1014
428
|
return tronBase58check.encode(addressBytes);
|
|
1015
429
|
} catch (error) {
|
|
1016
430
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1025,7 +439,7 @@ function deriveSparkAddress(seed, network = "mainnet") {
|
|
|
1025
439
|
if (!child.publicKey) {
|
|
1026
440
|
throw new Error("Failed to derive public key");
|
|
1027
441
|
}
|
|
1028
|
-
const pubKeyHash = ripemd160(sha256
|
|
442
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
1029
443
|
const witnessVersion = 0;
|
|
1030
444
|
const words = bech32.toWords(pubKeyHash);
|
|
1031
445
|
words.unshift(witnessVersion);
|
|
@@ -1126,9 +540,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1126
540
|
"no route": "NETWORK_ERROR"
|
|
1127
541
|
}
|
|
1128
542
|
};
|
|
1129
|
-
function parseChainError(
|
|
543
|
+
function parseChainError(chain, errorMessage) {
|
|
1130
544
|
const errorLower = errorMessage.toLowerCase();
|
|
1131
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
545
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1132
546
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1133
547
|
if (errorLower.includes(pattern)) {
|
|
1134
548
|
return code;
|
|
@@ -1266,38 +680,38 @@ var ZubariWdkService = class {
|
|
|
1266
680
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1267
681
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1268
682
|
*/
|
|
1269
|
-
async deriveAddress(seed,
|
|
683
|
+
async deriveAddress(seed, chain) {
|
|
1270
684
|
await this.initialize();
|
|
1271
|
-
const path = this.getDerivationPath(
|
|
685
|
+
const path = this.getDerivationPath(chain);
|
|
1272
686
|
try {
|
|
1273
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
687
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1274
688
|
if (response.success && response.address) {
|
|
1275
689
|
return {
|
|
1276
|
-
chain
|
|
690
|
+
chain,
|
|
1277
691
|
address: response.address,
|
|
1278
692
|
path: response.path || path
|
|
1279
693
|
};
|
|
1280
694
|
}
|
|
1281
695
|
} catch (error) {
|
|
1282
|
-
console.warn(`API address derivation failed for ${
|
|
1283
|
-
if (
|
|
1284
|
-
return this.deriveBrowserAddress(seed,
|
|
696
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
697
|
+
if (chain === "ethereum") {
|
|
698
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1285
699
|
}
|
|
1286
700
|
}
|
|
1287
701
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1288
702
|
try {
|
|
1289
703
|
const wdk = this.nativeWdkService;
|
|
1290
704
|
await wdk.initialize(seed);
|
|
1291
|
-
return await wdk.deriveAddress(
|
|
705
|
+
return await wdk.deriveAddress(chain);
|
|
1292
706
|
} catch (error) {
|
|
1293
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
707
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1294
708
|
}
|
|
1295
709
|
}
|
|
1296
|
-
if (
|
|
1297
|
-
return this.deriveBrowserAddress(seed,
|
|
710
|
+
if (chain === "ethereum") {
|
|
711
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1298
712
|
}
|
|
1299
713
|
throw new Error(
|
|
1300
|
-
`WDK API required for ${
|
|
714
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1301
715
|
);
|
|
1302
716
|
}
|
|
1303
717
|
/**
|
|
@@ -1377,13 +791,13 @@ var ZubariWdkService = class {
|
|
|
1377
791
|
/**
|
|
1378
792
|
* Get fee rates for a chain
|
|
1379
793
|
*/
|
|
1380
|
-
async getFeeRates(seed,
|
|
794
|
+
async getFeeRates(seed, chain) {
|
|
1381
795
|
await this.initialize();
|
|
1382
796
|
try {
|
|
1383
797
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1384
798
|
method: "POST",
|
|
1385
799
|
headers: { "Content-Type": "application/json" },
|
|
1386
|
-
body: JSON.stringify({ seed, chain
|
|
800
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1387
801
|
});
|
|
1388
802
|
if (response.ok) {
|
|
1389
803
|
const data = await response.json();
|
|
@@ -1392,20 +806,20 @@ var ZubariWdkService = class {
|
|
|
1392
806
|
}
|
|
1393
807
|
}
|
|
1394
808
|
} catch (error) {
|
|
1395
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
809
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1396
810
|
}
|
|
1397
811
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1398
812
|
}
|
|
1399
813
|
/**
|
|
1400
814
|
* Estimate transaction fee
|
|
1401
815
|
*/
|
|
1402
|
-
async estimateFee(seed,
|
|
816
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1403
817
|
await this.initialize();
|
|
1404
818
|
try {
|
|
1405
819
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1406
820
|
method: "POST",
|
|
1407
821
|
headers: { "Content-Type": "application/json" },
|
|
1408
|
-
body: JSON.stringify({ seed, chain
|
|
822
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1409
823
|
});
|
|
1410
824
|
if (response.ok) {
|
|
1411
825
|
const data = await response.json();
|
|
@@ -1414,9 +828,9 @@ var ZubariWdkService = class {
|
|
|
1414
828
|
}
|
|
1415
829
|
}
|
|
1416
830
|
} catch (error) {
|
|
1417
|
-
console.warn(`Failed to estimate fee for ${
|
|
831
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1418
832
|
}
|
|
1419
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
833
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1420
834
|
}
|
|
1421
835
|
/**
|
|
1422
836
|
* Send a transaction on any supported chain
|
|
@@ -1427,10 +841,10 @@ var ZubariWdkService = class {
|
|
|
1427
841
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1428
842
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1429
843
|
*/
|
|
1430
|
-
async sendTransaction(seed,
|
|
844
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1431
845
|
await this.initialize();
|
|
1432
846
|
const startTime = Date.now();
|
|
1433
|
-
console.log(`[ZubariWdkService] Sending ${
|
|
847
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
1434
848
|
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1435
849
|
amount,
|
|
1436
850
|
network: this.config.network
|
|
@@ -1439,7 +853,7 @@ var ZubariWdkService = class {
|
|
|
1439
853
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1440
854
|
method: "POST",
|
|
1441
855
|
headers: { "Content-Type": "application/json" },
|
|
1442
|
-
body: JSON.stringify({ seed, chain
|
|
856
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1443
857
|
});
|
|
1444
858
|
const elapsed = Date.now() - startTime;
|
|
1445
859
|
if (response.ok) {
|
|
@@ -1449,22 +863,22 @@ var ZubariWdkService = class {
|
|
|
1449
863
|
txHash = txHash.hash;
|
|
1450
864
|
}
|
|
1451
865
|
if (txHash) {
|
|
1452
|
-
const isValid = this.validateTxHash(
|
|
866
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1453
867
|
if (!isValid) {
|
|
1454
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
868
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1455
869
|
}
|
|
1456
870
|
}
|
|
1457
|
-
console.log(`[ZubariWdkService] ${
|
|
871
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1458
872
|
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1459
873
|
elapsed: `${elapsed}ms`
|
|
1460
874
|
});
|
|
1461
875
|
if (!data.success) {
|
|
1462
|
-
const errorCode2 = parseChainError(
|
|
876
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1463
877
|
return {
|
|
1464
878
|
success: false,
|
|
1465
879
|
error: data.error,
|
|
1466
880
|
errorCode: errorCode2,
|
|
1467
|
-
chain
|
|
881
|
+
chain
|
|
1468
882
|
};
|
|
1469
883
|
}
|
|
1470
884
|
return {
|
|
@@ -1473,14 +887,14 @@ var ZubariWdkService = class {
|
|
|
1473
887
|
from: data.from,
|
|
1474
888
|
to: data.to,
|
|
1475
889
|
amount: data.amount,
|
|
1476
|
-
chain: data.chain ||
|
|
890
|
+
chain: data.chain || chain,
|
|
1477
891
|
network: data.network || this.config.network
|
|
1478
892
|
};
|
|
1479
893
|
}
|
|
1480
894
|
const errorData = await response.json().catch(() => ({}));
|
|
1481
895
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1482
|
-
const errorCode = parseChainError(
|
|
1483
|
-
console.error(`[ZubariWdkService] ${
|
|
896
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
897
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
1484
898
|
status: response.status,
|
|
1485
899
|
error: errorMessage,
|
|
1486
900
|
errorCode,
|
|
@@ -1490,13 +904,13 @@ var ZubariWdkService = class {
|
|
|
1490
904
|
success: false,
|
|
1491
905
|
error: errorMessage,
|
|
1492
906
|
errorCode,
|
|
1493
|
-
chain
|
|
907
|
+
chain
|
|
1494
908
|
};
|
|
1495
909
|
} catch (error) {
|
|
1496
910
|
const elapsed = Date.now() - startTime;
|
|
1497
911
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1498
|
-
const errorCode = parseChainError(
|
|
1499
|
-
console.error(`[ZubariWdkService] ${
|
|
912
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
913
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
1500
914
|
error: errorMessage,
|
|
1501
915
|
errorCode,
|
|
1502
916
|
elapsed: `${elapsed}ms`
|
|
@@ -1505,15 +919,15 @@ var ZubariWdkService = class {
|
|
|
1505
919
|
success: false,
|
|
1506
920
|
error: errorMessage,
|
|
1507
921
|
errorCode,
|
|
1508
|
-
chain
|
|
922
|
+
chain
|
|
1509
923
|
};
|
|
1510
924
|
}
|
|
1511
925
|
}
|
|
1512
926
|
/**
|
|
1513
927
|
* Validate transaction hash format for a specific chain
|
|
1514
928
|
*/
|
|
1515
|
-
validateTxHash(
|
|
1516
|
-
switch (
|
|
929
|
+
validateTxHash(chain, txHash) {
|
|
930
|
+
switch (chain) {
|
|
1517
931
|
case "ethereum":
|
|
1518
932
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1519
933
|
case "bitcoin":
|
|
@@ -1545,7 +959,7 @@ var ZubariWdkService = class {
|
|
|
1545
959
|
// ==========================================
|
|
1546
960
|
// Private Helper Methods
|
|
1547
961
|
// ==========================================
|
|
1548
|
-
getDerivationPath(
|
|
962
|
+
getDerivationPath(chain) {
|
|
1549
963
|
const paths = {
|
|
1550
964
|
bitcoin: this.config.network === "testnet" ? "m/84'/1'/0'/0/0" : "m/84'/0'/0'/0/0",
|
|
1551
965
|
ethereum: "m/44'/60'/0'/0/0",
|
|
@@ -1554,9 +968,9 @@ var ZubariWdkService = class {
|
|
|
1554
968
|
solana: "m/44'/501'/0'/0'",
|
|
1555
969
|
spark: "m/44'/998'/0'/0/0"
|
|
1556
970
|
};
|
|
1557
|
-
return paths[
|
|
971
|
+
return paths[chain];
|
|
1558
972
|
}
|
|
1559
|
-
getChainSymbol(
|
|
973
|
+
getChainSymbol(chain) {
|
|
1560
974
|
const symbols = {
|
|
1561
975
|
ethereum: "ETH",
|
|
1562
976
|
bitcoin: "BTC",
|
|
@@ -1565,16 +979,16 @@ var ZubariWdkService = class {
|
|
|
1565
979
|
solana: "SOL",
|
|
1566
980
|
spark: "SAT"
|
|
1567
981
|
};
|
|
1568
|
-
return symbols[
|
|
982
|
+
return symbols[chain];
|
|
1569
983
|
}
|
|
1570
984
|
/**
|
|
1571
985
|
* Derive address using browser-compatible libraries
|
|
1572
986
|
*/
|
|
1573
|
-
async deriveBrowserAddress(seed,
|
|
1574
|
-
const path = this.getDerivationPath(
|
|
987
|
+
async deriveBrowserAddress(seed, chain) {
|
|
988
|
+
const path = this.getDerivationPath(chain);
|
|
1575
989
|
try {
|
|
1576
990
|
let address;
|
|
1577
|
-
switch (
|
|
991
|
+
switch (chain) {
|
|
1578
992
|
case "ethereum":
|
|
1579
993
|
address = deriveEthereumAddress(seed);
|
|
1580
994
|
break;
|
|
@@ -1594,11 +1008,11 @@ var ZubariWdkService = class {
|
|
|
1594
1008
|
address = await deriveTonAddress(seed);
|
|
1595
1009
|
break;
|
|
1596
1010
|
default:
|
|
1597
|
-
throw new Error(`Unsupported chain: ${
|
|
1011
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1598
1012
|
}
|
|
1599
|
-
return { chain
|
|
1013
|
+
return { chain, address, path };
|
|
1600
1014
|
} catch (error) {
|
|
1601
|
-
console.error(`Browser derivation failed for ${
|
|
1015
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1602
1016
|
throw error;
|
|
1603
1017
|
}
|
|
1604
1018
|
}
|
|
@@ -1611,7 +1025,7 @@ var ZubariWdkService = class {
|
|
|
1611
1025
|
};
|
|
1612
1026
|
var defaultService = null;
|
|
1613
1027
|
function getZubariWdkService(config) {
|
|
1614
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1028
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1615
1029
|
defaultService = new ZubariWdkService(config);
|
|
1616
1030
|
}
|
|
1617
1031
|
return defaultService;
|
|
@@ -2000,8 +1414,8 @@ async function fetchPrices() {
|
|
|
2000
1414
|
if (response.ok) {
|
|
2001
1415
|
const data = await response.json();
|
|
2002
1416
|
const prices = {};
|
|
2003
|
-
for (const [
|
|
2004
|
-
prices[
|
|
1417
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1418
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2005
1419
|
}
|
|
2006
1420
|
priceCache = { prices, timestamp: Date.now() };
|
|
2007
1421
|
return prices;
|
|
@@ -2011,9 +1425,22 @@ async function fetchPrices() {
|
|
|
2011
1425
|
}
|
|
2012
1426
|
return priceCache?.prices || {};
|
|
2013
1427
|
}
|
|
2014
|
-
async function getPriceForChain(
|
|
1428
|
+
async function getPriceForChain(chain) {
|
|
2015
1429
|
const prices = await fetchPrices();
|
|
2016
|
-
return prices[
|
|
1430
|
+
return prices[chain] || 0;
|
|
1431
|
+
}
|
|
1432
|
+
function tonFriendlyToRaw(addr) {
|
|
1433
|
+
if (addr.includes(":")) return addr;
|
|
1434
|
+
try {
|
|
1435
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1436
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1437
|
+
if (bytes.length !== 36) return addr;
|
|
1438
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1439
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1440
|
+
return `${workchain}:${hash}`;
|
|
1441
|
+
} catch {
|
|
1442
|
+
return addr;
|
|
1443
|
+
}
|
|
2017
1444
|
}
|
|
2018
1445
|
var STORAGE_KEYS = {
|
|
2019
1446
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2219,9 +1646,9 @@ var WalletManager = class _WalletManager {
|
|
|
2219
1646
|
if (!this.derivedAddress) {
|
|
2220
1647
|
throw new Error("Wallet not initialized");
|
|
2221
1648
|
}
|
|
2222
|
-
const
|
|
1649
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2223
1650
|
const client = createPublicClient({
|
|
2224
|
-
chain
|
|
1651
|
+
chain,
|
|
2225
1652
|
transport: http(this.config.rpcUrl, {
|
|
2226
1653
|
timeout: 15e3,
|
|
2227
1654
|
// 15 second timeout
|
|
@@ -2243,9 +1670,9 @@ var WalletManager = class _WalletManager {
|
|
|
2243
1670
|
* Create viem public client for the current network
|
|
2244
1671
|
*/
|
|
2245
1672
|
getPublicClient() {
|
|
2246
|
-
const
|
|
1673
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2247
1674
|
return createPublicClient({
|
|
2248
|
-
chain
|
|
1675
|
+
chain,
|
|
2249
1676
|
transport: http(this.config.rpcUrl, {
|
|
2250
1677
|
timeout: 15e3,
|
|
2251
1678
|
// 15 second timeout
|
|
@@ -2299,11 +1726,11 @@ var WalletManager = class _WalletManager {
|
|
|
2299
1726
|
*
|
|
2300
1727
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2301
1728
|
*/
|
|
2302
|
-
static async deriveAddressForChainAsync(seed,
|
|
2303
|
-
if (
|
|
1729
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
1730
|
+
if (chain === "ethereum") {
|
|
2304
1731
|
try {
|
|
2305
1732
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2306
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
1733
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2307
1734
|
return result2.address;
|
|
2308
1735
|
} catch (error) {
|
|
2309
1736
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2311,7 +1738,7 @@ var WalletManager = class _WalletManager {
|
|
|
2311
1738
|
}
|
|
2312
1739
|
}
|
|
2313
1740
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2314
|
-
const result = await wdkService.deriveAddress(seed,
|
|
1741
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2315
1742
|
return result.address;
|
|
2316
1743
|
}
|
|
2317
1744
|
/**
|
|
@@ -2320,14 +1747,14 @@ var WalletManager = class _WalletManager {
|
|
|
2320
1747
|
*
|
|
2321
1748
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2322
1749
|
*/
|
|
2323
|
-
static deriveAddressForChain(seed,
|
|
2324
|
-
if (
|
|
1750
|
+
static deriveAddressForChain(seed, chain) {
|
|
1751
|
+
if (chain === "ethereum") {
|
|
2325
1752
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2326
1753
|
const ethNode = HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2327
1754
|
return ethNode.address;
|
|
2328
1755
|
}
|
|
2329
1756
|
throw new Error(
|
|
2330
|
-
`Sync derivation not supported for ${
|
|
1757
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2331
1758
|
);
|
|
2332
1759
|
}
|
|
2333
1760
|
/**
|
|
@@ -2359,9 +1786,9 @@ var WalletManager = class _WalletManager {
|
|
|
2359
1786
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2360
1787
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2361
1788
|
const addresses = {};
|
|
2362
|
-
for (const [
|
|
2363
|
-
if (enabledChainsSet.has(
|
|
2364
|
-
addresses[
|
|
1789
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
1790
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
1791
|
+
addresses[chain] = address;
|
|
2365
1792
|
}
|
|
2366
1793
|
}
|
|
2367
1794
|
this.derivedAddresses = addresses;
|
|
@@ -2402,10 +1829,10 @@ var WalletManager = class _WalletManager {
|
|
|
2402
1829
|
*/
|
|
2403
1830
|
normalizeAddresses(addresses) {
|
|
2404
1831
|
const normalized = {};
|
|
2405
|
-
for (const [
|
|
1832
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2406
1833
|
const addr = this.normalizeAddress(value);
|
|
2407
1834
|
if (addr) {
|
|
2408
|
-
normalized[
|
|
1835
|
+
normalized[chain] = addr;
|
|
2409
1836
|
}
|
|
2410
1837
|
}
|
|
2411
1838
|
return normalized;
|
|
@@ -2458,20 +1885,20 @@ var WalletManager = class _WalletManager {
|
|
|
2458
1885
|
* Get address for a specific chain
|
|
2459
1886
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
2460
1887
|
*/
|
|
2461
|
-
getAddressForChain(
|
|
2462
|
-
const cachedValue = this.derivedAddresses[
|
|
1888
|
+
getAddressForChain(chain) {
|
|
1889
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
2463
1890
|
if (cachedValue) {
|
|
2464
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
1891
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
2465
1892
|
const addr = this.normalizeAddress(cachedValue);
|
|
2466
|
-
console.log(`[WalletManager] getAddressForChain(${
|
|
1893
|
+
console.log(`[WalletManager] getAddressForChain(${chain}) normalized:`, addr);
|
|
2467
1894
|
if (addr) {
|
|
2468
|
-
this.derivedAddresses[
|
|
1895
|
+
this.derivedAddresses[chain] = addr;
|
|
2469
1896
|
return addr;
|
|
2470
1897
|
}
|
|
2471
1898
|
}
|
|
2472
|
-
if (
|
|
2473
|
-
this.derivedAddresses[
|
|
2474
|
-
return this.derivedAddresses[
|
|
1899
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
1900
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
1901
|
+
return this.derivedAddresses[chain];
|
|
2475
1902
|
}
|
|
2476
1903
|
return null;
|
|
2477
1904
|
}
|
|
@@ -2484,11 +1911,11 @@ var WalletManager = class _WalletManager {
|
|
|
2484
1911
|
/**
|
|
2485
1912
|
* Set the selected chain
|
|
2486
1913
|
*/
|
|
2487
|
-
setSelectedChain(
|
|
2488
|
-
if (!this.config.enabledChains.includes(
|
|
2489
|
-
throw new Error(`Chain ${
|
|
1914
|
+
setSelectedChain(chain) {
|
|
1915
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
1916
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
2490
1917
|
}
|
|
2491
|
-
this.selectedChain =
|
|
1918
|
+
this.selectedChain = chain;
|
|
2492
1919
|
}
|
|
2493
1920
|
/**
|
|
2494
1921
|
* Get the currently selected chain
|
|
@@ -2505,22 +1932,22 @@ var WalletManager = class _WalletManager {
|
|
|
2505
1932
|
/**
|
|
2506
1933
|
* Get chain configuration
|
|
2507
1934
|
*/
|
|
2508
|
-
getChainConfig(
|
|
2509
|
-
return getNetworkConfig(
|
|
1935
|
+
getChainConfig(chain) {
|
|
1936
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
2510
1937
|
}
|
|
2511
1938
|
/**
|
|
2512
1939
|
* Fetch balance for a specific chain
|
|
2513
1940
|
* Note: Currently only Ethereum is implemented
|
|
2514
1941
|
*/
|
|
2515
|
-
async fetchBalanceForChain(
|
|
2516
|
-
const address = this.getAddressForChain(
|
|
1942
|
+
async fetchBalanceForChain(chain) {
|
|
1943
|
+
const address = this.getAddressForChain(chain);
|
|
2517
1944
|
if (!address) {
|
|
2518
|
-
throw new Error(`No address for chain ${
|
|
1945
|
+
throw new Error(`No address for chain ${chain}`);
|
|
2519
1946
|
}
|
|
2520
|
-
const networkConfig = this.getChainConfig(
|
|
1947
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2521
1948
|
let balance = "0";
|
|
2522
1949
|
const tokenBalances = {};
|
|
2523
|
-
if (
|
|
1950
|
+
if (chain === "ethereum") {
|
|
2524
1951
|
const viemChain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2525
1952
|
const isTestnet = this.config.network !== "mainnet";
|
|
2526
1953
|
const client = createPublicClient({
|
|
@@ -2567,7 +1994,7 @@ var WalletManager = class _WalletManager {
|
|
|
2567
1994
|
} else if (usdtResult.status === "rejected") {
|
|
2568
1995
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
2569
1996
|
}
|
|
2570
|
-
} else if (
|
|
1997
|
+
} else if (chain === "bitcoin") {
|
|
2571
1998
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
2572
1999
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
2573
2000
|
"https://mempool.space/testnet/api",
|
|
@@ -2599,7 +2026,7 @@ var WalletManager = class _WalletManager {
|
|
|
2599
2026
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
2600
2027
|
}
|
|
2601
2028
|
}
|
|
2602
|
-
} else if (
|
|
2029
|
+
} else if (chain === "solana") {
|
|
2603
2030
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
2604
2031
|
try {
|
|
2605
2032
|
const response = await fetch(rpcUrl, {
|
|
@@ -2619,7 +2046,7 @@ var WalletManager = class _WalletManager {
|
|
|
2619
2046
|
}
|
|
2620
2047
|
}
|
|
2621
2048
|
} catch (error) {
|
|
2622
|
-
console.warn(`Failed to fetch ${
|
|
2049
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2623
2050
|
}
|
|
2624
2051
|
const isTestnet = this.config.network !== "mainnet";
|
|
2625
2052
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -2653,7 +2080,7 @@ var WalletManager = class _WalletManager {
|
|
|
2653
2080
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
2654
2081
|
}
|
|
2655
2082
|
}
|
|
2656
|
-
} else if (
|
|
2083
|
+
} else if (chain === "tron") {
|
|
2657
2084
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
2658
2085
|
const baseUrl = tronConfig.rpcUrl;
|
|
2659
2086
|
try {
|
|
@@ -2682,9 +2109,9 @@ var WalletManager = class _WalletManager {
|
|
|
2682
2109
|
}
|
|
2683
2110
|
}
|
|
2684
2111
|
} catch (error) {
|
|
2685
|
-
console.warn(`Failed to fetch ${
|
|
2112
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2686
2113
|
}
|
|
2687
|
-
} else if (
|
|
2114
|
+
} else if (chain === "ton") {
|
|
2688
2115
|
const isTestnet = this.config.network !== "mainnet";
|
|
2689
2116
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
2690
2117
|
try {
|
|
@@ -2700,25 +2127,36 @@ var WalletManager = class _WalletManager {
|
|
|
2700
2127
|
}
|
|
2701
2128
|
}
|
|
2702
2129
|
} catch (error) {
|
|
2703
|
-
console.warn(`Failed to fetch ${
|
|
2130
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2704
2131
|
}
|
|
2705
2132
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
2706
2133
|
if (usdtJetton) {
|
|
2707
|
-
const
|
|
2134
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
2708
2135
|
try {
|
|
2136
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
2709
2137
|
const jettonResponse = await fetch(
|
|
2710
|
-
`${
|
|
2138
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
2711
2139
|
{ headers: { "Accept": "application/json" } }
|
|
2712
2140
|
);
|
|
2713
2141
|
if (jettonResponse.ok) {
|
|
2714
2142
|
const jettonData = await jettonResponse.json();
|
|
2715
|
-
const
|
|
2716
|
-
if (
|
|
2717
|
-
const
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2143
|
+
const balances = jettonData.balances;
|
|
2144
|
+
if (balances && balances.length > 0) {
|
|
2145
|
+
for (const jb of balances) {
|
|
2146
|
+
const jettonAddr = jb.jetton?.address;
|
|
2147
|
+
if (jettonAddr) {
|
|
2148
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2149
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2150
|
+
const rawBalance = jb.balance;
|
|
2151
|
+
if (rawBalance) {
|
|
2152
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2153
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2154
|
+
if (usdtAmount > 0) {
|
|
2155
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
break;
|
|
2159
|
+
}
|
|
2722
2160
|
}
|
|
2723
2161
|
}
|
|
2724
2162
|
}
|
|
@@ -2727,7 +2165,7 @@ var WalletManager = class _WalletManager {
|
|
|
2727
2165
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
2728
2166
|
}
|
|
2729
2167
|
}
|
|
2730
|
-
} else if (
|
|
2168
|
+
} else if (chain === "spark") {
|
|
2731
2169
|
try {
|
|
2732
2170
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
2733
2171
|
method: "POST",
|
|
@@ -2746,14 +2184,14 @@ var WalletManager = class _WalletManager {
|
|
|
2746
2184
|
}
|
|
2747
2185
|
}
|
|
2748
2186
|
} catch (error) {
|
|
2749
|
-
console.warn(`Failed to fetch ${
|
|
2187
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2750
2188
|
}
|
|
2751
2189
|
}
|
|
2752
|
-
const priceUsd = await getPriceForChain(
|
|
2190
|
+
const priceUsd = await getPriceForChain(chain);
|
|
2753
2191
|
const balanceNum = parseFloat(balance) || 0;
|
|
2754
2192
|
const balanceUsd = balanceNum * priceUsd;
|
|
2755
2193
|
return {
|
|
2756
|
-
chain
|
|
2194
|
+
chain,
|
|
2757
2195
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
2758
2196
|
balance,
|
|
2759
2197
|
balanceUsd,
|
|
@@ -2767,19 +2205,19 @@ var WalletManager = class _WalletManager {
|
|
|
2767
2205
|
*/
|
|
2768
2206
|
async fetchAllBalances() {
|
|
2769
2207
|
const balances = [];
|
|
2770
|
-
for (const
|
|
2208
|
+
for (const chain of this.config.enabledChains) {
|
|
2771
2209
|
try {
|
|
2772
|
-
const balance = await this.fetchBalanceForChain(
|
|
2210
|
+
const balance = await this.fetchBalanceForChain(chain);
|
|
2773
2211
|
balances.push(balance);
|
|
2774
2212
|
} catch (error) {
|
|
2775
|
-
console.error(`Failed to fetch balance for ${
|
|
2776
|
-
const networkConfig = this.getChainConfig(
|
|
2213
|
+
console.error(`Failed to fetch balance for ${chain}:`, error);
|
|
2214
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2777
2215
|
balances.push({
|
|
2778
|
-
chain
|
|
2216
|
+
chain,
|
|
2779
2217
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
2780
2218
|
balance: "0",
|
|
2781
2219
|
balanceUsd: 0,
|
|
2782
|
-
address: this.getAddressForChain(
|
|
2220
|
+
address: this.getAddressForChain(chain) || "",
|
|
2783
2221
|
decimals: networkConfig.nativeCurrency.decimals
|
|
2784
2222
|
});
|
|
2785
2223
|
}
|
|
@@ -2809,13 +2247,13 @@ var WalletManager = class _WalletManager {
|
|
|
2809
2247
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
2810
2248
|
* @returns Transaction result with hash and status
|
|
2811
2249
|
*/
|
|
2812
|
-
async sendTransaction(
|
|
2250
|
+
async sendTransaction(chain, to, amount, token) {
|
|
2813
2251
|
if (!this.currentSeed) {
|
|
2814
2252
|
return { success: false, error: "Wallet is locked" };
|
|
2815
2253
|
}
|
|
2816
|
-
const fromAddress = this.getAddressForChain(
|
|
2254
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
2817
2255
|
if (!fromAddress) {
|
|
2818
|
-
return { success: false, error: `No address for chain ${
|
|
2256
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
2819
2257
|
}
|
|
2820
2258
|
try {
|
|
2821
2259
|
const headers = {
|
|
@@ -2829,7 +2267,7 @@ var WalletManager = class _WalletManager {
|
|
|
2829
2267
|
headers,
|
|
2830
2268
|
body: JSON.stringify({
|
|
2831
2269
|
seed: this.currentSeed,
|
|
2832
|
-
chain
|
|
2270
|
+
chain,
|
|
2833
2271
|
to,
|
|
2834
2272
|
amount,
|
|
2835
2273
|
token,
|
|
@@ -2838,12 +2276,12 @@ var WalletManager = class _WalletManager {
|
|
|
2838
2276
|
});
|
|
2839
2277
|
if (response.ok) {
|
|
2840
2278
|
const data = await response.json();
|
|
2841
|
-
console.log(`Transaction sent on ${
|
|
2279
|
+
console.log(`Transaction sent on ${chain}:`, data);
|
|
2842
2280
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
2843
2281
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
2844
2282
|
txHash = txHash.hash;
|
|
2845
2283
|
}
|
|
2846
|
-
if (
|
|
2284
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
2847
2285
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
2848
2286
|
}
|
|
2849
2287
|
return {
|
|
@@ -2852,7 +2290,7 @@ var WalletManager = class _WalletManager {
|
|
|
2852
2290
|
from: fromAddress,
|
|
2853
2291
|
to,
|
|
2854
2292
|
amount,
|
|
2855
|
-
chain
|
|
2293
|
+
chain
|
|
2856
2294
|
};
|
|
2857
2295
|
}
|
|
2858
2296
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -2861,7 +2299,7 @@ var WalletManager = class _WalletManager {
|
|
|
2861
2299
|
error: errorData.error || `HTTP ${response.status}`
|
|
2862
2300
|
};
|
|
2863
2301
|
} catch (error) {
|
|
2864
|
-
console.error(`Transaction failed on ${
|
|
2302
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
2865
2303
|
return {
|
|
2866
2304
|
success: false,
|
|
2867
2305
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -2871,7 +2309,7 @@ var WalletManager = class _WalletManager {
|
|
|
2871
2309
|
/**
|
|
2872
2310
|
* Estimate transaction fee using Tether WDK
|
|
2873
2311
|
*/
|
|
2874
|
-
async estimateFee(
|
|
2312
|
+
async estimateFee(chain, to, amount, token) {
|
|
2875
2313
|
try {
|
|
2876
2314
|
const headers = {
|
|
2877
2315
|
"Content-Type": "application/json"
|
|
@@ -2883,7 +2321,7 @@ var WalletManager = class _WalletManager {
|
|
|
2883
2321
|
method: "POST",
|
|
2884
2322
|
headers,
|
|
2885
2323
|
body: JSON.stringify({
|
|
2886
|
-
chain
|
|
2324
|
+
chain,
|
|
2887
2325
|
to,
|
|
2888
2326
|
amount,
|
|
2889
2327
|
token,
|
|
@@ -3092,12 +2530,12 @@ function useWalletManager(options = {}) {
|
|
|
3092
2530
|
setIsLoading(false);
|
|
3093
2531
|
}
|
|
3094
2532
|
}, [manager]);
|
|
3095
|
-
const setSelectedChain = useCallback((
|
|
3096
|
-
manager.setSelectedChain(
|
|
3097
|
-
setSelectedChainState(
|
|
2533
|
+
const setSelectedChain = useCallback((chain) => {
|
|
2534
|
+
manager.setSelectedChain(chain);
|
|
2535
|
+
setSelectedChainState(chain);
|
|
3098
2536
|
}, [manager]);
|
|
3099
2537
|
const getAddressForChain = useCallback(
|
|
3100
|
-
(
|
|
2538
|
+
(chain) => manager.getAddressForChain(chain),
|
|
3101
2539
|
[manager]
|
|
3102
2540
|
);
|
|
3103
2541
|
const getAllAddresses = useCallback(
|
|
@@ -3107,10 +2545,10 @@ function useWalletManager(options = {}) {
|
|
|
3107
2545
|
const hasWallet = useCallback(() => manager.hasWallet(), [manager]);
|
|
3108
2546
|
const getSeed = useCallback(() => manager.getSeed(), [manager]);
|
|
3109
2547
|
const sendTransaction = useCallback(
|
|
3110
|
-
async (
|
|
2548
|
+
async (chain, to, amount, token) => {
|
|
3111
2549
|
setIsLoading(true);
|
|
3112
2550
|
try {
|
|
3113
|
-
const result = await manager.sendTransaction(
|
|
2551
|
+
const result = await manager.sendTransaction(chain, to, amount, token);
|
|
3114
2552
|
if (result.success) {
|
|
3115
2553
|
try {
|
|
3116
2554
|
const balances = await manager.fetchAllBalances();
|
|
@@ -3127,8 +2565,8 @@ function useWalletManager(options = {}) {
|
|
|
3127
2565
|
[manager]
|
|
3128
2566
|
);
|
|
3129
2567
|
const estimateFee = useCallback(
|
|
3130
|
-
async (
|
|
3131
|
-
return manager.estimateFee(
|
|
2568
|
+
async (chain, to, amount, token) => {
|
|
2569
|
+
return manager.estimateFee(chain, to, amount, token);
|
|
3132
2570
|
},
|
|
3133
2571
|
[manager]
|
|
3134
2572
|
);
|
|
@@ -3162,14 +2600,6 @@ function useWalletManager(options = {}) {
|
|
|
3162
2600
|
manager
|
|
3163
2601
|
};
|
|
3164
2602
|
}
|
|
3165
|
-
/*! Bundled license information:
|
|
3166
|
-
|
|
3167
|
-
@scure/base/index.js:
|
|
3168
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3169
|
-
|
|
3170
|
-
@scure/bip32/index.js:
|
|
3171
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
3172
|
-
*/
|
|
3173
2603
|
|
|
3174
2604
|
export { SUPPORTED_CHAINS, useWalletManager };
|
|
3175
2605
|
//# sourceMappingURL=index.mjs.map
|