@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/wallet/index.mjs
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { Wallet, HDNodeWallet } from 'ethers';
|
|
2
2
|
import { generateMnemonic, validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';
|
|
3
3
|
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
8
|
-
import { createView, concatBytes, abytes } from '@noble/hashes/utils.js';
|
|
9
|
-
import { sha256 as sha256$1 } from '@noble/hashes/sha256';
|
|
4
|
+
import { HDKey } from '@scure/bip32';
|
|
5
|
+
import { bech32, base58check } from '@scure/base';
|
|
6
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
10
7
|
import { ripemd160 } from '@noble/hashes/ripemd160';
|
|
11
8
|
import { createPublicClient, http, formatEther, getAddress } from 'viem';
|
|
12
9
|
import { mainnet, sepolia } from 'viem/chains';
|
|
@@ -132,8 +129,8 @@ var TESTNET_NETWORKS = {
|
|
|
132
129
|
var USDT_ADDRESSES = {
|
|
133
130
|
ethereum: {
|
|
134
131
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
135
|
-
testnet: "
|
|
136
|
-
// Sepolia
|
|
132
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
133
|
+
// Sepolia (Test Tether USD)
|
|
137
134
|
},
|
|
138
135
|
tron: {
|
|
139
136
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -151,11 +148,11 @@ var USDT_ADDRESSES = {
|
|
|
151
148
|
}
|
|
152
149
|
};
|
|
153
150
|
var DERIVATION_PATHS = {
|
|
154
|
-
bitcoin: "m/
|
|
151
|
+
bitcoin: "m/84'/0'/0'/0",
|
|
155
152
|
ethereum: "m/44'/60'/0'/0",
|
|
156
|
-
ton: "m/44'/607'/0'
|
|
153
|
+
ton: "m/44'/607'/0'",
|
|
157
154
|
tron: "m/44'/195'/0'/0",
|
|
158
|
-
solana: "m/44'/501'/0'
|
|
155
|
+
solana: "m/44'/501'/0'",
|
|
159
156
|
spark: "m/44'/998'/0'/0"
|
|
160
157
|
};
|
|
161
158
|
function getNetworkConfig(network, isTestnet = false) {
|
|
@@ -233,8 +230,27 @@ var WdkApiClient = class {
|
|
|
233
230
|
constructor(config) {
|
|
234
231
|
this.config = {
|
|
235
232
|
baseUrl: config.baseUrl,
|
|
236
|
-
timeout: config.timeout || 3e4
|
|
233
|
+
timeout: config.timeout || 3e4,
|
|
234
|
+
authToken: config.authToken
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Set or update the auth token for authenticated requests
|
|
239
|
+
*/
|
|
240
|
+
setAuthToken(token) {
|
|
241
|
+
this.config.authToken = token;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Build headers for API requests, including Authorization when available
|
|
245
|
+
*/
|
|
246
|
+
getHeaders() {
|
|
247
|
+
const headers = {
|
|
248
|
+
"Content-Type": "application/json"
|
|
237
249
|
};
|
|
250
|
+
if (this.config.authToken) {
|
|
251
|
+
headers["Authorization"] = `Bearer ${this.config.authToken}`;
|
|
252
|
+
}
|
|
253
|
+
return headers;
|
|
238
254
|
}
|
|
239
255
|
/**
|
|
240
256
|
* Generate a new BIP-39 seed phrase using Tether WDK
|
|
@@ -243,9 +259,7 @@ var WdkApiClient = class {
|
|
|
243
259
|
try {
|
|
244
260
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
|
|
245
261
|
method: "POST",
|
|
246
|
-
headers:
|
|
247
|
-
"Content-Type": "application/json"
|
|
248
|
-
}
|
|
262
|
+
headers: this.getHeaders()
|
|
249
263
|
});
|
|
250
264
|
return await response.json();
|
|
251
265
|
} catch (error) {
|
|
@@ -262,9 +276,7 @@ var WdkApiClient = class {
|
|
|
262
276
|
try {
|
|
263
277
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
|
|
264
278
|
method: "POST",
|
|
265
|
-
headers:
|
|
266
|
-
"Content-Type": "application/json"
|
|
267
|
-
},
|
|
279
|
+
headers: this.getHeaders(),
|
|
268
280
|
body: JSON.stringify({ seed })
|
|
269
281
|
});
|
|
270
282
|
return await response.json();
|
|
@@ -278,14 +290,12 @@ var WdkApiClient = class {
|
|
|
278
290
|
/**
|
|
279
291
|
* Derive address for a specific chain using Tether WDK
|
|
280
292
|
*/
|
|
281
|
-
async deriveAddress(seed,
|
|
293
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
282
294
|
try {
|
|
283
295
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
284
296
|
method: "POST",
|
|
285
|
-
headers:
|
|
286
|
-
|
|
287
|
-
},
|
|
288
|
-
body: JSON.stringify({ seed, chain: chain2, network })
|
|
297
|
+
headers: this.getHeaders(),
|
|
298
|
+
body: JSON.stringify({ seed, chain, network })
|
|
289
299
|
});
|
|
290
300
|
return await response.json();
|
|
291
301
|
} catch (error) {
|
|
@@ -302,9 +312,7 @@ var WdkApiClient = class {
|
|
|
302
312
|
try {
|
|
303
313
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
|
|
304
314
|
method: "POST",
|
|
305
|
-
headers:
|
|
306
|
-
"Content-Type": "application/json"
|
|
307
|
-
},
|
|
315
|
+
headers: this.getHeaders(),
|
|
308
316
|
body: JSON.stringify({ seed, network })
|
|
309
317
|
});
|
|
310
318
|
return await response.json();
|
|
@@ -318,14 +326,12 @@ var WdkApiClient = class {
|
|
|
318
326
|
/**
|
|
319
327
|
* Send a transaction on a specific chain using Tether WDK
|
|
320
328
|
*/
|
|
321
|
-
async sendTransaction(seed,
|
|
329
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
322
330
|
try {
|
|
323
331
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
324
332
|
method: "POST",
|
|
325
|
-
headers:
|
|
326
|
-
|
|
327
|
-
},
|
|
328
|
-
body: JSON.stringify({ seed, chain: chain2, to, amount, network })
|
|
333
|
+
headers: this.getHeaders(),
|
|
334
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
329
335
|
});
|
|
330
336
|
return await response.json();
|
|
331
337
|
} catch (error) {
|
|
@@ -339,14 +345,12 @@ var WdkApiClient = class {
|
|
|
339
345
|
* Get transaction history for an address on a specific chain
|
|
340
346
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
341
347
|
*/
|
|
342
|
-
async getTransactionHistory(seed,
|
|
348
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
343
349
|
try {
|
|
344
350
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
345
351
|
method: "POST",
|
|
346
|
-
headers:
|
|
347
|
-
|
|
348
|
-
},
|
|
349
|
-
body: JSON.stringify({ seed, chain: chain2, network, limit })
|
|
352
|
+
headers: this.getHeaders(),
|
|
353
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
350
354
|
});
|
|
351
355
|
return await response.json();
|
|
352
356
|
} catch (error) {
|
|
@@ -360,14 +364,12 @@ var WdkApiClient = class {
|
|
|
360
364
|
* Get transaction status by hash
|
|
361
365
|
* Fetches from blockchain explorers to check confirmation status
|
|
362
366
|
*/
|
|
363
|
-
async getTransactionStatus(txHash,
|
|
367
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
364
368
|
try {
|
|
365
369
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
366
370
|
method: "POST",
|
|
367
|
-
headers:
|
|
368
|
-
|
|
369
|
-
},
|
|
370
|
-
body: JSON.stringify({ txHash, chain: chain2, network })
|
|
371
|
+
headers: this.getHeaders(),
|
|
372
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
371
373
|
});
|
|
372
374
|
return await response.json();
|
|
373
375
|
} catch (error) {
|
|
@@ -380,605 +382,23 @@ var WdkApiClient = class {
|
|
|
380
382
|
};
|
|
381
383
|
var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
382
384
|
var wdkApiClient = null;
|
|
383
|
-
function getWdkApiClient(baseUrl) {
|
|
385
|
+
function getWdkApiClient(baseUrl, authToken) {
|
|
384
386
|
if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
|
|
385
387
|
wdkApiClient = new WdkApiClient({
|
|
386
|
-
baseUrl: baseUrl || DEFAULT_API_URL
|
|
388
|
+
baseUrl: baseUrl || DEFAULT_API_URL,
|
|
389
|
+
authToken
|
|
387
390
|
});
|
|
388
391
|
}
|
|
389
392
|
return wdkApiClient;
|
|
390
393
|
}
|
|
391
|
-
|
|
392
|
-
// node_modules/@scure/base/index.js
|
|
393
|
-
function isBytes(a) {
|
|
394
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
395
|
-
}
|
|
396
|
-
function isArrayOf(isString, arr) {
|
|
397
|
-
if (!Array.isArray(arr))
|
|
398
|
-
return false;
|
|
399
|
-
if (arr.length === 0)
|
|
400
|
-
return true;
|
|
401
|
-
if (isString) {
|
|
402
|
-
return arr.every((item) => typeof item === "string");
|
|
403
|
-
} else {
|
|
404
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
function afn(input) {
|
|
408
|
-
if (typeof input !== "function")
|
|
409
|
-
throw new Error("function expected");
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
function astr(label, input) {
|
|
413
|
-
if (typeof input !== "string")
|
|
414
|
-
throw new Error(`${label}: string expected`);
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
|
-
function anumber(n) {
|
|
418
|
-
if (!Number.isSafeInteger(n))
|
|
419
|
-
throw new Error(`invalid integer: ${n}`);
|
|
420
|
-
}
|
|
421
|
-
function aArr(input) {
|
|
422
|
-
if (!Array.isArray(input))
|
|
423
|
-
throw new Error("array expected");
|
|
424
|
-
}
|
|
425
|
-
function astrArr(label, input) {
|
|
426
|
-
if (!isArrayOf(true, input))
|
|
427
|
-
throw new Error(`${label}: array of strings expected`);
|
|
428
|
-
}
|
|
429
|
-
function anumArr(label, input) {
|
|
430
|
-
if (!isArrayOf(false, input))
|
|
431
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
432
|
-
}
|
|
433
|
-
// @__NO_SIDE_EFFECTS__
|
|
434
|
-
function chain(...args) {
|
|
435
|
-
const id = (a) => a;
|
|
436
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
437
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
438
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
439
|
-
return { encode, decode };
|
|
440
|
-
}
|
|
441
|
-
// @__NO_SIDE_EFFECTS__
|
|
442
|
-
function alphabet(letters) {
|
|
443
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
444
|
-
const len = lettersA.length;
|
|
445
|
-
astrArr("alphabet", lettersA);
|
|
446
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
447
|
-
return {
|
|
448
|
-
encode: (digits) => {
|
|
449
|
-
aArr(digits);
|
|
450
|
-
return digits.map((i) => {
|
|
451
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
452
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
453
|
-
return lettersA[i];
|
|
454
|
-
});
|
|
455
|
-
},
|
|
456
|
-
decode: (input) => {
|
|
457
|
-
aArr(input);
|
|
458
|
-
return input.map((letter) => {
|
|
459
|
-
astr("alphabet.decode", letter);
|
|
460
|
-
const i = indexes.get(letter);
|
|
461
|
-
if (i === void 0)
|
|
462
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
463
|
-
return i;
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
// @__NO_SIDE_EFFECTS__
|
|
469
|
-
function join(separator = "") {
|
|
470
|
-
astr("join", separator);
|
|
471
|
-
return {
|
|
472
|
-
encode: (from) => {
|
|
473
|
-
astrArr("join.decode", from);
|
|
474
|
-
return from.join(separator);
|
|
475
|
-
},
|
|
476
|
-
decode: (to) => {
|
|
477
|
-
astr("join.decode", to);
|
|
478
|
-
return to.split(separator);
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
function convertRadix(data, from, to) {
|
|
483
|
-
if (from < 2)
|
|
484
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
485
|
-
if (to < 2)
|
|
486
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
487
|
-
aArr(data);
|
|
488
|
-
if (!data.length)
|
|
489
|
-
return [];
|
|
490
|
-
let pos = 0;
|
|
491
|
-
const res = [];
|
|
492
|
-
const digits = Array.from(data, (d) => {
|
|
493
|
-
anumber(d);
|
|
494
|
-
if (d < 0 || d >= from)
|
|
495
|
-
throw new Error(`invalid integer: ${d}`);
|
|
496
|
-
return d;
|
|
497
|
-
});
|
|
498
|
-
const dlen = digits.length;
|
|
499
|
-
while (true) {
|
|
500
|
-
let carry = 0;
|
|
501
|
-
let done = true;
|
|
502
|
-
for (let i = pos; i < dlen; i++) {
|
|
503
|
-
const digit = digits[i];
|
|
504
|
-
const fromCarry = from * carry;
|
|
505
|
-
const digitBase = fromCarry + digit;
|
|
506
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
507
|
-
throw new Error("convertRadix: carry overflow");
|
|
508
|
-
}
|
|
509
|
-
const div = digitBase / to;
|
|
510
|
-
carry = digitBase % to;
|
|
511
|
-
const rounded = Math.floor(div);
|
|
512
|
-
digits[i] = rounded;
|
|
513
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
514
|
-
throw new Error("convertRadix: carry overflow");
|
|
515
|
-
if (!done)
|
|
516
|
-
continue;
|
|
517
|
-
else if (!rounded)
|
|
518
|
-
pos = i;
|
|
519
|
-
else
|
|
520
|
-
done = false;
|
|
521
|
-
}
|
|
522
|
-
res.push(carry);
|
|
523
|
-
if (done)
|
|
524
|
-
break;
|
|
525
|
-
}
|
|
526
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
527
|
-
res.push(0);
|
|
528
|
-
return res.reverse();
|
|
529
|
-
}
|
|
530
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
531
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
532
|
-
var powers = /* @__PURE__ */ (() => {
|
|
533
|
-
let res = [];
|
|
534
|
-
for (let i = 0; i < 40; i++)
|
|
535
|
-
res.push(2 ** i);
|
|
536
|
-
return res;
|
|
537
|
-
})();
|
|
538
|
-
function convertRadix2(data, from, to, padding) {
|
|
539
|
-
aArr(data);
|
|
540
|
-
if (from <= 0 || from > 32)
|
|
541
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
542
|
-
if (to <= 0 || to > 32)
|
|
543
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
544
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
545
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
546
|
-
}
|
|
547
|
-
let carry = 0;
|
|
548
|
-
let pos = 0;
|
|
549
|
-
const max = powers[from];
|
|
550
|
-
const mask = powers[to] - 1;
|
|
551
|
-
const res = [];
|
|
552
|
-
for (const n of data) {
|
|
553
|
-
anumber(n);
|
|
554
|
-
if (n >= max)
|
|
555
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
556
|
-
carry = carry << from | n;
|
|
557
|
-
if (pos + from > 32)
|
|
558
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
559
|
-
pos += from;
|
|
560
|
-
for (; pos >= to; pos -= to)
|
|
561
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
562
|
-
const pow = powers[pos];
|
|
563
|
-
if (pow === void 0)
|
|
564
|
-
throw new Error("invalid carry");
|
|
565
|
-
carry &= pow - 1;
|
|
566
|
-
}
|
|
567
|
-
carry = carry << to - pos & mask;
|
|
568
|
-
if (!padding && pos >= from)
|
|
569
|
-
throw new Error("Excess padding");
|
|
570
|
-
if (!padding && carry > 0)
|
|
571
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
572
|
-
if (padding && pos > 0)
|
|
573
|
-
res.push(carry >>> 0);
|
|
574
|
-
return res;
|
|
575
|
-
}
|
|
576
|
-
// @__NO_SIDE_EFFECTS__
|
|
577
|
-
function radix(num) {
|
|
578
|
-
anumber(num);
|
|
579
|
-
const _256 = 2 ** 8;
|
|
580
|
-
return {
|
|
581
|
-
encode: (bytes) => {
|
|
582
|
-
if (!isBytes(bytes))
|
|
583
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
584
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
585
|
-
},
|
|
586
|
-
decode: (digits) => {
|
|
587
|
-
anumArr("radix.decode", digits);
|
|
588
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
// @__NO_SIDE_EFFECTS__
|
|
593
|
-
function radix2(bits, revPadding = false) {
|
|
594
|
-
anumber(bits);
|
|
595
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
596
|
-
throw new Error("radix2: carry overflow");
|
|
597
|
-
return {
|
|
598
|
-
encode: (bytes) => {
|
|
599
|
-
if (!isBytes(bytes))
|
|
600
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
601
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
602
|
-
},
|
|
603
|
-
decode: (digits) => {
|
|
604
|
-
anumArr("radix2.decode", digits);
|
|
605
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
function unsafeWrapper(fn) {
|
|
610
|
-
afn(fn);
|
|
611
|
-
return function(...args) {
|
|
612
|
-
try {
|
|
613
|
-
return fn.apply(null, args);
|
|
614
|
-
} catch (e) {
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
function checksum(len, fn) {
|
|
619
|
-
anumber(len);
|
|
620
|
-
afn(fn);
|
|
621
|
-
return {
|
|
622
|
-
encode(data) {
|
|
623
|
-
if (!isBytes(data))
|
|
624
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
625
|
-
const sum = fn(data).slice(0, len);
|
|
626
|
-
const res = new Uint8Array(data.length + len);
|
|
627
|
-
res.set(data);
|
|
628
|
-
res.set(sum, data.length);
|
|
629
|
-
return res;
|
|
630
|
-
},
|
|
631
|
-
decode(data) {
|
|
632
|
-
if (!isBytes(data))
|
|
633
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
634
|
-
const payload = data.slice(0, -len);
|
|
635
|
-
const oldChecksum = data.slice(-len);
|
|
636
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
637
|
-
for (let i = 0; i < len; i++)
|
|
638
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
639
|
-
throw new Error("Invalid checksum");
|
|
640
|
-
return payload;
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
645
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
646
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
647
|
-
var base58check = createBase58check;
|
|
648
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
649
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
650
|
-
function bech32Polymod(pre) {
|
|
651
|
-
const b = pre >> 25;
|
|
652
|
-
let chk = (pre & 33554431) << 5;
|
|
653
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
654
|
-
if ((b >> i & 1) === 1)
|
|
655
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
656
|
-
}
|
|
657
|
-
return chk;
|
|
658
|
-
}
|
|
659
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
660
|
-
const len = prefix.length;
|
|
661
|
-
let chk = 1;
|
|
662
|
-
for (let i = 0; i < len; i++) {
|
|
663
|
-
const c = prefix.charCodeAt(i);
|
|
664
|
-
if (c < 33 || c > 126)
|
|
665
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
666
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
667
|
-
}
|
|
668
|
-
chk = bech32Polymod(chk);
|
|
669
|
-
for (let i = 0; i < len; i++)
|
|
670
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
671
|
-
for (let v of words)
|
|
672
|
-
chk = bech32Polymod(chk) ^ v;
|
|
673
|
-
for (let i = 0; i < 6; i++)
|
|
674
|
-
chk = bech32Polymod(chk);
|
|
675
|
-
chk ^= encodingConst;
|
|
676
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
677
|
-
}
|
|
678
|
-
// @__NO_SIDE_EFFECTS__
|
|
679
|
-
function genBech32(encoding) {
|
|
680
|
-
const ENCODING_CONST = 1 ;
|
|
681
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
682
|
-
const fromWords = _words.decode;
|
|
683
|
-
const toWords = _words.encode;
|
|
684
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
685
|
-
function encode(prefix, words, limit = 90) {
|
|
686
|
-
astr("bech32.encode prefix", prefix);
|
|
687
|
-
if (isBytes(words))
|
|
688
|
-
words = Array.from(words);
|
|
689
|
-
anumArr("bech32.encode", words);
|
|
690
|
-
const plen = prefix.length;
|
|
691
|
-
if (plen === 0)
|
|
692
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
693
|
-
const actualLength = plen + 7 + words.length;
|
|
694
|
-
if (limit !== false && actualLength > limit)
|
|
695
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
696
|
-
const lowered = prefix.toLowerCase();
|
|
697
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
698
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
699
|
-
}
|
|
700
|
-
function decode(str, limit = 90) {
|
|
701
|
-
astr("bech32.decode input", str);
|
|
702
|
-
const slen = str.length;
|
|
703
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
704
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
705
|
-
const lowered = str.toLowerCase();
|
|
706
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
707
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
708
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
709
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
710
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
711
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
712
|
-
const data = lowered.slice(sepIndex + 1);
|
|
713
|
-
if (data.length < 6)
|
|
714
|
-
throw new Error("Data must be at least 6 characters long");
|
|
715
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
716
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
717
|
-
if (!data.endsWith(sum))
|
|
718
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
719
|
-
return { prefix, words };
|
|
720
|
-
}
|
|
721
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
722
|
-
function decodeToBytes(str) {
|
|
723
|
-
const { prefix, words } = decode(str, false);
|
|
724
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
725
|
-
}
|
|
726
|
-
function encodeFromBytes(prefix, bytes) {
|
|
727
|
-
return encode(prefix, toWords(bytes));
|
|
728
|
-
}
|
|
729
|
-
return {
|
|
730
|
-
encode,
|
|
731
|
-
decode,
|
|
732
|
-
encodeFromBytes,
|
|
733
|
-
decodeToBytes,
|
|
734
|
-
decodeUnsafe,
|
|
735
|
-
fromWords,
|
|
736
|
-
fromWordsUnsafe,
|
|
737
|
-
toWords
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
741
|
-
|
|
742
|
-
// node_modules/@scure/bip32/index.js
|
|
743
|
-
var Point = secp256k1.Point;
|
|
744
|
-
var { Fn } = Point;
|
|
745
|
-
var base58check2 = createBase58check(sha256);
|
|
746
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
747
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
748
|
-
var HARDENED_OFFSET = 2147483648;
|
|
749
|
-
var hash160 = (data) => ripemd160$1(sha256(data));
|
|
750
|
-
var fromU32 = (data) => createView(data).getUint32(0, false);
|
|
751
|
-
var toU32 = (n) => {
|
|
752
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
753
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
754
|
-
}
|
|
755
|
-
const buf = new Uint8Array(4);
|
|
756
|
-
createView(buf).setUint32(0, n, false);
|
|
757
|
-
return buf;
|
|
758
|
-
};
|
|
759
|
-
var HDKey = class _HDKey {
|
|
760
|
-
get fingerprint() {
|
|
761
|
-
if (!this.pubHash) {
|
|
762
|
-
throw new Error("No publicKey set!");
|
|
763
|
-
}
|
|
764
|
-
return fromU32(this.pubHash);
|
|
765
|
-
}
|
|
766
|
-
get identifier() {
|
|
767
|
-
return this.pubHash;
|
|
768
|
-
}
|
|
769
|
-
get pubKeyHash() {
|
|
770
|
-
return this.pubHash;
|
|
771
|
-
}
|
|
772
|
-
get privateKey() {
|
|
773
|
-
return this._privateKey || null;
|
|
774
|
-
}
|
|
775
|
-
get publicKey() {
|
|
776
|
-
return this._publicKey || null;
|
|
777
|
-
}
|
|
778
|
-
get privateExtendedKey() {
|
|
779
|
-
const priv = this._privateKey;
|
|
780
|
-
if (!priv) {
|
|
781
|
-
throw new Error("No private key");
|
|
782
|
-
}
|
|
783
|
-
return base58check2.encode(this.serialize(this.versions.private, concatBytes(Uint8Array.of(0), priv)));
|
|
784
|
-
}
|
|
785
|
-
get publicExtendedKey() {
|
|
786
|
-
if (!this._publicKey) {
|
|
787
|
-
throw new Error("No public key");
|
|
788
|
-
}
|
|
789
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
790
|
-
}
|
|
791
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
792
|
-
abytes(seed);
|
|
793
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
794
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
795
|
-
}
|
|
796
|
-
const I = hmac(sha512, MASTER_SECRET, seed);
|
|
797
|
-
const privateKey = I.slice(0, 32);
|
|
798
|
-
const chainCode = I.slice(32);
|
|
799
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
800
|
-
}
|
|
801
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
802
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
803
|
-
const keyView = createView(keyBuffer);
|
|
804
|
-
const version = keyView.getUint32(0, false);
|
|
805
|
-
const opt = {
|
|
806
|
-
versions,
|
|
807
|
-
depth: keyBuffer[4],
|
|
808
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
809
|
-
index: keyView.getUint32(9, false),
|
|
810
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
811
|
-
};
|
|
812
|
-
const key = keyBuffer.slice(45);
|
|
813
|
-
const isPriv = key[0] === 0;
|
|
814
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
815
|
-
throw new Error("Version mismatch");
|
|
816
|
-
}
|
|
817
|
-
if (isPriv) {
|
|
818
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
819
|
-
} else {
|
|
820
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
static fromJSON(json) {
|
|
824
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
825
|
-
}
|
|
826
|
-
versions;
|
|
827
|
-
depth = 0;
|
|
828
|
-
index = 0;
|
|
829
|
-
chainCode = null;
|
|
830
|
-
parentFingerprint = 0;
|
|
831
|
-
_privateKey;
|
|
832
|
-
_publicKey;
|
|
833
|
-
pubHash;
|
|
834
|
-
constructor(opt) {
|
|
835
|
-
if (!opt || typeof opt !== "object") {
|
|
836
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
837
|
-
}
|
|
838
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
839
|
-
this.depth = opt.depth || 0;
|
|
840
|
-
this.chainCode = opt.chainCode || null;
|
|
841
|
-
this.index = opt.index || 0;
|
|
842
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
843
|
-
if (!this.depth) {
|
|
844
|
-
if (this.parentFingerprint || this.index) {
|
|
845
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (this.depth > 255) {
|
|
849
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
850
|
-
}
|
|
851
|
-
if (opt.publicKey && opt.privateKey) {
|
|
852
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
853
|
-
}
|
|
854
|
-
if (opt.privateKey) {
|
|
855
|
-
if (!secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
856
|
-
throw new Error("Invalid private key");
|
|
857
|
-
this._privateKey = opt.privateKey;
|
|
858
|
-
this._publicKey = secp256k1.getPublicKey(opt.privateKey, true);
|
|
859
|
-
} else if (opt.publicKey) {
|
|
860
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
861
|
-
} else {
|
|
862
|
-
throw new Error("HDKey: no public or private key provided");
|
|
863
|
-
}
|
|
864
|
-
this.pubHash = hash160(this._publicKey);
|
|
865
|
-
}
|
|
866
|
-
derive(path) {
|
|
867
|
-
if (!/^[mM]'?/.test(path)) {
|
|
868
|
-
throw new Error('Path must start with "m" or "M"');
|
|
869
|
-
}
|
|
870
|
-
if (/^[mM]'?$/.test(path)) {
|
|
871
|
-
return this;
|
|
872
|
-
}
|
|
873
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
874
|
-
let child = this;
|
|
875
|
-
for (const c of parts) {
|
|
876
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
877
|
-
const m1 = m && m[1];
|
|
878
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
879
|
-
throw new Error("invalid child index: " + c);
|
|
880
|
-
let idx = +m1;
|
|
881
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
882
|
-
throw new Error("Invalid index");
|
|
883
|
-
}
|
|
884
|
-
if (m[2] === "'") {
|
|
885
|
-
idx += HARDENED_OFFSET;
|
|
886
|
-
}
|
|
887
|
-
child = child.deriveChild(idx);
|
|
888
|
-
}
|
|
889
|
-
return child;
|
|
890
|
-
}
|
|
891
|
-
deriveChild(index) {
|
|
892
|
-
if (!this._publicKey || !this.chainCode) {
|
|
893
|
-
throw new Error("No publicKey or chainCode set");
|
|
894
|
-
}
|
|
895
|
-
let data = toU32(index);
|
|
896
|
-
if (index >= HARDENED_OFFSET) {
|
|
897
|
-
const priv = this._privateKey;
|
|
898
|
-
if (!priv) {
|
|
899
|
-
throw new Error("Could not derive hardened child key");
|
|
900
|
-
}
|
|
901
|
-
data = concatBytes(Uint8Array.of(0), priv, data);
|
|
902
|
-
} else {
|
|
903
|
-
data = concatBytes(this._publicKey, data);
|
|
904
|
-
}
|
|
905
|
-
const I = hmac(sha512, this.chainCode, data);
|
|
906
|
-
const childTweak = I.slice(0, 32);
|
|
907
|
-
const chainCode = I.slice(32);
|
|
908
|
-
if (!secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
909
|
-
throw new Error("Tweak bigger than curve order");
|
|
910
|
-
}
|
|
911
|
-
const opt = {
|
|
912
|
-
versions: this.versions,
|
|
913
|
-
chainCode,
|
|
914
|
-
depth: this.depth + 1,
|
|
915
|
-
parentFingerprint: this.fingerprint,
|
|
916
|
-
index
|
|
917
|
-
};
|
|
918
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
919
|
-
try {
|
|
920
|
-
if (this._privateKey) {
|
|
921
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
922
|
-
if (!Fn.isValidNot0(added)) {
|
|
923
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
924
|
-
}
|
|
925
|
-
opt.privateKey = Fn.toBytes(added);
|
|
926
|
-
} else {
|
|
927
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
928
|
-
if (added.equals(Point.ZERO)) {
|
|
929
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
930
|
-
}
|
|
931
|
-
opt.publicKey = added.toBytes(true);
|
|
932
|
-
}
|
|
933
|
-
return new _HDKey(opt);
|
|
934
|
-
} catch (err) {
|
|
935
|
-
return this.deriveChild(index + 1);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
sign(hash) {
|
|
939
|
-
if (!this._privateKey) {
|
|
940
|
-
throw new Error("No privateKey set!");
|
|
941
|
-
}
|
|
942
|
-
abytes(hash, 32);
|
|
943
|
-
return secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
944
|
-
}
|
|
945
|
-
verify(hash, signature) {
|
|
946
|
-
abytes(hash, 32);
|
|
947
|
-
abytes(signature, 64);
|
|
948
|
-
if (!this._publicKey) {
|
|
949
|
-
throw new Error("No publicKey set!");
|
|
950
|
-
}
|
|
951
|
-
return secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
952
|
-
}
|
|
953
|
-
wipePrivateData() {
|
|
954
|
-
if (this._privateKey) {
|
|
955
|
-
this._privateKey.fill(0);
|
|
956
|
-
this._privateKey = void 0;
|
|
957
|
-
}
|
|
958
|
-
return this;
|
|
959
|
-
}
|
|
960
|
-
toJSON() {
|
|
961
|
-
return {
|
|
962
|
-
xpriv: this.privateExtendedKey,
|
|
963
|
-
xpub: this.publicExtendedKey
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
serialize(version, key) {
|
|
967
|
-
if (!this.chainCode) {
|
|
968
|
-
throw new Error("No chainCode set");
|
|
969
|
-
}
|
|
970
|
-
abytes(key, 33);
|
|
971
|
-
return concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
972
|
-
}
|
|
973
|
-
};
|
|
974
394
|
var DERIVATION_PATHS2 = {
|
|
975
|
-
ethereum:
|
|
976
|
-
bitcoin_mainnet:
|
|
395
|
+
ethereum: `${DERIVATION_PATHS.ethereum}/0`,
|
|
396
|
+
bitcoin_mainnet: `${DERIVATION_PATHS.bitcoin}/0`,
|
|
977
397
|
bitcoin_testnet: "m/84'/1'/0'/0/0",
|
|
978
|
-
ton:
|
|
979
|
-
tron:
|
|
980
|
-
solana:
|
|
981
|
-
spark:
|
|
398
|
+
ton: `${DERIVATION_PATHS.ton}/0'/0'`,
|
|
399
|
+
tron: `${DERIVATION_PATHS.tron}/0`,
|
|
400
|
+
solana: `${DERIVATION_PATHS.solana}/0'`,
|
|
401
|
+
spark: `${DERIVATION_PATHS.spark}/0`
|
|
982
402
|
};
|
|
983
403
|
function deriveEthereumAddress(seed) {
|
|
984
404
|
const hdNode = HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
|
|
@@ -993,7 +413,7 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
993
413
|
if (!child.publicKey) {
|
|
994
414
|
throw new Error("Failed to derive public key");
|
|
995
415
|
}
|
|
996
|
-
const pubKeyHash = ripemd160(sha256
|
|
416
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
997
417
|
const witnessVersion = 0;
|
|
998
418
|
const words = bech32.toWords(pubKeyHash);
|
|
999
419
|
words.unshift(witnessVersion);
|
|
@@ -1034,7 +454,7 @@ async function deriveTonAddress(seed) {
|
|
|
1034
454
|
const publicKey = keypair.publicKey;
|
|
1035
455
|
const workchain = 0;
|
|
1036
456
|
const flags = 17;
|
|
1037
|
-
const hash = sha256
|
|
457
|
+
const hash = sha256(publicKey);
|
|
1038
458
|
const addressData = new Uint8Array(34);
|
|
1039
459
|
addressData[0] = flags;
|
|
1040
460
|
addressData[1] = workchain;
|
|
@@ -1071,7 +491,7 @@ function deriveTronAddress(seed) {
|
|
|
1071
491
|
for (let i = 0; i < 20; i++) {
|
|
1072
492
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1073
493
|
}
|
|
1074
|
-
const tronBase58check = base58check(sha256
|
|
494
|
+
const tronBase58check = base58check(sha256);
|
|
1075
495
|
return tronBase58check.encode(addressBytes);
|
|
1076
496
|
} catch (error) {
|
|
1077
497
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1086,7 +506,7 @@ function deriveSparkAddress(seed, network = "mainnet") {
|
|
|
1086
506
|
if (!child.publicKey) {
|
|
1087
507
|
throw new Error("Failed to derive public key");
|
|
1088
508
|
}
|
|
1089
|
-
const pubKeyHash = ripemd160(sha256
|
|
509
|
+
const pubKeyHash = ripemd160(sha256(child.publicKey));
|
|
1090
510
|
const witnessVersion = 0;
|
|
1091
511
|
const words = bech32.toWords(pubKeyHash);
|
|
1092
512
|
words.unshift(witnessVersion);
|
|
@@ -1187,9 +607,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1187
607
|
"no route": "NETWORK_ERROR"
|
|
1188
608
|
}
|
|
1189
609
|
};
|
|
1190
|
-
function parseChainError(
|
|
610
|
+
function parseChainError(chain, errorMessage) {
|
|
1191
611
|
const errorLower = errorMessage.toLowerCase();
|
|
1192
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
612
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1193
613
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1194
614
|
if (errorLower.includes(pattern)) {
|
|
1195
615
|
return code;
|
|
@@ -1327,38 +747,38 @@ var ZubariWdkService = class {
|
|
|
1327
747
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1328
748
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1329
749
|
*/
|
|
1330
|
-
async deriveAddress(seed,
|
|
750
|
+
async deriveAddress(seed, chain) {
|
|
1331
751
|
await this.initialize();
|
|
1332
|
-
const path = this.getDerivationPath(
|
|
752
|
+
const path = this.getDerivationPath(chain);
|
|
1333
753
|
try {
|
|
1334
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
754
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1335
755
|
if (response.success && response.address) {
|
|
1336
756
|
return {
|
|
1337
|
-
chain
|
|
757
|
+
chain,
|
|
1338
758
|
address: response.address,
|
|
1339
759
|
path: response.path || path
|
|
1340
760
|
};
|
|
1341
761
|
}
|
|
1342
762
|
} catch (error) {
|
|
1343
|
-
console.warn(`API address derivation failed for ${
|
|
1344
|
-
if (
|
|
1345
|
-
return this.deriveBrowserAddress(seed,
|
|
763
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
764
|
+
if (chain === "ethereum") {
|
|
765
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1346
766
|
}
|
|
1347
767
|
}
|
|
1348
768
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1349
769
|
try {
|
|
1350
770
|
const wdk = this.nativeWdkService;
|
|
1351
771
|
await wdk.initialize(seed);
|
|
1352
|
-
return await wdk.deriveAddress(
|
|
772
|
+
return await wdk.deriveAddress(chain);
|
|
1353
773
|
} catch (error) {
|
|
1354
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
774
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1355
775
|
}
|
|
1356
776
|
}
|
|
1357
|
-
if (
|
|
1358
|
-
return this.deriveBrowserAddress(seed,
|
|
777
|
+
if (chain === "ethereum") {
|
|
778
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1359
779
|
}
|
|
1360
780
|
throw new Error(
|
|
1361
|
-
`WDK API required for ${
|
|
781
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1362
782
|
);
|
|
1363
783
|
}
|
|
1364
784
|
/**
|
|
@@ -1438,13 +858,13 @@ var ZubariWdkService = class {
|
|
|
1438
858
|
/**
|
|
1439
859
|
* Get fee rates for a chain
|
|
1440
860
|
*/
|
|
1441
|
-
async getFeeRates(seed,
|
|
861
|
+
async getFeeRates(seed, chain) {
|
|
1442
862
|
await this.initialize();
|
|
1443
863
|
try {
|
|
1444
864
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1445
865
|
method: "POST",
|
|
1446
866
|
headers: { "Content-Type": "application/json" },
|
|
1447
|
-
body: JSON.stringify({ seed, chain
|
|
867
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1448
868
|
});
|
|
1449
869
|
if (response.ok) {
|
|
1450
870
|
const data = await response.json();
|
|
@@ -1453,20 +873,20 @@ var ZubariWdkService = class {
|
|
|
1453
873
|
}
|
|
1454
874
|
}
|
|
1455
875
|
} catch (error) {
|
|
1456
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
876
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1457
877
|
}
|
|
1458
878
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1459
879
|
}
|
|
1460
880
|
/**
|
|
1461
881
|
* Estimate transaction fee
|
|
1462
882
|
*/
|
|
1463
|
-
async estimateFee(seed,
|
|
883
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1464
884
|
await this.initialize();
|
|
1465
885
|
try {
|
|
1466
886
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1467
887
|
method: "POST",
|
|
1468
888
|
headers: { "Content-Type": "application/json" },
|
|
1469
|
-
body: JSON.stringify({ seed, chain
|
|
889
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1470
890
|
});
|
|
1471
891
|
if (response.ok) {
|
|
1472
892
|
const data = await response.json();
|
|
@@ -1475,9 +895,9 @@ var ZubariWdkService = class {
|
|
|
1475
895
|
}
|
|
1476
896
|
}
|
|
1477
897
|
} catch (error) {
|
|
1478
|
-
console.warn(`Failed to estimate fee for ${
|
|
898
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1479
899
|
}
|
|
1480
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
900
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1481
901
|
}
|
|
1482
902
|
/**
|
|
1483
903
|
* Send a transaction on any supported chain
|
|
@@ -1488,19 +908,14 @@ var ZubariWdkService = class {
|
|
|
1488
908
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1489
909
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1490
910
|
*/
|
|
1491
|
-
async sendTransaction(seed,
|
|
911
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1492
912
|
await this.initialize();
|
|
1493
913
|
const startTime = Date.now();
|
|
1494
|
-
console.log(`[ZubariWdkService] Sending ${chain2} transaction`, {
|
|
1495
|
-
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1496
|
-
amount,
|
|
1497
|
-
network: this.config.network
|
|
1498
|
-
});
|
|
1499
914
|
try {
|
|
1500
915
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1501
916
|
method: "POST",
|
|
1502
917
|
headers: { "Content-Type": "application/json" },
|
|
1503
|
-
body: JSON.stringify({ seed, chain
|
|
918
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1504
919
|
});
|
|
1505
920
|
const elapsed = Date.now() - startTime;
|
|
1506
921
|
if (response.ok) {
|
|
@@ -1510,22 +925,18 @@ var ZubariWdkService = class {
|
|
|
1510
925
|
txHash = txHash.hash;
|
|
1511
926
|
}
|
|
1512
927
|
if (txHash) {
|
|
1513
|
-
const isValid = this.validateTxHash(
|
|
928
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1514
929
|
if (!isValid) {
|
|
1515
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
930
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1516
931
|
}
|
|
1517
932
|
}
|
|
1518
|
-
console.log(`[ZubariWdkService] ${chain2} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1519
|
-
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1520
|
-
elapsed: `${elapsed}ms`
|
|
1521
|
-
});
|
|
1522
933
|
if (!data.success) {
|
|
1523
|
-
const errorCode2 = parseChainError(
|
|
934
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1524
935
|
return {
|
|
1525
936
|
success: false,
|
|
1526
937
|
error: data.error,
|
|
1527
938
|
errorCode: errorCode2,
|
|
1528
|
-
chain
|
|
939
|
+
chain
|
|
1529
940
|
};
|
|
1530
941
|
}
|
|
1531
942
|
return {
|
|
@@ -1534,47 +945,35 @@ var ZubariWdkService = class {
|
|
|
1534
945
|
from: data.from,
|
|
1535
946
|
to: data.to,
|
|
1536
947
|
amount: data.amount,
|
|
1537
|
-
chain: data.chain ||
|
|
948
|
+
chain: data.chain || chain,
|
|
1538
949
|
network: data.network || this.config.network
|
|
1539
950
|
};
|
|
1540
951
|
}
|
|
1541
952
|
const errorData = await response.json().catch(() => ({}));
|
|
1542
953
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1543
|
-
const errorCode = parseChainError(
|
|
1544
|
-
console.error(`[ZubariWdkService] ${chain2} transaction FAILED`, {
|
|
1545
|
-
status: response.status,
|
|
1546
|
-
error: errorMessage,
|
|
1547
|
-
errorCode,
|
|
1548
|
-
elapsed: `${elapsed}ms`
|
|
1549
|
-
});
|
|
954
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1550
955
|
return {
|
|
1551
956
|
success: false,
|
|
1552
957
|
error: errorMessage,
|
|
1553
958
|
errorCode,
|
|
1554
|
-
chain
|
|
959
|
+
chain
|
|
1555
960
|
};
|
|
1556
961
|
} catch (error) {
|
|
1557
|
-
const elapsed = Date.now() - startTime;
|
|
1558
962
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1559
|
-
const errorCode = parseChainError(
|
|
1560
|
-
console.error(`[ZubariWdkService] ${chain2} transaction ERROR`, {
|
|
1561
|
-
error: errorMessage,
|
|
1562
|
-
errorCode,
|
|
1563
|
-
elapsed: `${elapsed}ms`
|
|
1564
|
-
});
|
|
963
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1565
964
|
return {
|
|
1566
965
|
success: false,
|
|
1567
966
|
error: errorMessage,
|
|
1568
967
|
errorCode,
|
|
1569
|
-
chain
|
|
968
|
+
chain
|
|
1570
969
|
};
|
|
1571
970
|
}
|
|
1572
971
|
}
|
|
1573
972
|
/**
|
|
1574
973
|
* Validate transaction hash format for a specific chain
|
|
1575
974
|
*/
|
|
1576
|
-
validateTxHash(
|
|
1577
|
-
switch (
|
|
975
|
+
validateTxHash(chain, txHash) {
|
|
976
|
+
switch (chain) {
|
|
1578
977
|
case "ethereum":
|
|
1579
978
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1580
979
|
case "bitcoin":
|
|
@@ -1606,18 +1005,25 @@ var ZubariWdkService = class {
|
|
|
1606
1005
|
// ==========================================
|
|
1607
1006
|
// Private Helper Methods
|
|
1608
1007
|
// ==========================================
|
|
1609
|
-
getDerivationPath(
|
|
1610
|
-
const
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1008
|
+
getDerivationPath(chain) {
|
|
1009
|
+
const basePath = DERIVATION_PATHS[chain];
|
|
1010
|
+
if (chain === "bitcoin" && this.config.network === "testnet") {
|
|
1011
|
+
return "m/84'/1'/0'/0/0";
|
|
1012
|
+
}
|
|
1013
|
+
switch (chain) {
|
|
1014
|
+
case "ton":
|
|
1015
|
+
return `${basePath}/0'/0'`;
|
|
1016
|
+
case "solana":
|
|
1017
|
+
return `${basePath}/0'`;
|
|
1018
|
+
case "bitcoin":
|
|
1019
|
+
case "ethereum":
|
|
1020
|
+
case "tron":
|
|
1021
|
+
case "spark":
|
|
1022
|
+
default:
|
|
1023
|
+
return `${basePath}/0`;
|
|
1024
|
+
}
|
|
1619
1025
|
}
|
|
1620
|
-
getChainSymbol(
|
|
1026
|
+
getChainSymbol(chain) {
|
|
1621
1027
|
const symbols = {
|
|
1622
1028
|
ethereum: "ETH",
|
|
1623
1029
|
bitcoin: "BTC",
|
|
@@ -1626,16 +1032,16 @@ var ZubariWdkService = class {
|
|
|
1626
1032
|
solana: "SOL",
|
|
1627
1033
|
spark: "SAT"
|
|
1628
1034
|
};
|
|
1629
|
-
return symbols[
|
|
1035
|
+
return symbols[chain];
|
|
1630
1036
|
}
|
|
1631
1037
|
/**
|
|
1632
1038
|
* Derive address using browser-compatible libraries
|
|
1633
1039
|
*/
|
|
1634
|
-
async deriveBrowserAddress(seed,
|
|
1635
|
-
const path = this.getDerivationPath(
|
|
1040
|
+
async deriveBrowserAddress(seed, chain) {
|
|
1041
|
+
const path = this.getDerivationPath(chain);
|
|
1636
1042
|
try {
|
|
1637
1043
|
let address;
|
|
1638
|
-
switch (
|
|
1044
|
+
switch (chain) {
|
|
1639
1045
|
case "ethereum":
|
|
1640
1046
|
address = deriveEthereumAddress(seed);
|
|
1641
1047
|
break;
|
|
@@ -1655,11 +1061,11 @@ var ZubariWdkService = class {
|
|
|
1655
1061
|
address = await deriveTonAddress(seed);
|
|
1656
1062
|
break;
|
|
1657
1063
|
default:
|
|
1658
|
-
throw new Error(`Unsupported chain: ${
|
|
1064
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1659
1065
|
}
|
|
1660
|
-
return { chain
|
|
1066
|
+
return { chain, address, path };
|
|
1661
1067
|
} catch (error) {
|
|
1662
|
-
console.error(`Browser derivation failed for ${
|
|
1068
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1663
1069
|
throw error;
|
|
1664
1070
|
}
|
|
1665
1071
|
}
|
|
@@ -1672,19 +1078,28 @@ var ZubariWdkService = class {
|
|
|
1672
1078
|
};
|
|
1673
1079
|
var defaultService = null;
|
|
1674
1080
|
function getZubariWdkService(config) {
|
|
1675
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1081
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1676
1082
|
defaultService = new ZubariWdkService(config);
|
|
1677
1083
|
}
|
|
1678
1084
|
return defaultService;
|
|
1679
1085
|
}
|
|
1680
1086
|
|
|
1681
1087
|
// src/wallet/ZubariWallet.ts
|
|
1682
|
-
var ZubariWallet = class {
|
|
1088
|
+
var ZubariWallet = class _ZubariWallet {
|
|
1683
1089
|
seed;
|
|
1684
1090
|
config;
|
|
1685
1091
|
accounts = /* @__PURE__ */ new Map();
|
|
1686
1092
|
wdkService;
|
|
1687
1093
|
initialized = false;
|
|
1094
|
+
/** Mapping from NetworkType to SupportedChain (identity map, shared across methods) */
|
|
1095
|
+
static CHAIN_MAP = {
|
|
1096
|
+
ethereum: "ethereum",
|
|
1097
|
+
bitcoin: "bitcoin",
|
|
1098
|
+
ton: "ton",
|
|
1099
|
+
tron: "tron",
|
|
1100
|
+
solana: "solana",
|
|
1101
|
+
spark: "spark"
|
|
1102
|
+
};
|
|
1688
1103
|
constructor(seed, config) {
|
|
1689
1104
|
this.seed = seed;
|
|
1690
1105
|
this.config = {
|
|
@@ -1717,20 +1132,12 @@ var ZubariWallet = class {
|
|
|
1717
1132
|
async deriveAccount(network, index = 0) {
|
|
1718
1133
|
const basePath = DERIVATION_PATHS[network];
|
|
1719
1134
|
const derivationPath = `${basePath}/${index}`;
|
|
1720
|
-
const
|
|
1721
|
-
|
|
1722
|
-
bitcoin: "bitcoin",
|
|
1723
|
-
ton: "ton",
|
|
1724
|
-
tron: "tron",
|
|
1725
|
-
solana: "solana",
|
|
1726
|
-
spark: "spark"
|
|
1727
|
-
};
|
|
1728
|
-
const chain2 = chainMap[network];
|
|
1729
|
-
if (!chain2) {
|
|
1135
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1136
|
+
if (!chain) {
|
|
1730
1137
|
throw new Error(`Unsupported network: ${network}`);
|
|
1731
1138
|
}
|
|
1732
1139
|
try {
|
|
1733
|
-
const result = await this.wdkService.deriveAddress(this.seed,
|
|
1140
|
+
const result = await this.wdkService.deriveAddress(this.seed, chain);
|
|
1734
1141
|
const account = {
|
|
1735
1142
|
network,
|
|
1736
1143
|
address: result.address,
|
|
@@ -1777,21 +1184,13 @@ var ZubariWallet = class {
|
|
|
1777
1184
|
*/
|
|
1778
1185
|
async getBalance(network) {
|
|
1779
1186
|
const networkConfig = getNetworkConfig(network, this.config.network === "testnet");
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
bitcoin: "bitcoin",
|
|
1783
|
-
ton: "ton",
|
|
1784
|
-
tron: "tron",
|
|
1785
|
-
solana: "solana",
|
|
1786
|
-
spark: "spark"
|
|
1787
|
-
};
|
|
1788
|
-
const chain2 = chainMap[network];
|
|
1789
|
-
if (!chain2) {
|
|
1187
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1188
|
+
if (!chain) {
|
|
1790
1189
|
throw new Error(`Unsupported network: ${network}`);
|
|
1791
1190
|
}
|
|
1792
1191
|
try {
|
|
1793
1192
|
const balances = await this.wdkService.getAllBalances(this.seed);
|
|
1794
|
-
const chainBalance = balances[
|
|
1193
|
+
const chainBalance = balances[chain];
|
|
1795
1194
|
if (chainBalance) {
|
|
1796
1195
|
const balanceValue = BigInt(chainBalance.balance || "0");
|
|
1797
1196
|
const decimals = networkConfig.nativeCurrency.decimals;
|
|
@@ -1872,22 +1271,14 @@ var ZubariWallet = class {
|
|
|
1872
1271
|
*/
|
|
1873
1272
|
async send(network, params) {
|
|
1874
1273
|
const { to, amount } = params;
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
bitcoin: "bitcoin",
|
|
1878
|
-
ton: "ton",
|
|
1879
|
-
tron: "tron",
|
|
1880
|
-
solana: "solana",
|
|
1881
|
-
spark: "spark"
|
|
1882
|
-
};
|
|
1883
|
-
const chain2 = chainMap[network];
|
|
1884
|
-
if (!chain2) {
|
|
1274
|
+
const chain = _ZubariWallet.CHAIN_MAP[network];
|
|
1275
|
+
if (!chain) {
|
|
1885
1276
|
throw new Error(`Unsupported network: ${network}`);
|
|
1886
1277
|
}
|
|
1887
1278
|
try {
|
|
1888
1279
|
const result = await this.wdkService.sendTransaction(
|
|
1889
1280
|
this.seed,
|
|
1890
|
-
|
|
1281
|
+
chain,
|
|
1891
1282
|
to,
|
|
1892
1283
|
amount.toString()
|
|
1893
1284
|
);
|
|
@@ -2185,7 +1576,10 @@ var KeyManager = class {
|
|
|
2185
1576
|
static KEY_LENGTH = 256;
|
|
2186
1577
|
static IV_LENGTH = 12;
|
|
2187
1578
|
static SALT_LENGTH = 16;
|
|
2188
|
-
|
|
1579
|
+
// OWASP 2023 recommends 600,000 iterations for PBKDF2-SHA256 to resist
|
|
1580
|
+
// brute-force attacks with modern GPU hardware.
|
|
1581
|
+
// See: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
|
|
1582
|
+
static PBKDF2_ITERATIONS = 6e5;
|
|
2189
1583
|
/**
|
|
2190
1584
|
* Encrypt a seed phrase with a password
|
|
2191
1585
|
*/
|
|
@@ -2424,7 +1818,7 @@ var WebEncryptedStorageAdapter = class {
|
|
|
2424
1818
|
{
|
|
2425
1819
|
name: "PBKDF2",
|
|
2426
1820
|
salt: salt.buffer,
|
|
2427
|
-
iterations:
|
|
1821
|
+
iterations: 6e5,
|
|
2428
1822
|
hash: "SHA-256"
|
|
2429
1823
|
},
|
|
2430
1824
|
keyMaterial,
|
|
@@ -2562,8 +1956,8 @@ async function fetchPrices() {
|
|
|
2562
1956
|
if (response.ok) {
|
|
2563
1957
|
const data = await response.json();
|
|
2564
1958
|
const prices = {};
|
|
2565
|
-
for (const [
|
|
2566
|
-
prices[
|
|
1959
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1960
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2567
1961
|
}
|
|
2568
1962
|
priceCache = { prices, timestamp: Date.now() };
|
|
2569
1963
|
return prices;
|
|
@@ -2573,9 +1967,22 @@ async function fetchPrices() {
|
|
|
2573
1967
|
}
|
|
2574
1968
|
return priceCache?.prices || {};
|
|
2575
1969
|
}
|
|
2576
|
-
async function getPriceForChain(
|
|
1970
|
+
async function getPriceForChain(chain) {
|
|
2577
1971
|
const prices = await fetchPrices();
|
|
2578
|
-
return prices[
|
|
1972
|
+
return prices[chain] || 0;
|
|
1973
|
+
}
|
|
1974
|
+
function tonFriendlyToRaw(addr) {
|
|
1975
|
+
if (addr.includes(":")) return addr;
|
|
1976
|
+
try {
|
|
1977
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1978
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1979
|
+
if (bytes.length !== 36) return addr;
|
|
1980
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1981
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1982
|
+
return `${workchain}:${hash}`;
|
|
1983
|
+
} catch {
|
|
1984
|
+
return addr;
|
|
1985
|
+
}
|
|
2579
1986
|
}
|
|
2580
1987
|
var STORAGE_KEYS = {
|
|
2581
1988
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2724,6 +2131,16 @@ var WalletManager = class _WalletManager {
|
|
|
2724
2131
|
}
|
|
2725
2132
|
/**
|
|
2726
2133
|
* Lock wallet (clear seed from memory)
|
|
2134
|
+
*
|
|
2135
|
+
* SECURITY NOTE: JavaScript strings are immutable and cannot be overwritten
|
|
2136
|
+
* in place. Setting `this.currentSeed = null` removes the reference, but
|
|
2137
|
+
* the original string may persist in memory until garbage collected.
|
|
2138
|
+
* There is no reliable way to zero out a JS string.
|
|
2139
|
+
*
|
|
2140
|
+
* TODO: In a future version, store the seed as a Uint8Array instead of a
|
|
2141
|
+
* string. Uint8Array contents can be explicitly zeroed (e.g.,
|
|
2142
|
+
* `seedBytes.fill(0)`) before releasing the reference, which provides
|
|
2143
|
+
* stronger guarantees that sensitive material is scrubbed from memory.
|
|
2727
2144
|
*/
|
|
2728
2145
|
lock() {
|
|
2729
2146
|
this.currentSeed = null;
|
|
@@ -2781,9 +2198,9 @@ var WalletManager = class _WalletManager {
|
|
|
2781
2198
|
if (!this.derivedAddress) {
|
|
2782
2199
|
throw new Error("Wallet not initialized");
|
|
2783
2200
|
}
|
|
2784
|
-
const
|
|
2201
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2785
2202
|
const client = createPublicClient({
|
|
2786
|
-
chain
|
|
2203
|
+
chain,
|
|
2787
2204
|
transport: http(this.config.rpcUrl, {
|
|
2788
2205
|
timeout: 15e3,
|
|
2789
2206
|
// 15 second timeout
|
|
@@ -2805,9 +2222,9 @@ var WalletManager = class _WalletManager {
|
|
|
2805
2222
|
* Create viem public client for the current network
|
|
2806
2223
|
*/
|
|
2807
2224
|
getPublicClient() {
|
|
2808
|
-
const
|
|
2225
|
+
const chain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2809
2226
|
return createPublicClient({
|
|
2810
|
-
chain
|
|
2227
|
+
chain,
|
|
2811
2228
|
transport: http(this.config.rpcUrl, {
|
|
2812
2229
|
timeout: 15e3,
|
|
2813
2230
|
// 15 second timeout
|
|
@@ -2861,11 +2278,11 @@ var WalletManager = class _WalletManager {
|
|
|
2861
2278
|
*
|
|
2862
2279
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2863
2280
|
*/
|
|
2864
|
-
static async deriveAddressForChainAsync(seed,
|
|
2865
|
-
if (
|
|
2281
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
2282
|
+
if (chain === "ethereum") {
|
|
2866
2283
|
try {
|
|
2867
2284
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2868
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
2285
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2869
2286
|
return result2.address;
|
|
2870
2287
|
} catch (error) {
|
|
2871
2288
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2873,7 +2290,7 @@ var WalletManager = class _WalletManager {
|
|
|
2873
2290
|
}
|
|
2874
2291
|
}
|
|
2875
2292
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2876
|
-
const result = await wdkService.deriveAddress(seed,
|
|
2293
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2877
2294
|
return result.address;
|
|
2878
2295
|
}
|
|
2879
2296
|
/**
|
|
@@ -2882,14 +2299,14 @@ var WalletManager = class _WalletManager {
|
|
|
2882
2299
|
*
|
|
2883
2300
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2884
2301
|
*/
|
|
2885
|
-
static deriveAddressForChain(seed,
|
|
2886
|
-
if (
|
|
2302
|
+
static deriveAddressForChain(seed, chain) {
|
|
2303
|
+
if (chain === "ethereum") {
|
|
2887
2304
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2888
2305
|
const ethNode = HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2889
2306
|
return ethNode.address;
|
|
2890
2307
|
}
|
|
2891
2308
|
throw new Error(
|
|
2892
|
-
`Sync derivation not supported for ${
|
|
2309
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2893
2310
|
);
|
|
2894
2311
|
}
|
|
2895
2312
|
/**
|
|
@@ -2921,9 +2338,9 @@ var WalletManager = class _WalletManager {
|
|
|
2921
2338
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2922
2339
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2923
2340
|
const addresses = {};
|
|
2924
|
-
for (const [
|
|
2925
|
-
if (enabledChainsSet.has(
|
|
2926
|
-
addresses[
|
|
2341
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
2342
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
2343
|
+
addresses[chain] = address;
|
|
2927
2344
|
}
|
|
2928
2345
|
}
|
|
2929
2346
|
this.derivedAddresses = addresses;
|
|
@@ -2940,7 +2357,6 @@ var WalletManager = class _WalletManager {
|
|
|
2940
2357
|
async saveAddressesToStorage(addresses) {
|
|
2941
2358
|
try {
|
|
2942
2359
|
await this.storage.setItem(STORAGE_KEYS.DERIVED_ADDRESSES, JSON.stringify(addresses));
|
|
2943
|
-
console.log("Saved derived addresses to storage:", Object.keys(addresses));
|
|
2944
2360
|
} catch (error) {
|
|
2945
2361
|
console.warn("Failed to save addresses to storage:", error);
|
|
2946
2362
|
}
|
|
@@ -2964,10 +2380,10 @@ var WalletManager = class _WalletManager {
|
|
|
2964
2380
|
*/
|
|
2965
2381
|
normalizeAddresses(addresses) {
|
|
2966
2382
|
const normalized = {};
|
|
2967
|
-
for (const [
|
|
2383
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2968
2384
|
const addr = this.normalizeAddress(value);
|
|
2969
2385
|
if (addr) {
|
|
2970
|
-
normalized[
|
|
2386
|
+
normalized[chain] = addr;
|
|
2971
2387
|
}
|
|
2972
2388
|
}
|
|
2973
2389
|
return normalized;
|
|
@@ -2980,9 +2396,7 @@ var WalletManager = class _WalletManager {
|
|
|
2980
2396
|
const stored = await this.storage.getItem(STORAGE_KEYS.DERIVED_ADDRESSES);
|
|
2981
2397
|
if (stored) {
|
|
2982
2398
|
const rawAddresses = JSON.parse(stored);
|
|
2983
|
-
console.log("[WalletManager] Raw addresses from storage:", rawAddresses);
|
|
2984
2399
|
const addresses = this.normalizeAddresses(rawAddresses);
|
|
2985
|
-
console.log("[WalletManager] Normalized addresses:", addresses);
|
|
2986
2400
|
await this.saveAddressesToStorage(addresses);
|
|
2987
2401
|
return addresses;
|
|
2988
2402
|
}
|
|
@@ -3007,11 +2421,8 @@ var WalletManager = class _WalletManager {
|
|
|
3007
2421
|
if (storedAddresses && Object.keys(storedAddresses).length > 1) {
|
|
3008
2422
|
const expectedEthAddress = _WalletManager.deriveAddress(this.currentSeed);
|
|
3009
2423
|
if (storedAddresses.ethereum === expectedEthAddress) {
|
|
3010
|
-
console.log("Using addresses from storage (verified by Ethereum address)");
|
|
3011
2424
|
this.derivedAddresses = storedAddresses;
|
|
3012
2425
|
return storedAddresses;
|
|
3013
|
-
} else {
|
|
3014
|
-
console.log("Stored addresses do not match current seed, re-deriving...");
|
|
3015
2426
|
}
|
|
3016
2427
|
}
|
|
3017
2428
|
return await this.deriveAllAddressesWithWdk();
|
|
@@ -3020,20 +2431,18 @@ var WalletManager = class _WalletManager {
|
|
|
3020
2431
|
* Get address for a specific chain
|
|
3021
2432
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
3022
2433
|
*/
|
|
3023
|
-
getAddressForChain(
|
|
3024
|
-
const cachedValue = this.derivedAddresses[
|
|
2434
|
+
getAddressForChain(chain) {
|
|
2435
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
3025
2436
|
if (cachedValue) {
|
|
3026
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
3027
2437
|
const addr = this.normalizeAddress(cachedValue);
|
|
3028
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) normalized:`, addr);
|
|
3029
2438
|
if (addr) {
|
|
3030
|
-
this.derivedAddresses[
|
|
2439
|
+
this.derivedAddresses[chain] = addr;
|
|
3031
2440
|
return addr;
|
|
3032
2441
|
}
|
|
3033
2442
|
}
|
|
3034
|
-
if (
|
|
3035
|
-
this.derivedAddresses[
|
|
3036
|
-
return this.derivedAddresses[
|
|
2443
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
2444
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
2445
|
+
return this.derivedAddresses[chain];
|
|
3037
2446
|
}
|
|
3038
2447
|
return null;
|
|
3039
2448
|
}
|
|
@@ -3046,11 +2455,11 @@ var WalletManager = class _WalletManager {
|
|
|
3046
2455
|
/**
|
|
3047
2456
|
* Set the selected chain
|
|
3048
2457
|
*/
|
|
3049
|
-
setSelectedChain(
|
|
3050
|
-
if (!this.config.enabledChains.includes(
|
|
3051
|
-
throw new Error(`Chain ${
|
|
2458
|
+
setSelectedChain(chain) {
|
|
2459
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
2460
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
3052
2461
|
}
|
|
3053
|
-
this.selectedChain =
|
|
2462
|
+
this.selectedChain = chain;
|
|
3054
2463
|
}
|
|
3055
2464
|
/**
|
|
3056
2465
|
* Get the currently selected chain
|
|
@@ -3067,22 +2476,22 @@ var WalletManager = class _WalletManager {
|
|
|
3067
2476
|
/**
|
|
3068
2477
|
* Get chain configuration
|
|
3069
2478
|
*/
|
|
3070
|
-
getChainConfig(
|
|
3071
|
-
return getNetworkConfig(
|
|
2479
|
+
getChainConfig(chain) {
|
|
2480
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
3072
2481
|
}
|
|
3073
2482
|
/**
|
|
3074
2483
|
* Fetch balance for a specific chain
|
|
3075
2484
|
* Note: Currently only Ethereum is implemented
|
|
3076
2485
|
*/
|
|
3077
|
-
async fetchBalanceForChain(
|
|
3078
|
-
const address = this.getAddressForChain(
|
|
2486
|
+
async fetchBalanceForChain(chain) {
|
|
2487
|
+
const address = this.getAddressForChain(chain);
|
|
3079
2488
|
if (!address) {
|
|
3080
|
-
throw new Error(`No address for chain ${
|
|
2489
|
+
throw new Error(`No address for chain ${chain}`);
|
|
3081
2490
|
}
|
|
3082
|
-
const networkConfig = this.getChainConfig(
|
|
2491
|
+
const networkConfig = this.getChainConfig(chain);
|
|
3083
2492
|
let balance = "0";
|
|
3084
2493
|
const tokenBalances = {};
|
|
3085
|
-
if (
|
|
2494
|
+
if (chain === "ethereum") {
|
|
3086
2495
|
const viemChain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
3087
2496
|
const isTestnet = this.config.network !== "mainnet";
|
|
3088
2497
|
const client = createPublicClient({
|
|
@@ -3129,7 +2538,7 @@ var WalletManager = class _WalletManager {
|
|
|
3129
2538
|
} else if (usdtResult.status === "rejected") {
|
|
3130
2539
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
3131
2540
|
}
|
|
3132
|
-
} else if (
|
|
2541
|
+
} else if (chain === "bitcoin") {
|
|
3133
2542
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
3134
2543
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
3135
2544
|
"https://mempool.space/testnet/api",
|
|
@@ -3152,16 +2561,14 @@ var WalletManager = class _WalletManager {
|
|
|
3152
2561
|
const mempoolSpent = data.mempool_stats?.spent_txo_sum || 0;
|
|
3153
2562
|
const satoshis = chainFunded - chainSpent + (mempoolFunded - mempoolSpent);
|
|
3154
2563
|
balance = (satoshis / 1e8).toFixed(8);
|
|
3155
|
-
console.log(`Bitcoin balance for ${address}: ${balance} BTC (${satoshis} sats) via ${apiUrl}`);
|
|
3156
2564
|
break;
|
|
3157
2565
|
}
|
|
3158
|
-
console.log(`No transactions found on ${apiUrl}, trying next...`);
|
|
3159
2566
|
}
|
|
3160
2567
|
} catch (error) {
|
|
3161
2568
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
3162
2569
|
}
|
|
3163
2570
|
}
|
|
3164
|
-
} else if (
|
|
2571
|
+
} else if (chain === "solana") {
|
|
3165
2572
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
3166
2573
|
try {
|
|
3167
2574
|
const response = await fetch(rpcUrl, {
|
|
@@ -3181,7 +2588,7 @@ var WalletManager = class _WalletManager {
|
|
|
3181
2588
|
}
|
|
3182
2589
|
}
|
|
3183
2590
|
} catch (error) {
|
|
3184
|
-
console.warn(`Failed to fetch ${
|
|
2591
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3185
2592
|
}
|
|
3186
2593
|
const isTestnet = this.config.network !== "mainnet";
|
|
3187
2594
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -3215,7 +2622,7 @@ var WalletManager = class _WalletManager {
|
|
|
3215
2622
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
3216
2623
|
}
|
|
3217
2624
|
}
|
|
3218
|
-
} else if (
|
|
2625
|
+
} else if (chain === "tron") {
|
|
3219
2626
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
3220
2627
|
const baseUrl = tronConfig.rpcUrl;
|
|
3221
2628
|
try {
|
|
@@ -3244,9 +2651,9 @@ var WalletManager = class _WalletManager {
|
|
|
3244
2651
|
}
|
|
3245
2652
|
}
|
|
3246
2653
|
} catch (error) {
|
|
3247
|
-
console.warn(`Failed to fetch ${
|
|
2654
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3248
2655
|
}
|
|
3249
|
-
} else if (
|
|
2656
|
+
} else if (chain === "ton") {
|
|
3250
2657
|
const isTestnet = this.config.network !== "mainnet";
|
|
3251
2658
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
3252
2659
|
try {
|
|
@@ -3258,29 +2665,39 @@ var WalletManager = class _WalletManager {
|
|
|
3258
2665
|
if (data.ok && data.result !== void 0) {
|
|
3259
2666
|
const nanotons = BigInt(data.result);
|
|
3260
2667
|
balance = (Number(nanotons) / 1e9).toFixed(9);
|
|
3261
|
-
console.log(`TON balance for ${address}: ${balance} TON`);
|
|
3262
2668
|
}
|
|
3263
2669
|
}
|
|
3264
2670
|
} catch (error) {
|
|
3265
|
-
console.warn(`Failed to fetch ${
|
|
2671
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3266
2672
|
}
|
|
3267
2673
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
3268
2674
|
if (usdtJetton) {
|
|
3269
|
-
const
|
|
2675
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
3270
2676
|
try {
|
|
2677
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
3271
2678
|
const jettonResponse = await fetch(
|
|
3272
|
-
`${
|
|
2679
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
3273
2680
|
{ headers: { "Accept": "application/json" } }
|
|
3274
2681
|
);
|
|
3275
2682
|
if (jettonResponse.ok) {
|
|
3276
2683
|
const jettonData = await jettonResponse.json();
|
|
3277
|
-
const
|
|
3278
|
-
if (
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
2684
|
+
const balances = jettonData.balances;
|
|
2685
|
+
if (balances && balances.length > 0) {
|
|
2686
|
+
for (const jb of balances) {
|
|
2687
|
+
const jettonAddr = jb.jetton?.address;
|
|
2688
|
+
if (jettonAddr) {
|
|
2689
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2690
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2691
|
+
const rawBalance = jb.balance;
|
|
2692
|
+
if (rawBalance) {
|
|
2693
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2694
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2695
|
+
if (usdtAmount > 0) {
|
|
2696
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
break;
|
|
2700
|
+
}
|
|
3284
2701
|
}
|
|
3285
2702
|
}
|
|
3286
2703
|
}
|
|
@@ -3289,7 +2706,7 @@ var WalletManager = class _WalletManager {
|
|
|
3289
2706
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
3290
2707
|
}
|
|
3291
2708
|
}
|
|
3292
|
-
} else if (
|
|
2709
|
+
} else if (chain === "spark") {
|
|
3293
2710
|
try {
|
|
3294
2711
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
3295
2712
|
method: "POST",
|
|
@@ -3304,18 +2721,17 @@ var WalletManager = class _WalletManager {
|
|
|
3304
2721
|
const data = await response.json();
|
|
3305
2722
|
if (data.success && data.balance !== void 0) {
|
|
3306
2723
|
balance = (parseFloat(data.balance) / 1e8).toFixed(8);
|
|
3307
|
-
console.log(`Spark balance for ${address}: ${balance} BTC`);
|
|
3308
2724
|
}
|
|
3309
2725
|
}
|
|
3310
2726
|
} catch (error) {
|
|
3311
|
-
console.warn(`Failed to fetch ${
|
|
2727
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
3312
2728
|
}
|
|
3313
2729
|
}
|
|
3314
|
-
const priceUsd = await getPriceForChain(
|
|
2730
|
+
const priceUsd = await getPriceForChain(chain);
|
|
3315
2731
|
const balanceNum = parseFloat(balance) || 0;
|
|
3316
2732
|
const balanceUsd = balanceNum * priceUsd;
|
|
3317
2733
|
return {
|
|
3318
|
-
chain
|
|
2734
|
+
chain,
|
|
3319
2735
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
3320
2736
|
balance,
|
|
3321
2737
|
balanceUsd,
|
|
@@ -3325,28 +2741,29 @@ var WalletManager = class _WalletManager {
|
|
|
3325
2741
|
};
|
|
3326
2742
|
}
|
|
3327
2743
|
/**
|
|
3328
|
-
* Fetch balances for all enabled chains
|
|
2744
|
+
* Fetch balances for all enabled chains in parallel.
|
|
2745
|
+
* Uses Promise.allSettled so that one chain failing does not block others.
|
|
3329
2746
|
*/
|
|
3330
2747
|
async fetchAllBalances() {
|
|
3331
|
-
const
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
const networkConfig = this.getChainConfig(chain2);
|
|
3339
|
-
balances.push({
|
|
3340
|
-
chain: chain2,
|
|
3341
|
-
symbol: networkConfig.nativeCurrency.symbol,
|
|
3342
|
-
balance: "0",
|
|
3343
|
-
balanceUsd: 0,
|
|
3344
|
-
address: this.getAddressForChain(chain2) || "",
|
|
3345
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
3346
|
-
});
|
|
2748
|
+
const results = await Promise.allSettled(
|
|
2749
|
+
this.config.enabledChains.map((chain) => this.fetchBalanceForChain(chain))
|
|
2750
|
+
);
|
|
2751
|
+
return results.map((result, index) => {
|
|
2752
|
+
const chain = this.config.enabledChains[index];
|
|
2753
|
+
if (result.status === "fulfilled") {
|
|
2754
|
+
return result.value;
|
|
3347
2755
|
}
|
|
3348
|
-
|
|
3349
|
-
|
|
2756
|
+
console.error(`Failed to fetch balance for ${chain}:`, result.reason);
|
|
2757
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2758
|
+
return {
|
|
2759
|
+
chain,
|
|
2760
|
+
symbol: networkConfig.nativeCurrency.symbol,
|
|
2761
|
+
balance: "0",
|
|
2762
|
+
balanceUsd: 0,
|
|
2763
|
+
address: this.getAddressForChain(chain) || "",
|
|
2764
|
+
decimals: networkConfig.nativeCurrency.decimals
|
|
2765
|
+
};
|
|
2766
|
+
});
|
|
3350
2767
|
}
|
|
3351
2768
|
/**
|
|
3352
2769
|
* Get extended wallet state with multi-chain info
|
|
@@ -3371,13 +2788,13 @@ var WalletManager = class _WalletManager {
|
|
|
3371
2788
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
3372
2789
|
* @returns Transaction result with hash and status
|
|
3373
2790
|
*/
|
|
3374
|
-
async sendTransaction(
|
|
2791
|
+
async sendTransaction(chain, to, amount, token) {
|
|
3375
2792
|
if (!this.currentSeed) {
|
|
3376
2793
|
return { success: false, error: "Wallet is locked" };
|
|
3377
2794
|
}
|
|
3378
|
-
const fromAddress = this.getAddressForChain(
|
|
2795
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
3379
2796
|
if (!fromAddress) {
|
|
3380
|
-
return { success: false, error: `No address for chain ${
|
|
2797
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
3381
2798
|
}
|
|
3382
2799
|
try {
|
|
3383
2800
|
const headers = {
|
|
@@ -3391,7 +2808,7 @@ var WalletManager = class _WalletManager {
|
|
|
3391
2808
|
headers,
|
|
3392
2809
|
body: JSON.stringify({
|
|
3393
2810
|
seed: this.currentSeed,
|
|
3394
|
-
chain
|
|
2811
|
+
chain,
|
|
3395
2812
|
to,
|
|
3396
2813
|
amount,
|
|
3397
2814
|
token,
|
|
@@ -3400,12 +2817,11 @@ var WalletManager = class _WalletManager {
|
|
|
3400
2817
|
});
|
|
3401
2818
|
if (response.ok) {
|
|
3402
2819
|
const data = await response.json();
|
|
3403
|
-
console.log(`Transaction sent on ${chain2}:`, data);
|
|
3404
2820
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
3405
2821
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
3406
2822
|
txHash = txHash.hash;
|
|
3407
2823
|
}
|
|
3408
|
-
if (
|
|
2824
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
3409
2825
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
3410
2826
|
}
|
|
3411
2827
|
return {
|
|
@@ -3414,7 +2830,7 @@ var WalletManager = class _WalletManager {
|
|
|
3414
2830
|
from: fromAddress,
|
|
3415
2831
|
to,
|
|
3416
2832
|
amount,
|
|
3417
|
-
chain
|
|
2833
|
+
chain
|
|
3418
2834
|
};
|
|
3419
2835
|
}
|
|
3420
2836
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -3423,7 +2839,7 @@ var WalletManager = class _WalletManager {
|
|
|
3423
2839
|
error: errorData.error || `HTTP ${response.status}`
|
|
3424
2840
|
};
|
|
3425
2841
|
} catch (error) {
|
|
3426
|
-
console.error(`Transaction failed on ${
|
|
2842
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
3427
2843
|
return {
|
|
3428
2844
|
success: false,
|
|
3429
2845
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -3433,7 +2849,7 @@ var WalletManager = class _WalletManager {
|
|
|
3433
2849
|
/**
|
|
3434
2850
|
* Estimate transaction fee using Tether WDK
|
|
3435
2851
|
*/
|
|
3436
|
-
async estimateFee(
|
|
2852
|
+
async estimateFee(chain, to, amount, token) {
|
|
3437
2853
|
try {
|
|
3438
2854
|
const headers = {
|
|
3439
2855
|
"Content-Type": "application/json"
|
|
@@ -3445,7 +2861,7 @@ var WalletManager = class _WalletManager {
|
|
|
3445
2861
|
method: "POST",
|
|
3446
2862
|
headers,
|
|
3447
2863
|
body: JSON.stringify({
|
|
3448
|
-
chain
|
|
2864
|
+
chain,
|
|
3449
2865
|
to,
|
|
3450
2866
|
amount,
|
|
3451
2867
|
token,
|
|
@@ -3469,14 +2885,6 @@ var WalletManager = class _WalletManager {
|
|
|
3469
2885
|
}
|
|
3470
2886
|
}
|
|
3471
2887
|
};
|
|
3472
|
-
/*! Bundled license information:
|
|
3473
|
-
|
|
3474
|
-
@scure/base/index.js:
|
|
3475
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3476
|
-
|
|
3477
|
-
@scure/bip32/index.js:
|
|
3478
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
3479
|
-
*/
|
|
3480
2888
|
|
|
3481
2889
|
export { SUPPORTED_CHAINS, WalletManager, ZubariWallet };
|
|
3482
2890
|
//# sourceMappingURL=index.mjs.map
|