@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/react/index.js
CHANGED
|
@@ -4,11 +4,8 @@ var react = require('react');
|
|
|
4
4
|
var ethers = require('ethers');
|
|
5
5
|
var bip39 = require('@scure/bip39');
|
|
6
6
|
var english = require('@scure/bip39/wordlists/english');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var legacy_js = require('@noble/hashes/legacy.js');
|
|
10
|
-
var sha2_js = require('@noble/hashes/sha2.js');
|
|
11
|
-
var utils_js = require('@noble/hashes/utils.js');
|
|
7
|
+
var bip32 = require('@scure/bip32');
|
|
8
|
+
var base = require('@scure/base');
|
|
12
9
|
var sha256 = require('@noble/hashes/sha256');
|
|
13
10
|
var ripemd160 = require('@noble/hashes/ripemd160');
|
|
14
11
|
var viem = require('viem');
|
|
@@ -137,8 +134,8 @@ var TESTNET_NETWORKS = {
|
|
|
137
134
|
var USDT_ADDRESSES = {
|
|
138
135
|
ethereum: {
|
|
139
136
|
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
140
|
-
testnet: "
|
|
141
|
-
// Sepolia
|
|
137
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
138
|
+
// Sepolia (Test Tether USD)
|
|
142
139
|
},
|
|
143
140
|
tron: {
|
|
144
141
|
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
@@ -156,7 +153,13 @@ var USDT_ADDRESSES = {
|
|
|
156
153
|
}
|
|
157
154
|
};
|
|
158
155
|
var DERIVATION_PATHS = {
|
|
159
|
-
|
|
156
|
+
bitcoin: "m/84'/0'/0'/0",
|
|
157
|
+
ethereum: "m/44'/60'/0'/0",
|
|
158
|
+
ton: "m/44'/607'/0'",
|
|
159
|
+
tron: "m/44'/195'/0'/0",
|
|
160
|
+
solana: "m/44'/501'/0'",
|
|
161
|
+
spark: "m/44'/998'/0'/0"
|
|
162
|
+
};
|
|
160
163
|
function getNetworkConfig(network, isTestnet = false) {
|
|
161
164
|
const mainnetConfig = NETWORKS[network];
|
|
162
165
|
if (!isTestnet) return mainnetConfig;
|
|
@@ -174,8 +177,27 @@ var WdkApiClient = class {
|
|
|
174
177
|
constructor(config) {
|
|
175
178
|
this.config = {
|
|
176
179
|
baseUrl: config.baseUrl,
|
|
177
|
-
timeout: config.timeout || 3e4
|
|
180
|
+
timeout: config.timeout || 3e4,
|
|
181
|
+
authToken: config.authToken
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Set or update the auth token for authenticated requests
|
|
186
|
+
*/
|
|
187
|
+
setAuthToken(token) {
|
|
188
|
+
this.config.authToken = token;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Build headers for API requests, including Authorization when available
|
|
192
|
+
*/
|
|
193
|
+
getHeaders() {
|
|
194
|
+
const headers = {
|
|
195
|
+
"Content-Type": "application/json"
|
|
178
196
|
};
|
|
197
|
+
if (this.config.authToken) {
|
|
198
|
+
headers["Authorization"] = `Bearer ${this.config.authToken}`;
|
|
199
|
+
}
|
|
200
|
+
return headers;
|
|
179
201
|
}
|
|
180
202
|
/**
|
|
181
203
|
* Generate a new BIP-39 seed phrase using Tether WDK
|
|
@@ -184,9 +206,7 @@ var WdkApiClient = class {
|
|
|
184
206
|
try {
|
|
185
207
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/generate-seed`, {
|
|
186
208
|
method: "POST",
|
|
187
|
-
headers:
|
|
188
|
-
"Content-Type": "application/json"
|
|
189
|
-
}
|
|
209
|
+
headers: this.getHeaders()
|
|
190
210
|
});
|
|
191
211
|
return await response.json();
|
|
192
212
|
} catch (error) {
|
|
@@ -203,9 +223,7 @@ var WdkApiClient = class {
|
|
|
203
223
|
try {
|
|
204
224
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/validate-seed`, {
|
|
205
225
|
method: "POST",
|
|
206
|
-
headers:
|
|
207
|
-
"Content-Type": "application/json"
|
|
208
|
-
},
|
|
226
|
+
headers: this.getHeaders(),
|
|
209
227
|
body: JSON.stringify({ seed })
|
|
210
228
|
});
|
|
211
229
|
return await response.json();
|
|
@@ -219,14 +237,12 @@ var WdkApiClient = class {
|
|
|
219
237
|
/**
|
|
220
238
|
* Derive address for a specific chain using Tether WDK
|
|
221
239
|
*/
|
|
222
|
-
async deriveAddress(seed,
|
|
240
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
223
241
|
try {
|
|
224
242
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
225
243
|
method: "POST",
|
|
226
|
-
headers:
|
|
227
|
-
|
|
228
|
-
},
|
|
229
|
-
body: JSON.stringify({ seed, chain: chain2, network })
|
|
244
|
+
headers: this.getHeaders(),
|
|
245
|
+
body: JSON.stringify({ seed, chain, network })
|
|
230
246
|
});
|
|
231
247
|
return await response.json();
|
|
232
248
|
} catch (error) {
|
|
@@ -243,9 +259,7 @@ var WdkApiClient = class {
|
|
|
243
259
|
try {
|
|
244
260
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
|
|
245
261
|
method: "POST",
|
|
246
|
-
headers:
|
|
247
|
-
"Content-Type": "application/json"
|
|
248
|
-
},
|
|
262
|
+
headers: this.getHeaders(),
|
|
249
263
|
body: JSON.stringify({ seed, network })
|
|
250
264
|
});
|
|
251
265
|
return await response.json();
|
|
@@ -259,14 +273,12 @@ var WdkApiClient = class {
|
|
|
259
273
|
/**
|
|
260
274
|
* Send a transaction on a specific chain using Tether WDK
|
|
261
275
|
*/
|
|
262
|
-
async sendTransaction(seed,
|
|
276
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
263
277
|
try {
|
|
264
278
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
265
279
|
method: "POST",
|
|
266
|
-
headers:
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
body: JSON.stringify({ seed, chain: chain2, to, amount, network })
|
|
280
|
+
headers: this.getHeaders(),
|
|
281
|
+
body: JSON.stringify({ seed, chain, to, amount, network })
|
|
270
282
|
});
|
|
271
283
|
return await response.json();
|
|
272
284
|
} catch (error) {
|
|
@@ -280,14 +292,12 @@ var WdkApiClient = class {
|
|
|
280
292
|
* Get transaction history for an address on a specific chain
|
|
281
293
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
282
294
|
*/
|
|
283
|
-
async getTransactionHistory(seed,
|
|
295
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
284
296
|
try {
|
|
285
297
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
286
298
|
method: "POST",
|
|
287
|
-
headers:
|
|
288
|
-
|
|
289
|
-
},
|
|
290
|
-
body: JSON.stringify({ seed, chain: chain2, network, limit })
|
|
299
|
+
headers: this.getHeaders(),
|
|
300
|
+
body: JSON.stringify({ seed, chain, network, limit })
|
|
291
301
|
});
|
|
292
302
|
return await response.json();
|
|
293
303
|
} catch (error) {
|
|
@@ -301,14 +311,12 @@ var WdkApiClient = class {
|
|
|
301
311
|
* Get transaction status by hash
|
|
302
312
|
* Fetches from blockchain explorers to check confirmation status
|
|
303
313
|
*/
|
|
304
|
-
async getTransactionStatus(txHash,
|
|
314
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
305
315
|
try {
|
|
306
316
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
307
317
|
method: "POST",
|
|
308
|
-
headers:
|
|
309
|
-
|
|
310
|
-
},
|
|
311
|
-
body: JSON.stringify({ txHash, chain: chain2, network })
|
|
318
|
+
headers: this.getHeaders(),
|
|
319
|
+
body: JSON.stringify({ txHash, chain, network })
|
|
312
320
|
});
|
|
313
321
|
return await response.json();
|
|
314
322
|
} catch (error) {
|
|
@@ -321,605 +329,23 @@ var WdkApiClient = class {
|
|
|
321
329
|
};
|
|
322
330
|
var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
323
331
|
var wdkApiClient = null;
|
|
324
|
-
function getWdkApiClient(baseUrl) {
|
|
332
|
+
function getWdkApiClient(baseUrl, authToken) {
|
|
325
333
|
if (!wdkApiClient || baseUrl && wdkApiClient["config"].baseUrl !== baseUrl) {
|
|
326
334
|
wdkApiClient = new WdkApiClient({
|
|
327
|
-
baseUrl: baseUrl || DEFAULT_API_URL
|
|
335
|
+
baseUrl: baseUrl || DEFAULT_API_URL,
|
|
336
|
+
authToken
|
|
328
337
|
});
|
|
329
338
|
}
|
|
330
339
|
return wdkApiClient;
|
|
331
340
|
}
|
|
332
|
-
|
|
333
|
-
// node_modules/@scure/base/index.js
|
|
334
|
-
function isBytes(a) {
|
|
335
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
336
|
-
}
|
|
337
|
-
function isArrayOf(isString, arr) {
|
|
338
|
-
if (!Array.isArray(arr))
|
|
339
|
-
return false;
|
|
340
|
-
if (arr.length === 0)
|
|
341
|
-
return true;
|
|
342
|
-
if (isString) {
|
|
343
|
-
return arr.every((item) => typeof item === "string");
|
|
344
|
-
} else {
|
|
345
|
-
return arr.every((item) => Number.isSafeInteger(item));
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
function afn(input) {
|
|
349
|
-
if (typeof input !== "function")
|
|
350
|
-
throw new Error("function expected");
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
function astr(label, input) {
|
|
354
|
-
if (typeof input !== "string")
|
|
355
|
-
throw new Error(`${label}: string expected`);
|
|
356
|
-
return true;
|
|
357
|
-
}
|
|
358
|
-
function anumber(n) {
|
|
359
|
-
if (!Number.isSafeInteger(n))
|
|
360
|
-
throw new Error(`invalid integer: ${n}`);
|
|
361
|
-
}
|
|
362
|
-
function aArr(input) {
|
|
363
|
-
if (!Array.isArray(input))
|
|
364
|
-
throw new Error("array expected");
|
|
365
|
-
}
|
|
366
|
-
function astrArr(label, input) {
|
|
367
|
-
if (!isArrayOf(true, input))
|
|
368
|
-
throw new Error(`${label}: array of strings expected`);
|
|
369
|
-
}
|
|
370
|
-
function anumArr(label, input) {
|
|
371
|
-
if (!isArrayOf(false, input))
|
|
372
|
-
throw new Error(`${label}: array of numbers expected`);
|
|
373
|
-
}
|
|
374
|
-
// @__NO_SIDE_EFFECTS__
|
|
375
|
-
function chain(...args) {
|
|
376
|
-
const id = (a) => a;
|
|
377
|
-
const wrap = (a, b) => (c) => a(b(c));
|
|
378
|
-
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
379
|
-
const decode = args.map((x) => x.decode).reduce(wrap, id);
|
|
380
|
-
return { encode, decode };
|
|
381
|
-
}
|
|
382
|
-
// @__NO_SIDE_EFFECTS__
|
|
383
|
-
function alphabet(letters) {
|
|
384
|
-
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
385
|
-
const len = lettersA.length;
|
|
386
|
-
astrArr("alphabet", lettersA);
|
|
387
|
-
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
388
|
-
return {
|
|
389
|
-
encode: (digits) => {
|
|
390
|
-
aArr(digits);
|
|
391
|
-
return digits.map((i) => {
|
|
392
|
-
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
393
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
394
|
-
return lettersA[i];
|
|
395
|
-
});
|
|
396
|
-
},
|
|
397
|
-
decode: (input) => {
|
|
398
|
-
aArr(input);
|
|
399
|
-
return input.map((letter) => {
|
|
400
|
-
astr("alphabet.decode", letter);
|
|
401
|
-
const i = indexes.get(letter);
|
|
402
|
-
if (i === void 0)
|
|
403
|
-
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
404
|
-
return i;
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
// @__NO_SIDE_EFFECTS__
|
|
410
|
-
function join(separator = "") {
|
|
411
|
-
astr("join", separator);
|
|
412
|
-
return {
|
|
413
|
-
encode: (from) => {
|
|
414
|
-
astrArr("join.decode", from);
|
|
415
|
-
return from.join(separator);
|
|
416
|
-
},
|
|
417
|
-
decode: (to) => {
|
|
418
|
-
astr("join.decode", to);
|
|
419
|
-
return to.split(separator);
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
function convertRadix(data, from, to) {
|
|
424
|
-
if (from < 2)
|
|
425
|
-
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
|
|
426
|
-
if (to < 2)
|
|
427
|
-
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
|
|
428
|
-
aArr(data);
|
|
429
|
-
if (!data.length)
|
|
430
|
-
return [];
|
|
431
|
-
let pos = 0;
|
|
432
|
-
const res = [];
|
|
433
|
-
const digits = Array.from(data, (d) => {
|
|
434
|
-
anumber(d);
|
|
435
|
-
if (d < 0 || d >= from)
|
|
436
|
-
throw new Error(`invalid integer: ${d}`);
|
|
437
|
-
return d;
|
|
438
|
-
});
|
|
439
|
-
const dlen = digits.length;
|
|
440
|
-
while (true) {
|
|
441
|
-
let carry = 0;
|
|
442
|
-
let done = true;
|
|
443
|
-
for (let i = pos; i < dlen; i++) {
|
|
444
|
-
const digit = digits[i];
|
|
445
|
-
const fromCarry = from * carry;
|
|
446
|
-
const digitBase = fromCarry + digit;
|
|
447
|
-
if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
|
|
448
|
-
throw new Error("convertRadix: carry overflow");
|
|
449
|
-
}
|
|
450
|
-
const div = digitBase / to;
|
|
451
|
-
carry = digitBase % to;
|
|
452
|
-
const rounded = Math.floor(div);
|
|
453
|
-
digits[i] = rounded;
|
|
454
|
-
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
|
|
455
|
-
throw new Error("convertRadix: carry overflow");
|
|
456
|
-
if (!done)
|
|
457
|
-
continue;
|
|
458
|
-
else if (!rounded)
|
|
459
|
-
pos = i;
|
|
460
|
-
else
|
|
461
|
-
done = false;
|
|
462
|
-
}
|
|
463
|
-
res.push(carry);
|
|
464
|
-
if (done)
|
|
465
|
-
break;
|
|
466
|
-
}
|
|
467
|
-
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
|
|
468
|
-
res.push(0);
|
|
469
|
-
return res.reverse();
|
|
470
|
-
}
|
|
471
|
-
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
472
|
-
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
473
|
-
var powers = /* @__PURE__ */ (() => {
|
|
474
|
-
let res = [];
|
|
475
|
-
for (let i = 0; i < 40; i++)
|
|
476
|
-
res.push(2 ** i);
|
|
477
|
-
return res;
|
|
478
|
-
})();
|
|
479
|
-
function convertRadix2(data, from, to, padding) {
|
|
480
|
-
aArr(data);
|
|
481
|
-
if (from <= 0 || from > 32)
|
|
482
|
-
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
483
|
-
if (to <= 0 || to > 32)
|
|
484
|
-
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
485
|
-
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
486
|
-
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
487
|
-
}
|
|
488
|
-
let carry = 0;
|
|
489
|
-
let pos = 0;
|
|
490
|
-
const max = powers[from];
|
|
491
|
-
const mask = powers[to] - 1;
|
|
492
|
-
const res = [];
|
|
493
|
-
for (const n of data) {
|
|
494
|
-
anumber(n);
|
|
495
|
-
if (n >= max)
|
|
496
|
-
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
497
|
-
carry = carry << from | n;
|
|
498
|
-
if (pos + from > 32)
|
|
499
|
-
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
500
|
-
pos += from;
|
|
501
|
-
for (; pos >= to; pos -= to)
|
|
502
|
-
res.push((carry >> pos - to & mask) >>> 0);
|
|
503
|
-
const pow = powers[pos];
|
|
504
|
-
if (pow === void 0)
|
|
505
|
-
throw new Error("invalid carry");
|
|
506
|
-
carry &= pow - 1;
|
|
507
|
-
}
|
|
508
|
-
carry = carry << to - pos & mask;
|
|
509
|
-
if (!padding && pos >= from)
|
|
510
|
-
throw new Error("Excess padding");
|
|
511
|
-
if (!padding && carry > 0)
|
|
512
|
-
throw new Error(`Non-zero padding: ${carry}`);
|
|
513
|
-
if (padding && pos > 0)
|
|
514
|
-
res.push(carry >>> 0);
|
|
515
|
-
return res;
|
|
516
|
-
}
|
|
517
|
-
// @__NO_SIDE_EFFECTS__
|
|
518
|
-
function radix(num) {
|
|
519
|
-
anumber(num);
|
|
520
|
-
const _256 = 2 ** 8;
|
|
521
|
-
return {
|
|
522
|
-
encode: (bytes) => {
|
|
523
|
-
if (!isBytes(bytes))
|
|
524
|
-
throw new Error("radix.encode input should be Uint8Array");
|
|
525
|
-
return convertRadix(Array.from(bytes), _256, num);
|
|
526
|
-
},
|
|
527
|
-
decode: (digits) => {
|
|
528
|
-
anumArr("radix.decode", digits);
|
|
529
|
-
return Uint8Array.from(convertRadix(digits, num, _256));
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
// @__NO_SIDE_EFFECTS__
|
|
534
|
-
function radix2(bits, revPadding = false) {
|
|
535
|
-
anumber(bits);
|
|
536
|
-
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
537
|
-
throw new Error("radix2: carry overflow");
|
|
538
|
-
return {
|
|
539
|
-
encode: (bytes) => {
|
|
540
|
-
if (!isBytes(bytes))
|
|
541
|
-
throw new Error("radix2.encode input should be Uint8Array");
|
|
542
|
-
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
543
|
-
},
|
|
544
|
-
decode: (digits) => {
|
|
545
|
-
anumArr("radix2.decode", digits);
|
|
546
|
-
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
function unsafeWrapper(fn) {
|
|
551
|
-
afn(fn);
|
|
552
|
-
return function(...args) {
|
|
553
|
-
try {
|
|
554
|
-
return fn.apply(null, args);
|
|
555
|
-
} catch (e) {
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
function checksum(len, fn) {
|
|
560
|
-
anumber(len);
|
|
561
|
-
afn(fn);
|
|
562
|
-
return {
|
|
563
|
-
encode(data) {
|
|
564
|
-
if (!isBytes(data))
|
|
565
|
-
throw new Error("checksum.encode: input should be Uint8Array");
|
|
566
|
-
const sum = fn(data).slice(0, len);
|
|
567
|
-
const res = new Uint8Array(data.length + len);
|
|
568
|
-
res.set(data);
|
|
569
|
-
res.set(sum, data.length);
|
|
570
|
-
return res;
|
|
571
|
-
},
|
|
572
|
-
decode(data) {
|
|
573
|
-
if (!isBytes(data))
|
|
574
|
-
throw new Error("checksum.decode: input should be Uint8Array");
|
|
575
|
-
const payload = data.slice(0, -len);
|
|
576
|
-
const oldChecksum = data.slice(-len);
|
|
577
|
-
const newChecksum = fn(payload).slice(0, len);
|
|
578
|
-
for (let i = 0; i < len; i++)
|
|
579
|
-
if (newChecksum[i] !== oldChecksum[i])
|
|
580
|
-
throw new Error("Invalid checksum");
|
|
581
|
-
return payload;
|
|
582
|
-
}
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
|
|
586
|
-
var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
587
|
-
var createBase58check = (sha2563) => /* @__PURE__ */ chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
588
|
-
var base58check = createBase58check;
|
|
589
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
590
|
-
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
591
|
-
function bech32Polymod(pre) {
|
|
592
|
-
const b = pre >> 25;
|
|
593
|
-
let chk = (pre & 33554431) << 5;
|
|
594
|
-
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
595
|
-
if ((b >> i & 1) === 1)
|
|
596
|
-
chk ^= POLYMOD_GENERATORS[i];
|
|
597
|
-
}
|
|
598
|
-
return chk;
|
|
599
|
-
}
|
|
600
|
-
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
601
|
-
const len = prefix.length;
|
|
602
|
-
let chk = 1;
|
|
603
|
-
for (let i = 0; i < len; i++) {
|
|
604
|
-
const c = prefix.charCodeAt(i);
|
|
605
|
-
if (c < 33 || c > 126)
|
|
606
|
-
throw new Error(`Invalid prefix (${prefix})`);
|
|
607
|
-
chk = bech32Polymod(chk) ^ c >> 5;
|
|
608
|
-
}
|
|
609
|
-
chk = bech32Polymod(chk);
|
|
610
|
-
for (let i = 0; i < len; i++)
|
|
611
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
612
|
-
for (let v of words)
|
|
613
|
-
chk = bech32Polymod(chk) ^ v;
|
|
614
|
-
for (let i = 0; i < 6; i++)
|
|
615
|
-
chk = bech32Polymod(chk);
|
|
616
|
-
chk ^= encodingConst;
|
|
617
|
-
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
618
|
-
}
|
|
619
|
-
// @__NO_SIDE_EFFECTS__
|
|
620
|
-
function genBech32(encoding) {
|
|
621
|
-
const ENCODING_CONST = 1 ;
|
|
622
|
-
const _words = /* @__PURE__ */ radix2(5);
|
|
623
|
-
const fromWords = _words.decode;
|
|
624
|
-
const toWords = _words.encode;
|
|
625
|
-
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
626
|
-
function encode(prefix, words, limit = 90) {
|
|
627
|
-
astr("bech32.encode prefix", prefix);
|
|
628
|
-
if (isBytes(words))
|
|
629
|
-
words = Array.from(words);
|
|
630
|
-
anumArr("bech32.encode", words);
|
|
631
|
-
const plen = prefix.length;
|
|
632
|
-
if (plen === 0)
|
|
633
|
-
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
634
|
-
const actualLength = plen + 7 + words.length;
|
|
635
|
-
if (limit !== false && actualLength > limit)
|
|
636
|
-
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
637
|
-
const lowered = prefix.toLowerCase();
|
|
638
|
-
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
639
|
-
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
640
|
-
}
|
|
641
|
-
function decode(str, limit = 90) {
|
|
642
|
-
astr("bech32.decode input", str);
|
|
643
|
-
const slen = str.length;
|
|
644
|
-
if (slen < 8 || limit !== false && slen > limit)
|
|
645
|
-
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
646
|
-
const lowered = str.toLowerCase();
|
|
647
|
-
if (str !== lowered && str !== str.toUpperCase())
|
|
648
|
-
throw new Error(`String must be lowercase or uppercase`);
|
|
649
|
-
const sepIndex = lowered.lastIndexOf("1");
|
|
650
|
-
if (sepIndex === 0 || sepIndex === -1)
|
|
651
|
-
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
652
|
-
const prefix = lowered.slice(0, sepIndex);
|
|
653
|
-
const data = lowered.slice(sepIndex + 1);
|
|
654
|
-
if (data.length < 6)
|
|
655
|
-
throw new Error("Data must be at least 6 characters long");
|
|
656
|
-
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
657
|
-
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
658
|
-
if (!data.endsWith(sum))
|
|
659
|
-
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
660
|
-
return { prefix, words };
|
|
661
|
-
}
|
|
662
|
-
const decodeUnsafe = unsafeWrapper(decode);
|
|
663
|
-
function decodeToBytes(str) {
|
|
664
|
-
const { prefix, words } = decode(str, false);
|
|
665
|
-
return { prefix, words, bytes: fromWords(words) };
|
|
666
|
-
}
|
|
667
|
-
function encodeFromBytes(prefix, bytes) {
|
|
668
|
-
return encode(prefix, toWords(bytes));
|
|
669
|
-
}
|
|
670
|
-
return {
|
|
671
|
-
encode,
|
|
672
|
-
decode,
|
|
673
|
-
encodeFromBytes,
|
|
674
|
-
decodeToBytes,
|
|
675
|
-
decodeUnsafe,
|
|
676
|
-
fromWords,
|
|
677
|
-
fromWordsUnsafe,
|
|
678
|
-
toWords
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
var bech32 = /* @__PURE__ */ genBech32();
|
|
682
|
-
|
|
683
|
-
// node_modules/@scure/bip32/index.js
|
|
684
|
-
var Point = secp256k1_js.secp256k1.Point;
|
|
685
|
-
var { Fn } = Point;
|
|
686
|
-
var base58check2 = createBase58check(sha2_js.sha256);
|
|
687
|
-
var MASTER_SECRET = Uint8Array.from("Bitcoin seed".split(""), (char) => char.charCodeAt(0));
|
|
688
|
-
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
689
|
-
var HARDENED_OFFSET = 2147483648;
|
|
690
|
-
var hash160 = (data) => legacy_js.ripemd160(sha2_js.sha256(data));
|
|
691
|
-
var fromU32 = (data) => utils_js.createView(data).getUint32(0, false);
|
|
692
|
-
var toU32 = (n) => {
|
|
693
|
-
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
694
|
-
throw new Error("invalid number, should be from 0 to 2**32-1, got " + n);
|
|
695
|
-
}
|
|
696
|
-
const buf = new Uint8Array(4);
|
|
697
|
-
utils_js.createView(buf).setUint32(0, n, false);
|
|
698
|
-
return buf;
|
|
699
|
-
};
|
|
700
|
-
var HDKey = class _HDKey {
|
|
701
|
-
get fingerprint() {
|
|
702
|
-
if (!this.pubHash) {
|
|
703
|
-
throw new Error("No publicKey set!");
|
|
704
|
-
}
|
|
705
|
-
return fromU32(this.pubHash);
|
|
706
|
-
}
|
|
707
|
-
get identifier() {
|
|
708
|
-
return this.pubHash;
|
|
709
|
-
}
|
|
710
|
-
get pubKeyHash() {
|
|
711
|
-
return this.pubHash;
|
|
712
|
-
}
|
|
713
|
-
get privateKey() {
|
|
714
|
-
return this._privateKey || null;
|
|
715
|
-
}
|
|
716
|
-
get publicKey() {
|
|
717
|
-
return this._publicKey || null;
|
|
718
|
-
}
|
|
719
|
-
get privateExtendedKey() {
|
|
720
|
-
const priv = this._privateKey;
|
|
721
|
-
if (!priv) {
|
|
722
|
-
throw new Error("No private key");
|
|
723
|
-
}
|
|
724
|
-
return base58check2.encode(this.serialize(this.versions.private, utils_js.concatBytes(Uint8Array.of(0), priv)));
|
|
725
|
-
}
|
|
726
|
-
get publicExtendedKey() {
|
|
727
|
-
if (!this._publicKey) {
|
|
728
|
-
throw new Error("No public key");
|
|
729
|
-
}
|
|
730
|
-
return base58check2.encode(this.serialize(this.versions.public, this._publicKey));
|
|
731
|
-
}
|
|
732
|
-
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
733
|
-
utils_js.abytes(seed);
|
|
734
|
-
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
735
|
-
throw new Error("HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got " + seed.length);
|
|
736
|
-
}
|
|
737
|
-
const I = hmac_js.hmac(sha2_js.sha512, MASTER_SECRET, seed);
|
|
738
|
-
const privateKey = I.slice(0, 32);
|
|
739
|
-
const chainCode = I.slice(32);
|
|
740
|
-
return new _HDKey({ versions, chainCode, privateKey });
|
|
741
|
-
}
|
|
742
|
-
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
743
|
-
const keyBuffer = base58check2.decode(base58key);
|
|
744
|
-
const keyView = utils_js.createView(keyBuffer);
|
|
745
|
-
const version = keyView.getUint32(0, false);
|
|
746
|
-
const opt = {
|
|
747
|
-
versions,
|
|
748
|
-
depth: keyBuffer[4],
|
|
749
|
-
parentFingerprint: keyView.getUint32(5, false),
|
|
750
|
-
index: keyView.getUint32(9, false),
|
|
751
|
-
chainCode: keyBuffer.slice(13, 45)
|
|
752
|
-
};
|
|
753
|
-
const key = keyBuffer.slice(45);
|
|
754
|
-
const isPriv = key[0] === 0;
|
|
755
|
-
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
756
|
-
throw new Error("Version mismatch");
|
|
757
|
-
}
|
|
758
|
-
if (isPriv) {
|
|
759
|
-
return new _HDKey({ ...opt, privateKey: key.slice(1) });
|
|
760
|
-
} else {
|
|
761
|
-
return new _HDKey({ ...opt, publicKey: key });
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
static fromJSON(json) {
|
|
765
|
-
return _HDKey.fromExtendedKey(json.xpriv);
|
|
766
|
-
}
|
|
767
|
-
versions;
|
|
768
|
-
depth = 0;
|
|
769
|
-
index = 0;
|
|
770
|
-
chainCode = null;
|
|
771
|
-
parentFingerprint = 0;
|
|
772
|
-
_privateKey;
|
|
773
|
-
_publicKey;
|
|
774
|
-
pubHash;
|
|
775
|
-
constructor(opt) {
|
|
776
|
-
if (!opt || typeof opt !== "object") {
|
|
777
|
-
throw new Error("HDKey.constructor must not be called directly");
|
|
778
|
-
}
|
|
779
|
-
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
780
|
-
this.depth = opt.depth || 0;
|
|
781
|
-
this.chainCode = opt.chainCode || null;
|
|
782
|
-
this.index = opt.index || 0;
|
|
783
|
-
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
784
|
-
if (!this.depth) {
|
|
785
|
-
if (this.parentFingerprint || this.index) {
|
|
786
|
-
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
if (this.depth > 255) {
|
|
790
|
-
throw new Error("HDKey: depth exceeds the serializable value 255");
|
|
791
|
-
}
|
|
792
|
-
if (opt.publicKey && opt.privateKey) {
|
|
793
|
-
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
794
|
-
}
|
|
795
|
-
if (opt.privateKey) {
|
|
796
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(opt.privateKey))
|
|
797
|
-
throw new Error("Invalid private key");
|
|
798
|
-
this._privateKey = opt.privateKey;
|
|
799
|
-
this._publicKey = secp256k1_js.secp256k1.getPublicKey(opt.privateKey, true);
|
|
800
|
-
} else if (opt.publicKey) {
|
|
801
|
-
this._publicKey = Point.fromBytes(opt.publicKey).toBytes(true);
|
|
802
|
-
} else {
|
|
803
|
-
throw new Error("HDKey: no public or private key provided");
|
|
804
|
-
}
|
|
805
|
-
this.pubHash = hash160(this._publicKey);
|
|
806
|
-
}
|
|
807
|
-
derive(path) {
|
|
808
|
-
if (!/^[mM]'?/.test(path)) {
|
|
809
|
-
throw new Error('Path must start with "m" or "M"');
|
|
810
|
-
}
|
|
811
|
-
if (/^[mM]'?$/.test(path)) {
|
|
812
|
-
return this;
|
|
813
|
-
}
|
|
814
|
-
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
815
|
-
let child = this;
|
|
816
|
-
for (const c of parts) {
|
|
817
|
-
const m = /^(\d+)('?)$/.exec(c);
|
|
818
|
-
const m1 = m && m[1];
|
|
819
|
-
if (!m || m.length !== 3 || typeof m1 !== "string")
|
|
820
|
-
throw new Error("invalid child index: " + c);
|
|
821
|
-
let idx = +m1;
|
|
822
|
-
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
823
|
-
throw new Error("Invalid index");
|
|
824
|
-
}
|
|
825
|
-
if (m[2] === "'") {
|
|
826
|
-
idx += HARDENED_OFFSET;
|
|
827
|
-
}
|
|
828
|
-
child = child.deriveChild(idx);
|
|
829
|
-
}
|
|
830
|
-
return child;
|
|
831
|
-
}
|
|
832
|
-
deriveChild(index) {
|
|
833
|
-
if (!this._publicKey || !this.chainCode) {
|
|
834
|
-
throw new Error("No publicKey or chainCode set");
|
|
835
|
-
}
|
|
836
|
-
let data = toU32(index);
|
|
837
|
-
if (index >= HARDENED_OFFSET) {
|
|
838
|
-
const priv = this._privateKey;
|
|
839
|
-
if (!priv) {
|
|
840
|
-
throw new Error("Could not derive hardened child key");
|
|
841
|
-
}
|
|
842
|
-
data = utils_js.concatBytes(Uint8Array.of(0), priv, data);
|
|
843
|
-
} else {
|
|
844
|
-
data = utils_js.concatBytes(this._publicKey, data);
|
|
845
|
-
}
|
|
846
|
-
const I = hmac_js.hmac(sha2_js.sha512, this.chainCode, data);
|
|
847
|
-
const childTweak = I.slice(0, 32);
|
|
848
|
-
const chainCode = I.slice(32);
|
|
849
|
-
if (!secp256k1_js.secp256k1.utils.isValidSecretKey(childTweak)) {
|
|
850
|
-
throw new Error("Tweak bigger than curve order");
|
|
851
|
-
}
|
|
852
|
-
const opt = {
|
|
853
|
-
versions: this.versions,
|
|
854
|
-
chainCode,
|
|
855
|
-
depth: this.depth + 1,
|
|
856
|
-
parentFingerprint: this.fingerprint,
|
|
857
|
-
index
|
|
858
|
-
};
|
|
859
|
-
const ctweak = Fn.fromBytes(childTweak);
|
|
860
|
-
try {
|
|
861
|
-
if (this._privateKey) {
|
|
862
|
-
const added = Fn.create(Fn.fromBytes(this._privateKey) + ctweak);
|
|
863
|
-
if (!Fn.isValidNot0(added)) {
|
|
864
|
-
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
865
|
-
}
|
|
866
|
-
opt.privateKey = Fn.toBytes(added);
|
|
867
|
-
} else {
|
|
868
|
-
const added = Point.fromBytes(this._publicKey).add(Point.BASE.multiply(ctweak));
|
|
869
|
-
if (added.equals(Point.ZERO)) {
|
|
870
|
-
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
871
|
-
}
|
|
872
|
-
opt.publicKey = added.toBytes(true);
|
|
873
|
-
}
|
|
874
|
-
return new _HDKey(opt);
|
|
875
|
-
} catch (err) {
|
|
876
|
-
return this.deriveChild(index + 1);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
sign(hash) {
|
|
880
|
-
if (!this._privateKey) {
|
|
881
|
-
throw new Error("No privateKey set!");
|
|
882
|
-
}
|
|
883
|
-
utils_js.abytes(hash, 32);
|
|
884
|
-
return secp256k1_js.secp256k1.sign(hash, this._privateKey, { prehash: false });
|
|
885
|
-
}
|
|
886
|
-
verify(hash, signature) {
|
|
887
|
-
utils_js.abytes(hash, 32);
|
|
888
|
-
utils_js.abytes(signature, 64);
|
|
889
|
-
if (!this._publicKey) {
|
|
890
|
-
throw new Error("No publicKey set!");
|
|
891
|
-
}
|
|
892
|
-
return secp256k1_js.secp256k1.verify(signature, hash, this._publicKey, { prehash: false });
|
|
893
|
-
}
|
|
894
|
-
wipePrivateData() {
|
|
895
|
-
if (this._privateKey) {
|
|
896
|
-
this._privateKey.fill(0);
|
|
897
|
-
this._privateKey = void 0;
|
|
898
|
-
}
|
|
899
|
-
return this;
|
|
900
|
-
}
|
|
901
|
-
toJSON() {
|
|
902
|
-
return {
|
|
903
|
-
xpriv: this.privateExtendedKey,
|
|
904
|
-
xpub: this.publicExtendedKey
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
serialize(version, key) {
|
|
908
|
-
if (!this.chainCode) {
|
|
909
|
-
throw new Error("No chainCode set");
|
|
910
|
-
}
|
|
911
|
-
utils_js.abytes(key, 33);
|
|
912
|
-
return utils_js.concatBytes(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
913
|
-
}
|
|
914
|
-
};
|
|
915
341
|
var DERIVATION_PATHS2 = {
|
|
916
|
-
ethereum:
|
|
917
|
-
bitcoin_mainnet:
|
|
342
|
+
ethereum: `${DERIVATION_PATHS.ethereum}/0`,
|
|
343
|
+
bitcoin_mainnet: `${DERIVATION_PATHS.bitcoin}/0`,
|
|
918
344
|
bitcoin_testnet: "m/84'/1'/0'/0/0",
|
|
919
|
-
ton:
|
|
920
|
-
tron:
|
|
921
|
-
solana:
|
|
922
|
-
spark:
|
|
345
|
+
ton: `${DERIVATION_PATHS.ton}/0'/0'`,
|
|
346
|
+
tron: `${DERIVATION_PATHS.tron}/0`,
|
|
347
|
+
solana: `${DERIVATION_PATHS.solana}/0'`,
|
|
348
|
+
spark: `${DERIVATION_PATHS.spark}/0`
|
|
923
349
|
};
|
|
924
350
|
function deriveEthereumAddress(seed) {
|
|
925
351
|
const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
|
|
@@ -928,7 +354,7 @@ function deriveEthereumAddress(seed) {
|
|
|
928
354
|
function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
929
355
|
try {
|
|
930
356
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
931
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
357
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
932
358
|
const path = network === "testnet" ? DERIVATION_PATHS2.bitcoin_testnet : DERIVATION_PATHS2.bitcoin_mainnet;
|
|
933
359
|
const child = hdKey.derive(path);
|
|
934
360
|
if (!child.publicKey) {
|
|
@@ -936,10 +362,10 @@ function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
|
936
362
|
}
|
|
937
363
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
938
364
|
const witnessVersion = 0;
|
|
939
|
-
const words = bech32.toWords(pubKeyHash);
|
|
365
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
940
366
|
words.unshift(witnessVersion);
|
|
941
367
|
const hrp = network === "testnet" ? "tb" : "bc";
|
|
942
|
-
const address = bech32.encode(hrp, words);
|
|
368
|
+
const address = base.bech32.encode(hrp, words);
|
|
943
369
|
return address;
|
|
944
370
|
} catch (error) {
|
|
945
371
|
console.error("Bitcoin address derivation failed:", error);
|
|
@@ -1012,7 +438,7 @@ function deriveTronAddress(seed) {
|
|
|
1012
438
|
for (let i = 0; i < 20; i++) {
|
|
1013
439
|
addressBytes[i + 1] = parseInt(ethAddressHex.slice(i * 2, i * 2 + 2), 16);
|
|
1014
440
|
}
|
|
1015
|
-
const tronBase58check = base58check(sha256.sha256);
|
|
441
|
+
const tronBase58check = base.base58check(sha256.sha256);
|
|
1016
442
|
return tronBase58check.encode(addressBytes);
|
|
1017
443
|
} catch (error) {
|
|
1018
444
|
console.error("TRON address derivation failed:", error);
|
|
@@ -1022,17 +448,17 @@ function deriveTronAddress(seed) {
|
|
|
1022
448
|
function deriveSparkAddress(seed, network = "mainnet") {
|
|
1023
449
|
try {
|
|
1024
450
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
1025
|
-
const hdKey = HDKey.fromMasterSeed(seedBytes);
|
|
451
|
+
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
1026
452
|
const child = hdKey.derive(DERIVATION_PATHS2.spark);
|
|
1027
453
|
if (!child.publicKey) {
|
|
1028
454
|
throw new Error("Failed to derive public key");
|
|
1029
455
|
}
|
|
1030
456
|
const pubKeyHash = ripemd160.ripemd160(sha256.sha256(child.publicKey));
|
|
1031
457
|
const witnessVersion = 0;
|
|
1032
|
-
const words = bech32.toWords(pubKeyHash);
|
|
458
|
+
const words = base.bech32.toWords(pubKeyHash);
|
|
1033
459
|
words.unshift(witnessVersion);
|
|
1034
460
|
const hrp = network === "testnet" ? "tsp" : "sp";
|
|
1035
|
-
const address = bech32.encode(hrp, words);
|
|
461
|
+
const address = base.bech32.encode(hrp, words);
|
|
1036
462
|
return address;
|
|
1037
463
|
} catch (error) {
|
|
1038
464
|
console.error("Spark address derivation failed:", error);
|
|
@@ -1128,9 +554,9 @@ var CHAIN_ERROR_MESSAGES = {
|
|
|
1128
554
|
"no route": "NETWORK_ERROR"
|
|
1129
555
|
}
|
|
1130
556
|
};
|
|
1131
|
-
function parseChainError(
|
|
557
|
+
function parseChainError(chain, errorMessage) {
|
|
1132
558
|
const errorLower = errorMessage.toLowerCase();
|
|
1133
|
-
const chainErrors = CHAIN_ERROR_MESSAGES[
|
|
559
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
1134
560
|
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
1135
561
|
if (errorLower.includes(pattern)) {
|
|
1136
562
|
return code;
|
|
@@ -1268,38 +694,38 @@ var ZubariWdkService = class {
|
|
|
1268
694
|
* For Ethereum, falls back to local derivation if API fails.
|
|
1269
695
|
* For other chains, WDK API is required - no placeholder fallback.
|
|
1270
696
|
*/
|
|
1271
|
-
async deriveAddress(seed,
|
|
697
|
+
async deriveAddress(seed, chain) {
|
|
1272
698
|
await this.initialize();
|
|
1273
|
-
const path = this.getDerivationPath(
|
|
699
|
+
const path = this.getDerivationPath(chain);
|
|
1274
700
|
try {
|
|
1275
|
-
const response = await this.apiClient.deriveAddress(seed,
|
|
701
|
+
const response = await this.apiClient.deriveAddress(seed, chain, this.config.network);
|
|
1276
702
|
if (response.success && response.address) {
|
|
1277
703
|
return {
|
|
1278
|
-
chain
|
|
704
|
+
chain,
|
|
1279
705
|
address: response.address,
|
|
1280
706
|
path: response.path || path
|
|
1281
707
|
};
|
|
1282
708
|
}
|
|
1283
709
|
} catch (error) {
|
|
1284
|
-
console.warn(`API address derivation failed for ${
|
|
1285
|
-
if (
|
|
1286
|
-
return this.deriveBrowserAddress(seed,
|
|
710
|
+
console.warn(`API address derivation failed for ${chain}:`, error);
|
|
711
|
+
if (chain === "ethereum") {
|
|
712
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1287
713
|
}
|
|
1288
714
|
}
|
|
1289
715
|
if (this.useNativeWdk && this.nativeWdkService) {
|
|
1290
716
|
try {
|
|
1291
717
|
const wdk = this.nativeWdkService;
|
|
1292
718
|
await wdk.initialize(seed);
|
|
1293
|
-
return await wdk.deriveAddress(
|
|
719
|
+
return await wdk.deriveAddress(chain);
|
|
1294
720
|
} catch (error) {
|
|
1295
|
-
console.warn(`Native WDK address derivation failed for ${
|
|
721
|
+
console.warn(`Native WDK address derivation failed for ${chain}:`, error);
|
|
1296
722
|
}
|
|
1297
723
|
}
|
|
1298
|
-
if (
|
|
1299
|
-
return this.deriveBrowserAddress(seed,
|
|
724
|
+
if (chain === "ethereum") {
|
|
725
|
+
return this.deriveBrowserAddress(seed, chain);
|
|
1300
726
|
}
|
|
1301
727
|
throw new Error(
|
|
1302
|
-
`WDK API required for ${
|
|
728
|
+
`WDK API required for ${chain} address derivation. Ensure the backend is running.`
|
|
1303
729
|
);
|
|
1304
730
|
}
|
|
1305
731
|
/**
|
|
@@ -1379,13 +805,13 @@ var ZubariWdkService = class {
|
|
|
1379
805
|
/**
|
|
1380
806
|
* Get fee rates for a chain
|
|
1381
807
|
*/
|
|
1382
|
-
async getFeeRates(seed,
|
|
808
|
+
async getFeeRates(seed, chain) {
|
|
1383
809
|
await this.initialize();
|
|
1384
810
|
try {
|
|
1385
811
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/fee-rates`, {
|
|
1386
812
|
method: "POST",
|
|
1387
813
|
headers: { "Content-Type": "application/json" },
|
|
1388
|
-
body: JSON.stringify({ seed, chain
|
|
814
|
+
body: JSON.stringify({ seed, chain, network: this.config.network })
|
|
1389
815
|
});
|
|
1390
816
|
if (response.ok) {
|
|
1391
817
|
const data = await response.json();
|
|
@@ -1394,20 +820,20 @@ var ZubariWdkService = class {
|
|
|
1394
820
|
}
|
|
1395
821
|
}
|
|
1396
822
|
} catch (error) {
|
|
1397
|
-
console.warn(`Failed to fetch fee rates for ${
|
|
823
|
+
console.warn(`Failed to fetch fee rates for ${chain}:`, error);
|
|
1398
824
|
}
|
|
1399
825
|
return { slow: "0", normal: "0", fast: "0" };
|
|
1400
826
|
}
|
|
1401
827
|
/**
|
|
1402
828
|
* Estimate transaction fee
|
|
1403
829
|
*/
|
|
1404
|
-
async estimateFee(seed,
|
|
830
|
+
async estimateFee(seed, chain, to, amount) {
|
|
1405
831
|
await this.initialize();
|
|
1406
832
|
try {
|
|
1407
833
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/estimate-fee`, {
|
|
1408
834
|
method: "POST",
|
|
1409
835
|
headers: { "Content-Type": "application/json" },
|
|
1410
|
-
body: JSON.stringify({ seed, chain
|
|
836
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1411
837
|
});
|
|
1412
838
|
if (response.ok) {
|
|
1413
839
|
const data = await response.json();
|
|
@@ -1416,9 +842,9 @@ var ZubariWdkService = class {
|
|
|
1416
842
|
}
|
|
1417
843
|
}
|
|
1418
844
|
} catch (error) {
|
|
1419
|
-
console.warn(`Failed to estimate fee for ${
|
|
845
|
+
console.warn(`Failed to estimate fee for ${chain}:`, error);
|
|
1420
846
|
}
|
|
1421
|
-
return { fee: "0", symbol: this.getChainSymbol(
|
|
847
|
+
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
1422
848
|
}
|
|
1423
849
|
/**
|
|
1424
850
|
* Send a transaction on any supported chain
|
|
@@ -1429,19 +855,14 @@ var ZubariWdkService = class {
|
|
|
1429
855
|
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
1430
856
|
* @returns Transaction result with hash on success, or error details on failure
|
|
1431
857
|
*/
|
|
1432
|
-
async sendTransaction(seed,
|
|
858
|
+
async sendTransaction(seed, chain, to, amount) {
|
|
1433
859
|
await this.initialize();
|
|
1434
860
|
const startTime = Date.now();
|
|
1435
|
-
console.log(`[ZubariWdkService] Sending ${chain2} transaction`, {
|
|
1436
|
-
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
1437
|
-
amount,
|
|
1438
|
-
network: this.config.network
|
|
1439
|
-
});
|
|
1440
861
|
try {
|
|
1441
862
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
1442
863
|
method: "POST",
|
|
1443
864
|
headers: { "Content-Type": "application/json" },
|
|
1444
|
-
body: JSON.stringify({ seed, chain
|
|
865
|
+
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
1445
866
|
});
|
|
1446
867
|
const elapsed = Date.now() - startTime;
|
|
1447
868
|
if (response.ok) {
|
|
@@ -1451,22 +872,18 @@ var ZubariWdkService = class {
|
|
|
1451
872
|
txHash = txHash.hash;
|
|
1452
873
|
}
|
|
1453
874
|
if (txHash) {
|
|
1454
|
-
const isValid = this.validateTxHash(
|
|
875
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
1455
876
|
if (!isValid) {
|
|
1456
|
-
console.warn(`[ZubariWdkService] Invalid ${
|
|
877
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
1457
878
|
}
|
|
1458
879
|
}
|
|
1459
|
-
console.log(`[ZubariWdkService] ${chain2} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
1460
|
-
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
1461
|
-
elapsed: `${elapsed}ms`
|
|
1462
|
-
});
|
|
1463
880
|
if (!data.success) {
|
|
1464
|
-
const errorCode2 = parseChainError(
|
|
881
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
1465
882
|
return {
|
|
1466
883
|
success: false,
|
|
1467
884
|
error: data.error,
|
|
1468
885
|
errorCode: errorCode2,
|
|
1469
|
-
chain
|
|
886
|
+
chain
|
|
1470
887
|
};
|
|
1471
888
|
}
|
|
1472
889
|
return {
|
|
@@ -1475,47 +892,35 @@ var ZubariWdkService = class {
|
|
|
1475
892
|
from: data.from,
|
|
1476
893
|
to: data.to,
|
|
1477
894
|
amount: data.amount,
|
|
1478
|
-
chain: data.chain ||
|
|
895
|
+
chain: data.chain || chain,
|
|
1479
896
|
network: data.network || this.config.network
|
|
1480
897
|
};
|
|
1481
898
|
}
|
|
1482
899
|
const errorData = await response.json().catch(() => ({}));
|
|
1483
900
|
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
1484
|
-
const errorCode = parseChainError(
|
|
1485
|
-
console.error(`[ZubariWdkService] ${chain2} transaction FAILED`, {
|
|
1486
|
-
status: response.status,
|
|
1487
|
-
error: errorMessage,
|
|
1488
|
-
errorCode,
|
|
1489
|
-
elapsed: `${elapsed}ms`
|
|
1490
|
-
});
|
|
901
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1491
902
|
return {
|
|
1492
903
|
success: false,
|
|
1493
904
|
error: errorMessage,
|
|
1494
905
|
errorCode,
|
|
1495
|
-
chain
|
|
906
|
+
chain
|
|
1496
907
|
};
|
|
1497
908
|
} catch (error) {
|
|
1498
|
-
const elapsed = Date.now() - startTime;
|
|
1499
909
|
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
1500
|
-
const errorCode = parseChainError(
|
|
1501
|
-
console.error(`[ZubariWdkService] ${chain2} transaction ERROR`, {
|
|
1502
|
-
error: errorMessage,
|
|
1503
|
-
errorCode,
|
|
1504
|
-
elapsed: `${elapsed}ms`
|
|
1505
|
-
});
|
|
910
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
1506
911
|
return {
|
|
1507
912
|
success: false,
|
|
1508
913
|
error: errorMessage,
|
|
1509
914
|
errorCode,
|
|
1510
|
-
chain
|
|
915
|
+
chain
|
|
1511
916
|
};
|
|
1512
917
|
}
|
|
1513
918
|
}
|
|
1514
919
|
/**
|
|
1515
920
|
* Validate transaction hash format for a specific chain
|
|
1516
921
|
*/
|
|
1517
|
-
validateTxHash(
|
|
1518
|
-
switch (
|
|
922
|
+
validateTxHash(chain, txHash) {
|
|
923
|
+
switch (chain) {
|
|
1519
924
|
case "ethereum":
|
|
1520
925
|
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
1521
926
|
case "bitcoin":
|
|
@@ -1547,18 +952,25 @@ var ZubariWdkService = class {
|
|
|
1547
952
|
// ==========================================
|
|
1548
953
|
// Private Helper Methods
|
|
1549
954
|
// ==========================================
|
|
1550
|
-
getDerivationPath(
|
|
1551
|
-
const
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
955
|
+
getDerivationPath(chain) {
|
|
956
|
+
const basePath = DERIVATION_PATHS[chain];
|
|
957
|
+
if (chain === "bitcoin" && this.config.network === "testnet") {
|
|
958
|
+
return "m/84'/1'/0'/0/0";
|
|
959
|
+
}
|
|
960
|
+
switch (chain) {
|
|
961
|
+
case "ton":
|
|
962
|
+
return `${basePath}/0'/0'`;
|
|
963
|
+
case "solana":
|
|
964
|
+
return `${basePath}/0'`;
|
|
965
|
+
case "bitcoin":
|
|
966
|
+
case "ethereum":
|
|
967
|
+
case "tron":
|
|
968
|
+
case "spark":
|
|
969
|
+
default:
|
|
970
|
+
return `${basePath}/0`;
|
|
971
|
+
}
|
|
1560
972
|
}
|
|
1561
|
-
getChainSymbol(
|
|
973
|
+
getChainSymbol(chain) {
|
|
1562
974
|
const symbols = {
|
|
1563
975
|
ethereum: "ETH",
|
|
1564
976
|
bitcoin: "BTC",
|
|
@@ -1567,16 +979,16 @@ var ZubariWdkService = class {
|
|
|
1567
979
|
solana: "SOL",
|
|
1568
980
|
spark: "SAT"
|
|
1569
981
|
};
|
|
1570
|
-
return symbols[
|
|
982
|
+
return symbols[chain];
|
|
1571
983
|
}
|
|
1572
984
|
/**
|
|
1573
985
|
* Derive address using browser-compatible libraries
|
|
1574
986
|
*/
|
|
1575
|
-
async deriveBrowserAddress(seed,
|
|
1576
|
-
const path = this.getDerivationPath(
|
|
987
|
+
async deriveBrowserAddress(seed, chain) {
|
|
988
|
+
const path = this.getDerivationPath(chain);
|
|
1577
989
|
try {
|
|
1578
990
|
let address;
|
|
1579
|
-
switch (
|
|
991
|
+
switch (chain) {
|
|
1580
992
|
case "ethereum":
|
|
1581
993
|
address = deriveEthereumAddress(seed);
|
|
1582
994
|
break;
|
|
@@ -1596,11 +1008,11 @@ var ZubariWdkService = class {
|
|
|
1596
1008
|
address = await deriveTonAddress(seed);
|
|
1597
1009
|
break;
|
|
1598
1010
|
default:
|
|
1599
|
-
throw new Error(`Unsupported chain: ${
|
|
1011
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1600
1012
|
}
|
|
1601
|
-
return { chain
|
|
1013
|
+
return { chain, address, path };
|
|
1602
1014
|
} catch (error) {
|
|
1603
|
-
console.error(`Browser derivation failed for ${
|
|
1015
|
+
console.error(`Browser derivation failed for ${chain}:`, error);
|
|
1604
1016
|
throw error;
|
|
1605
1017
|
}
|
|
1606
1018
|
}
|
|
@@ -1613,7 +1025,7 @@ var ZubariWdkService = class {
|
|
|
1613
1025
|
};
|
|
1614
1026
|
var defaultService = null;
|
|
1615
1027
|
function getZubariWdkService(config) {
|
|
1616
|
-
if (!defaultService || config && config.network !== defaultService.getNetwork()) {
|
|
1028
|
+
if (!defaultService || config && (config.network !== defaultService.getNetwork() || config.apiUrl && config.apiUrl !== defaultService.getApiUrl())) {
|
|
1617
1029
|
defaultService = new ZubariWdkService(config);
|
|
1618
1030
|
}
|
|
1619
1031
|
return defaultService;
|
|
@@ -1625,7 +1037,10 @@ var KeyManager = class {
|
|
|
1625
1037
|
static KEY_LENGTH = 256;
|
|
1626
1038
|
static IV_LENGTH = 12;
|
|
1627
1039
|
static SALT_LENGTH = 16;
|
|
1628
|
-
|
|
1040
|
+
// OWASP 2023 recommends 600,000 iterations for PBKDF2-SHA256 to resist
|
|
1041
|
+
// brute-force attacks with modern GPU hardware.
|
|
1042
|
+
// See: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
|
|
1043
|
+
static PBKDF2_ITERATIONS = 6e5;
|
|
1629
1044
|
/**
|
|
1630
1045
|
* Encrypt a seed phrase with a password
|
|
1631
1046
|
*/
|
|
@@ -1864,7 +1279,7 @@ var WebEncryptedStorageAdapter = class {
|
|
|
1864
1279
|
{
|
|
1865
1280
|
name: "PBKDF2",
|
|
1866
1281
|
salt: salt.buffer,
|
|
1867
|
-
iterations:
|
|
1282
|
+
iterations: 6e5,
|
|
1868
1283
|
hash: "SHA-256"
|
|
1869
1284
|
},
|
|
1870
1285
|
keyMaterial,
|
|
@@ -2002,8 +1417,8 @@ async function fetchPrices() {
|
|
|
2002
1417
|
if (response.ok) {
|
|
2003
1418
|
const data = await response.json();
|
|
2004
1419
|
const prices = {};
|
|
2005
|
-
for (const [
|
|
2006
|
-
prices[
|
|
1420
|
+
for (const [chain, geckoId] of Object.entries(COINGECKO_IDS)) {
|
|
1421
|
+
prices[chain] = data[geckoId]?.usd || 0;
|
|
2007
1422
|
}
|
|
2008
1423
|
priceCache = { prices, timestamp: Date.now() };
|
|
2009
1424
|
return prices;
|
|
@@ -2013,9 +1428,22 @@ async function fetchPrices() {
|
|
|
2013
1428
|
}
|
|
2014
1429
|
return priceCache?.prices || {};
|
|
2015
1430
|
}
|
|
2016
|
-
async function getPriceForChain(
|
|
1431
|
+
async function getPriceForChain(chain) {
|
|
2017
1432
|
const prices = await fetchPrices();
|
|
2018
|
-
return prices[
|
|
1433
|
+
return prices[chain] || 0;
|
|
1434
|
+
}
|
|
1435
|
+
function tonFriendlyToRaw(addr) {
|
|
1436
|
+
if (addr.includes(":")) return addr;
|
|
1437
|
+
try {
|
|
1438
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1439
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1440
|
+
if (bytes.length !== 36) return addr;
|
|
1441
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1442
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1443
|
+
return `${workchain}:${hash}`;
|
|
1444
|
+
} catch {
|
|
1445
|
+
return addr;
|
|
1446
|
+
}
|
|
2019
1447
|
}
|
|
2020
1448
|
var STORAGE_KEYS = {
|
|
2021
1449
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
@@ -2164,6 +1592,16 @@ var WalletManager = class _WalletManager {
|
|
|
2164
1592
|
}
|
|
2165
1593
|
/**
|
|
2166
1594
|
* Lock wallet (clear seed from memory)
|
|
1595
|
+
*
|
|
1596
|
+
* SECURITY NOTE: JavaScript strings are immutable and cannot be overwritten
|
|
1597
|
+
* in place. Setting `this.currentSeed = null` removes the reference, but
|
|
1598
|
+
* the original string may persist in memory until garbage collected.
|
|
1599
|
+
* There is no reliable way to zero out a JS string.
|
|
1600
|
+
*
|
|
1601
|
+
* TODO: In a future version, store the seed as a Uint8Array instead of a
|
|
1602
|
+
* string. Uint8Array contents can be explicitly zeroed (e.g.,
|
|
1603
|
+
* `seedBytes.fill(0)`) before releasing the reference, which provides
|
|
1604
|
+
* stronger guarantees that sensitive material is scrubbed from memory.
|
|
2167
1605
|
*/
|
|
2168
1606
|
lock() {
|
|
2169
1607
|
this.currentSeed = null;
|
|
@@ -2221,9 +1659,9 @@ var WalletManager = class _WalletManager {
|
|
|
2221
1659
|
if (!this.derivedAddress) {
|
|
2222
1660
|
throw new Error("Wallet not initialized");
|
|
2223
1661
|
}
|
|
2224
|
-
const
|
|
1662
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2225
1663
|
const client = viem.createPublicClient({
|
|
2226
|
-
chain
|
|
1664
|
+
chain,
|
|
2227
1665
|
transport: viem.http(this.config.rpcUrl, {
|
|
2228
1666
|
timeout: 15e3,
|
|
2229
1667
|
// 15 second timeout
|
|
@@ -2245,9 +1683,9 @@ var WalletManager = class _WalletManager {
|
|
|
2245
1683
|
* Create viem public client for the current network
|
|
2246
1684
|
*/
|
|
2247
1685
|
getPublicClient() {
|
|
2248
|
-
const
|
|
1686
|
+
const chain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2249
1687
|
return viem.createPublicClient({
|
|
2250
|
-
chain
|
|
1688
|
+
chain,
|
|
2251
1689
|
transport: viem.http(this.config.rpcUrl, {
|
|
2252
1690
|
timeout: 15e3,
|
|
2253
1691
|
// 15 second timeout
|
|
@@ -2301,11 +1739,11 @@ var WalletManager = class _WalletManager {
|
|
|
2301
1739
|
*
|
|
2302
1740
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
2303
1741
|
*/
|
|
2304
|
-
static async deriveAddressForChainAsync(seed,
|
|
2305
|
-
if (
|
|
1742
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
1743
|
+
if (chain === "ethereum") {
|
|
2306
1744
|
try {
|
|
2307
1745
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
2308
|
-
const result2 = await wdkService2.deriveAddress(seed,
|
|
1746
|
+
const result2 = await wdkService2.deriveAddress(seed, chain);
|
|
2309
1747
|
return result2.address;
|
|
2310
1748
|
} catch (error) {
|
|
2311
1749
|
console.warn("WDK service failed for Ethereum, using local derivation:", error);
|
|
@@ -2313,7 +1751,7 @@ var WalletManager = class _WalletManager {
|
|
|
2313
1751
|
}
|
|
2314
1752
|
}
|
|
2315
1753
|
const wdkService = getZubariWdkService({ network, apiUrl });
|
|
2316
|
-
const result = await wdkService.deriveAddress(seed,
|
|
1754
|
+
const result = await wdkService.deriveAddress(seed, chain);
|
|
2317
1755
|
return result.address;
|
|
2318
1756
|
}
|
|
2319
1757
|
/**
|
|
@@ -2322,14 +1760,14 @@ var WalletManager = class _WalletManager {
|
|
|
2322
1760
|
*
|
|
2323
1761
|
* @throws Error for non-Ethereum chains - use WDK API instead
|
|
2324
1762
|
*/
|
|
2325
|
-
static deriveAddressForChain(seed,
|
|
2326
|
-
if (
|
|
1763
|
+
static deriveAddressForChain(seed, chain) {
|
|
1764
|
+
if (chain === "ethereum") {
|
|
2327
1765
|
const ethPath = DERIVATION_PATHS["ethereum"];
|
|
2328
1766
|
const ethNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, `${ethPath}/0`);
|
|
2329
1767
|
return ethNode.address;
|
|
2330
1768
|
}
|
|
2331
1769
|
throw new Error(
|
|
2332
|
-
`Sync derivation not supported for ${
|
|
1770
|
+
`Sync derivation not supported for ${chain}. Use deriveAddressForChainAsync() with WDK API.`
|
|
2333
1771
|
);
|
|
2334
1772
|
}
|
|
2335
1773
|
/**
|
|
@@ -2361,9 +1799,9 @@ var WalletManager = class _WalletManager {
|
|
|
2361
1799
|
const wdkAddresses = await this.wdkService.deriveAllAddresses(this.currentSeed);
|
|
2362
1800
|
const enabledChainsSet = new Set(this.config.enabledChains);
|
|
2363
1801
|
const addresses = {};
|
|
2364
|
-
for (const [
|
|
2365
|
-
if (enabledChainsSet.has(
|
|
2366
|
-
addresses[
|
|
1802
|
+
for (const [chain, address] of Object.entries(wdkAddresses)) {
|
|
1803
|
+
if (enabledChainsSet.has(chain) && address) {
|
|
1804
|
+
addresses[chain] = address;
|
|
2367
1805
|
}
|
|
2368
1806
|
}
|
|
2369
1807
|
this.derivedAddresses = addresses;
|
|
@@ -2380,7 +1818,6 @@ var WalletManager = class _WalletManager {
|
|
|
2380
1818
|
async saveAddressesToStorage(addresses) {
|
|
2381
1819
|
try {
|
|
2382
1820
|
await this.storage.setItem(STORAGE_KEYS.DERIVED_ADDRESSES, JSON.stringify(addresses));
|
|
2383
|
-
console.log("Saved derived addresses to storage:", Object.keys(addresses));
|
|
2384
1821
|
} catch (error) {
|
|
2385
1822
|
console.warn("Failed to save addresses to storage:", error);
|
|
2386
1823
|
}
|
|
@@ -2404,10 +1841,10 @@ var WalletManager = class _WalletManager {
|
|
|
2404
1841
|
*/
|
|
2405
1842
|
normalizeAddresses(addresses) {
|
|
2406
1843
|
const normalized = {};
|
|
2407
|
-
for (const [
|
|
1844
|
+
for (const [chain, value] of Object.entries(addresses)) {
|
|
2408
1845
|
const addr = this.normalizeAddress(value);
|
|
2409
1846
|
if (addr) {
|
|
2410
|
-
normalized[
|
|
1847
|
+
normalized[chain] = addr;
|
|
2411
1848
|
}
|
|
2412
1849
|
}
|
|
2413
1850
|
return normalized;
|
|
@@ -2420,9 +1857,7 @@ var WalletManager = class _WalletManager {
|
|
|
2420
1857
|
const stored = await this.storage.getItem(STORAGE_KEYS.DERIVED_ADDRESSES);
|
|
2421
1858
|
if (stored) {
|
|
2422
1859
|
const rawAddresses = JSON.parse(stored);
|
|
2423
|
-
console.log("[WalletManager] Raw addresses from storage:", rawAddresses);
|
|
2424
1860
|
const addresses = this.normalizeAddresses(rawAddresses);
|
|
2425
|
-
console.log("[WalletManager] Normalized addresses:", addresses);
|
|
2426
1861
|
await this.saveAddressesToStorage(addresses);
|
|
2427
1862
|
return addresses;
|
|
2428
1863
|
}
|
|
@@ -2447,11 +1882,8 @@ var WalletManager = class _WalletManager {
|
|
|
2447
1882
|
if (storedAddresses && Object.keys(storedAddresses).length > 1) {
|
|
2448
1883
|
const expectedEthAddress = _WalletManager.deriveAddress(this.currentSeed);
|
|
2449
1884
|
if (storedAddresses.ethereum === expectedEthAddress) {
|
|
2450
|
-
console.log("Using addresses from storage (verified by Ethereum address)");
|
|
2451
1885
|
this.derivedAddresses = storedAddresses;
|
|
2452
1886
|
return storedAddresses;
|
|
2453
|
-
} else {
|
|
2454
|
-
console.log("Stored addresses do not match current seed, re-deriving...");
|
|
2455
1887
|
}
|
|
2456
1888
|
}
|
|
2457
1889
|
return await this.deriveAllAddressesWithWdk();
|
|
@@ -2460,20 +1892,18 @@ var WalletManager = class _WalletManager {
|
|
|
2460
1892
|
* Get address for a specific chain
|
|
2461
1893
|
* Returns cached address or null - use deriveAllAddressesAsync to derive addresses
|
|
2462
1894
|
*/
|
|
2463
|
-
getAddressForChain(
|
|
2464
|
-
const cachedValue = this.derivedAddresses[
|
|
1895
|
+
getAddressForChain(chain) {
|
|
1896
|
+
const cachedValue = this.derivedAddresses[chain];
|
|
2465
1897
|
if (cachedValue) {
|
|
2466
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) cached value:`, cachedValue, "type:", typeof cachedValue);
|
|
2467
1898
|
const addr = this.normalizeAddress(cachedValue);
|
|
2468
|
-
console.log(`[WalletManager] getAddressForChain(${chain2}) normalized:`, addr);
|
|
2469
1899
|
if (addr) {
|
|
2470
|
-
this.derivedAddresses[
|
|
1900
|
+
this.derivedAddresses[chain] = addr;
|
|
2471
1901
|
return addr;
|
|
2472
1902
|
}
|
|
2473
1903
|
}
|
|
2474
|
-
if (
|
|
2475
|
-
this.derivedAddresses[
|
|
2476
|
-
return this.derivedAddresses[
|
|
1904
|
+
if (chain === "ethereum" && this.currentSeed) {
|
|
1905
|
+
this.derivedAddresses[chain] = _WalletManager.deriveAddressForChain(this.currentSeed, chain);
|
|
1906
|
+
return this.derivedAddresses[chain];
|
|
2477
1907
|
}
|
|
2478
1908
|
return null;
|
|
2479
1909
|
}
|
|
@@ -2486,11 +1916,11 @@ var WalletManager = class _WalletManager {
|
|
|
2486
1916
|
/**
|
|
2487
1917
|
* Set the selected chain
|
|
2488
1918
|
*/
|
|
2489
|
-
setSelectedChain(
|
|
2490
|
-
if (!this.config.enabledChains.includes(
|
|
2491
|
-
throw new Error(`Chain ${
|
|
1919
|
+
setSelectedChain(chain) {
|
|
1920
|
+
if (!this.config.enabledChains.includes(chain)) {
|
|
1921
|
+
throw new Error(`Chain ${chain} is not enabled`);
|
|
2492
1922
|
}
|
|
2493
|
-
this.selectedChain =
|
|
1923
|
+
this.selectedChain = chain;
|
|
2494
1924
|
}
|
|
2495
1925
|
/**
|
|
2496
1926
|
* Get the currently selected chain
|
|
@@ -2507,22 +1937,22 @@ var WalletManager = class _WalletManager {
|
|
|
2507
1937
|
/**
|
|
2508
1938
|
* Get chain configuration
|
|
2509
1939
|
*/
|
|
2510
|
-
getChainConfig(
|
|
2511
|
-
return getNetworkConfig(
|
|
1940
|
+
getChainConfig(chain) {
|
|
1941
|
+
return getNetworkConfig(chain, this.config.network === "testnet");
|
|
2512
1942
|
}
|
|
2513
1943
|
/**
|
|
2514
1944
|
* Fetch balance for a specific chain
|
|
2515
1945
|
* Note: Currently only Ethereum is implemented
|
|
2516
1946
|
*/
|
|
2517
|
-
async fetchBalanceForChain(
|
|
2518
|
-
const address = this.getAddressForChain(
|
|
1947
|
+
async fetchBalanceForChain(chain) {
|
|
1948
|
+
const address = this.getAddressForChain(chain);
|
|
2519
1949
|
if (!address) {
|
|
2520
|
-
throw new Error(`No address for chain ${
|
|
1950
|
+
throw new Error(`No address for chain ${chain}`);
|
|
2521
1951
|
}
|
|
2522
|
-
const networkConfig = this.getChainConfig(
|
|
1952
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2523
1953
|
let balance = "0";
|
|
2524
1954
|
const tokenBalances = {};
|
|
2525
|
-
if (
|
|
1955
|
+
if (chain === "ethereum") {
|
|
2526
1956
|
const viemChain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
2527
1957
|
const isTestnet = this.config.network !== "mainnet";
|
|
2528
1958
|
const client = viem.createPublicClient({
|
|
@@ -2569,7 +1999,7 @@ var WalletManager = class _WalletManager {
|
|
|
2569
1999
|
} else if (usdtResult.status === "rejected") {
|
|
2570
2000
|
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
2571
2001
|
}
|
|
2572
|
-
} else if (
|
|
2002
|
+
} else if (chain === "bitcoin") {
|
|
2573
2003
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
2574
2004
|
const apisToTry = isMainnet ? ["https://mempool.space/api"] : [
|
|
2575
2005
|
"https://mempool.space/testnet/api",
|
|
@@ -2592,16 +2022,14 @@ var WalletManager = class _WalletManager {
|
|
|
2592
2022
|
const mempoolSpent = data.mempool_stats?.spent_txo_sum || 0;
|
|
2593
2023
|
const satoshis = chainFunded - chainSpent + (mempoolFunded - mempoolSpent);
|
|
2594
2024
|
balance = (satoshis / 1e8).toFixed(8);
|
|
2595
|
-
console.log(`Bitcoin balance for ${address}: ${balance} BTC (${satoshis} sats) via ${apiUrl}`);
|
|
2596
2025
|
break;
|
|
2597
2026
|
}
|
|
2598
|
-
console.log(`No transactions found on ${apiUrl}, trying next...`);
|
|
2599
2027
|
}
|
|
2600
2028
|
} catch (error) {
|
|
2601
2029
|
console.warn(`Failed to fetch from ${apiUrl}:`, error);
|
|
2602
2030
|
}
|
|
2603
2031
|
}
|
|
2604
|
-
} else if (
|
|
2032
|
+
} else if (chain === "solana") {
|
|
2605
2033
|
const rpcUrl = this.config.network === "mainnet" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
2606
2034
|
try {
|
|
2607
2035
|
const response = await fetch(rpcUrl, {
|
|
@@ -2621,7 +2049,7 @@ var WalletManager = class _WalletManager {
|
|
|
2621
2049
|
}
|
|
2622
2050
|
}
|
|
2623
2051
|
} catch (error) {
|
|
2624
|
-
console.warn(`Failed to fetch ${
|
|
2052
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2625
2053
|
}
|
|
2626
2054
|
const isTestnet = this.config.network !== "mainnet";
|
|
2627
2055
|
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
@@ -2655,7 +2083,7 @@ var WalletManager = class _WalletManager {
|
|
|
2655
2083
|
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
2656
2084
|
}
|
|
2657
2085
|
}
|
|
2658
|
-
} else if (
|
|
2086
|
+
} else if (chain === "tron") {
|
|
2659
2087
|
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
2660
2088
|
const baseUrl = tronConfig.rpcUrl;
|
|
2661
2089
|
try {
|
|
@@ -2684,9 +2112,9 @@ var WalletManager = class _WalletManager {
|
|
|
2684
2112
|
}
|
|
2685
2113
|
}
|
|
2686
2114
|
} catch (error) {
|
|
2687
|
-
console.warn(`Failed to fetch ${
|
|
2115
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2688
2116
|
}
|
|
2689
|
-
} else if (
|
|
2117
|
+
} else if (chain === "ton") {
|
|
2690
2118
|
const isTestnet = this.config.network !== "mainnet";
|
|
2691
2119
|
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
2692
2120
|
try {
|
|
@@ -2698,29 +2126,39 @@ var WalletManager = class _WalletManager {
|
|
|
2698
2126
|
if (data.ok && data.result !== void 0) {
|
|
2699
2127
|
const nanotons = BigInt(data.result);
|
|
2700
2128
|
balance = (Number(nanotons) / 1e9).toFixed(9);
|
|
2701
|
-
console.log(`TON balance for ${address}: ${balance} TON`);
|
|
2702
2129
|
}
|
|
2703
2130
|
}
|
|
2704
2131
|
} catch (error) {
|
|
2705
|
-
console.warn(`Failed to fetch ${
|
|
2132
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2706
2133
|
}
|
|
2707
2134
|
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
2708
2135
|
if (usdtJetton) {
|
|
2709
|
-
const
|
|
2136
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
2710
2137
|
try {
|
|
2138
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
2711
2139
|
const jettonResponse = await fetch(
|
|
2712
|
-
`${
|
|
2140
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
2713
2141
|
{ headers: { "Accept": "application/json" } }
|
|
2714
2142
|
);
|
|
2715
2143
|
if (jettonResponse.ok) {
|
|
2716
2144
|
const jettonData = await jettonResponse.json();
|
|
2717
|
-
const
|
|
2718
|
-
if (
|
|
2719
|
-
const
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2145
|
+
const balances = jettonData.balances;
|
|
2146
|
+
if (balances && balances.length > 0) {
|
|
2147
|
+
for (const jb of balances) {
|
|
2148
|
+
const jettonAddr = jb.jetton?.address;
|
|
2149
|
+
if (jettonAddr) {
|
|
2150
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2151
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2152
|
+
const rawBalance = jb.balance;
|
|
2153
|
+
if (rawBalance) {
|
|
2154
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2155
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2156
|
+
if (usdtAmount > 0) {
|
|
2157
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
break;
|
|
2161
|
+
}
|
|
2724
2162
|
}
|
|
2725
2163
|
}
|
|
2726
2164
|
}
|
|
@@ -2729,7 +2167,7 @@ var WalletManager = class _WalletManager {
|
|
|
2729
2167
|
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
2730
2168
|
}
|
|
2731
2169
|
}
|
|
2732
|
-
} else if (
|
|
2170
|
+
} else if (chain === "spark") {
|
|
2733
2171
|
try {
|
|
2734
2172
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
2735
2173
|
method: "POST",
|
|
@@ -2744,18 +2182,17 @@ var WalletManager = class _WalletManager {
|
|
|
2744
2182
|
const data = await response.json();
|
|
2745
2183
|
if (data.success && data.balance !== void 0) {
|
|
2746
2184
|
balance = (parseFloat(data.balance) / 1e8).toFixed(8);
|
|
2747
|
-
console.log(`Spark balance for ${address}: ${balance} BTC`);
|
|
2748
2185
|
}
|
|
2749
2186
|
}
|
|
2750
2187
|
} catch (error) {
|
|
2751
|
-
console.warn(`Failed to fetch ${
|
|
2188
|
+
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2752
2189
|
}
|
|
2753
2190
|
}
|
|
2754
|
-
const priceUsd = await getPriceForChain(
|
|
2191
|
+
const priceUsd = await getPriceForChain(chain);
|
|
2755
2192
|
const balanceNum = parseFloat(balance) || 0;
|
|
2756
2193
|
const balanceUsd = balanceNum * priceUsd;
|
|
2757
2194
|
return {
|
|
2758
|
-
chain
|
|
2195
|
+
chain,
|
|
2759
2196
|
symbol: networkConfig.nativeCurrency.symbol,
|
|
2760
2197
|
balance,
|
|
2761
2198
|
balanceUsd,
|
|
@@ -2765,28 +2202,29 @@ var WalletManager = class _WalletManager {
|
|
|
2765
2202
|
};
|
|
2766
2203
|
}
|
|
2767
2204
|
/**
|
|
2768
|
-
* Fetch balances for all enabled chains
|
|
2205
|
+
* Fetch balances for all enabled chains in parallel.
|
|
2206
|
+
* Uses Promise.allSettled so that one chain failing does not block others.
|
|
2769
2207
|
*/
|
|
2770
2208
|
async fetchAllBalances() {
|
|
2771
|
-
const
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
const networkConfig = this.getChainConfig(chain2);
|
|
2779
|
-
balances.push({
|
|
2780
|
-
chain: chain2,
|
|
2781
|
-
symbol: networkConfig.nativeCurrency.symbol,
|
|
2782
|
-
balance: "0",
|
|
2783
|
-
balanceUsd: 0,
|
|
2784
|
-
address: this.getAddressForChain(chain2) || "",
|
|
2785
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
2786
|
-
});
|
|
2209
|
+
const results = await Promise.allSettled(
|
|
2210
|
+
this.config.enabledChains.map((chain) => this.fetchBalanceForChain(chain))
|
|
2211
|
+
);
|
|
2212
|
+
return results.map((result, index) => {
|
|
2213
|
+
const chain = this.config.enabledChains[index];
|
|
2214
|
+
if (result.status === "fulfilled") {
|
|
2215
|
+
return result.value;
|
|
2787
2216
|
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2217
|
+
console.error(`Failed to fetch balance for ${chain}:`, result.reason);
|
|
2218
|
+
const networkConfig = this.getChainConfig(chain);
|
|
2219
|
+
return {
|
|
2220
|
+
chain,
|
|
2221
|
+
symbol: networkConfig.nativeCurrency.symbol,
|
|
2222
|
+
balance: "0",
|
|
2223
|
+
balanceUsd: 0,
|
|
2224
|
+
address: this.getAddressForChain(chain) || "",
|
|
2225
|
+
decimals: networkConfig.nativeCurrency.decimals
|
|
2226
|
+
};
|
|
2227
|
+
});
|
|
2790
2228
|
}
|
|
2791
2229
|
/**
|
|
2792
2230
|
* Get extended wallet state with multi-chain info
|
|
@@ -2811,13 +2249,13 @@ var WalletManager = class _WalletManager {
|
|
|
2811
2249
|
* @param token - Optional token symbol (e.g., 'USDT' for stablecoins)
|
|
2812
2250
|
* @returns Transaction result with hash and status
|
|
2813
2251
|
*/
|
|
2814
|
-
async sendTransaction(
|
|
2252
|
+
async sendTransaction(chain, to, amount, token) {
|
|
2815
2253
|
if (!this.currentSeed) {
|
|
2816
2254
|
return { success: false, error: "Wallet is locked" };
|
|
2817
2255
|
}
|
|
2818
|
-
const fromAddress = this.getAddressForChain(
|
|
2256
|
+
const fromAddress = this.getAddressForChain(chain);
|
|
2819
2257
|
if (!fromAddress) {
|
|
2820
|
-
return { success: false, error: `No address for chain ${
|
|
2258
|
+
return { success: false, error: `No address for chain ${chain}` };
|
|
2821
2259
|
}
|
|
2822
2260
|
try {
|
|
2823
2261
|
const headers = {
|
|
@@ -2831,7 +2269,7 @@ var WalletManager = class _WalletManager {
|
|
|
2831
2269
|
headers,
|
|
2832
2270
|
body: JSON.stringify({
|
|
2833
2271
|
seed: this.currentSeed,
|
|
2834
|
-
chain
|
|
2272
|
+
chain,
|
|
2835
2273
|
to,
|
|
2836
2274
|
amount,
|
|
2837
2275
|
token,
|
|
@@ -2840,12 +2278,11 @@ var WalletManager = class _WalletManager {
|
|
|
2840
2278
|
});
|
|
2841
2279
|
if (response.ok) {
|
|
2842
2280
|
const data = await response.json();
|
|
2843
|
-
console.log(`Transaction sent on ${chain2}:`, data);
|
|
2844
2281
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
2845
2282
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
2846
2283
|
txHash = txHash.hash;
|
|
2847
2284
|
}
|
|
2848
|
-
if (
|
|
2285
|
+
if (chain === "ethereum" && txHash && (typeof txHash !== "string" || !txHash.startsWith("0x") || txHash.length !== 66)) {
|
|
2849
2286
|
console.warn(`Invalid Ethereum tx hash format: ${txHash} (length: ${txHash?.length}, expected: 66)`);
|
|
2850
2287
|
}
|
|
2851
2288
|
return {
|
|
@@ -2854,7 +2291,7 @@ var WalletManager = class _WalletManager {
|
|
|
2854
2291
|
from: fromAddress,
|
|
2855
2292
|
to,
|
|
2856
2293
|
amount,
|
|
2857
|
-
chain
|
|
2294
|
+
chain
|
|
2858
2295
|
};
|
|
2859
2296
|
}
|
|
2860
2297
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -2863,7 +2300,7 @@ var WalletManager = class _WalletManager {
|
|
|
2863
2300
|
error: errorData.error || `HTTP ${response.status}`
|
|
2864
2301
|
};
|
|
2865
2302
|
} catch (error) {
|
|
2866
|
-
console.error(`Transaction failed on ${
|
|
2303
|
+
console.error(`Transaction failed on ${chain}:`, error);
|
|
2867
2304
|
return {
|
|
2868
2305
|
success: false,
|
|
2869
2306
|
error: error instanceof Error ? error.message : "Transaction failed"
|
|
@@ -2873,7 +2310,7 @@ var WalletManager = class _WalletManager {
|
|
|
2873
2310
|
/**
|
|
2874
2311
|
* Estimate transaction fee using Tether WDK
|
|
2875
2312
|
*/
|
|
2876
|
-
async estimateFee(
|
|
2313
|
+
async estimateFee(chain, to, amount, token) {
|
|
2877
2314
|
try {
|
|
2878
2315
|
const headers = {
|
|
2879
2316
|
"Content-Type": "application/json"
|
|
@@ -2885,7 +2322,7 @@ var WalletManager = class _WalletManager {
|
|
|
2885
2322
|
method: "POST",
|
|
2886
2323
|
headers,
|
|
2887
2324
|
body: JSON.stringify({
|
|
2888
|
-
chain
|
|
2325
|
+
chain,
|
|
2889
2326
|
to,
|
|
2890
2327
|
amount,
|
|
2891
2328
|
token,
|
|
@@ -3094,12 +2531,12 @@ function useWalletManager(options = {}) {
|
|
|
3094
2531
|
setIsLoading(false);
|
|
3095
2532
|
}
|
|
3096
2533
|
}, [manager]);
|
|
3097
|
-
const setSelectedChain = react.useCallback((
|
|
3098
|
-
manager.setSelectedChain(
|
|
3099
|
-
setSelectedChainState(
|
|
2534
|
+
const setSelectedChain = react.useCallback((chain) => {
|
|
2535
|
+
manager.setSelectedChain(chain);
|
|
2536
|
+
setSelectedChainState(chain);
|
|
3100
2537
|
}, [manager]);
|
|
3101
2538
|
const getAddressForChain = react.useCallback(
|
|
3102
|
-
(
|
|
2539
|
+
(chain) => manager.getAddressForChain(chain),
|
|
3103
2540
|
[manager]
|
|
3104
2541
|
);
|
|
3105
2542
|
const getAllAddresses = react.useCallback(
|
|
@@ -3109,10 +2546,10 @@ function useWalletManager(options = {}) {
|
|
|
3109
2546
|
const hasWallet = react.useCallback(() => manager.hasWallet(), [manager]);
|
|
3110
2547
|
const getSeed = react.useCallback(() => manager.getSeed(), [manager]);
|
|
3111
2548
|
const sendTransaction = react.useCallback(
|
|
3112
|
-
async (
|
|
2549
|
+
async (chain, to, amount, token) => {
|
|
3113
2550
|
setIsLoading(true);
|
|
3114
2551
|
try {
|
|
3115
|
-
const result = await manager.sendTransaction(
|
|
2552
|
+
const result = await manager.sendTransaction(chain, to, amount, token);
|
|
3116
2553
|
if (result.success) {
|
|
3117
2554
|
try {
|
|
3118
2555
|
const balances = await manager.fetchAllBalances();
|
|
@@ -3129,8 +2566,8 @@ function useWalletManager(options = {}) {
|
|
|
3129
2566
|
[manager]
|
|
3130
2567
|
);
|
|
3131
2568
|
const estimateFee = react.useCallback(
|
|
3132
|
-
async (
|
|
3133
|
-
return manager.estimateFee(
|
|
2569
|
+
async (chain, to, amount, token) => {
|
|
2570
|
+
return manager.estimateFee(chain, to, amount, token);
|
|
3134
2571
|
},
|
|
3135
2572
|
[manager]
|
|
3136
2573
|
);
|
|
@@ -3164,14 +2601,6 @@ function useWalletManager(options = {}) {
|
|
|
3164
2601
|
manager
|
|
3165
2602
|
};
|
|
3166
2603
|
}
|
|
3167
|
-
/*! Bundled license information:
|
|
3168
|
-
|
|
3169
|
-
@scure/base/index.js:
|
|
3170
|
-
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
3171
|
-
|
|
3172
|
-
@scure/bip32/index.js:
|
|
3173
|
-
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
3174
|
-
*/
|
|
3175
2604
|
|
|
3176
2605
|
exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS;
|
|
3177
2606
|
exports.useWalletManager = useWalletManager;
|