@ecency/wallets 1.5.55 → 2.0.0

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.
@@ -2,21 +2,11 @@
2
2
 
3
3
  var sdk = require('@ecency/sdk');
4
4
  var reactQuery = require('@tanstack/react-query');
5
- var bip39 = require('bip39');
5
+ var R = require('remeda');
6
6
  var lruCache = require('lru-cache');
7
- var coinBitcoin = require('@okxweb3/coin-bitcoin');
8
- var coinEthereum = require('@okxweb3/coin-ethereum');
9
- var coinTron = require('@okxweb3/coin-tron');
10
- var coinTon = require('@okxweb3/coin-ton');
11
- var coinSolana = require('@okxweb3/coin-solana');
12
- var coinAptos = require('@okxweb3/coin-aptos');
13
- var cryptoLib = require('@okxweb3/crypto-lib');
7
+ var bip39 = require('bip39');
8
+ var bip32 = require('@scure/bip32');
14
9
  var dhive = require('@hiveio/dhive');
15
- var crypto = require('@hiveio/dhive/lib/crypto');
16
- var memo = require('@hiveio/dhive/lib/memo');
17
- var R = require('remeda');
18
-
19
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
10
 
21
11
  function _interopNamespace(e) {
22
12
  if (e && e.__esModule) return e;
@@ -36,7 +26,6 @@ function _interopNamespace(e) {
36
26
  return Object.freeze(n);
37
27
  }
38
28
 
39
- var bip39__default = /*#__PURE__*/_interopDefault(bip39);
40
29
  var R__namespace = /*#__PURE__*/_interopNamespace(R);
41
30
 
42
31
  var __defProp = Object.defineProperty;
@@ -81,9 +70,6 @@ var EcencyWalletCurrency = /* @__PURE__ */ ((EcencyWalletCurrency2) => {
81
70
  EcencyWalletCurrency2["BTC"] = "BTC";
82
71
  EcencyWalletCurrency2["ETH"] = "ETH";
83
72
  EcencyWalletCurrency2["BNB"] = "BNB";
84
- EcencyWalletCurrency2["APT"] = "APT";
85
- EcencyWalletCurrency2["TON"] = "TON";
86
- EcencyWalletCurrency2["TRON"] = "TRX";
87
73
  EcencyWalletCurrency2["SOL"] = "SOL";
88
74
  return EcencyWalletCurrency2;
89
75
  })(EcencyWalletCurrency || {});
@@ -96,14 +82,125 @@ var EcencyWalletBasicTokens = /* @__PURE__ */ ((EcencyWalletBasicTokens2) => {
96
82
  EcencyWalletBasicTokens2["HiveDollar"] = "HBD";
97
83
  return EcencyWalletBasicTokens2;
98
84
  })(EcencyWalletBasicTokens || {});
85
+
86
+ // src/modules/wallets/mutations/private-api/index.ts
87
+ var private_api_exports = {};
88
+ __export(private_api_exports, {
89
+ useCheckWalletExistence: () => useCheckWalletExistence,
90
+ useCreateAccountWithWallets: () => useCreateAccountWithWallets,
91
+ useUpdateAccountWithWallets: () => useUpdateAccountWithWallets
92
+ });
93
+
94
+ // src/modules/wallets/utils/get-bound-fetch.ts
95
+ var cachedFetch;
96
+ function getBoundFetch() {
97
+ if (!cachedFetch) {
98
+ if (typeof globalThis.fetch !== "function") {
99
+ throw new Error("[Ecency][Wallets] - global fetch is not available");
100
+ }
101
+ cachedFetch = globalThis.fetch.bind(globalThis);
102
+ }
103
+ return cachedFetch;
104
+ }
105
+ function useCreateAccountWithWallets(username) {
106
+ const fetchApi = getBoundFetch();
107
+ return reactQuery.useMutation({
108
+ mutationKey: ["ecency-wallets", "create-account-with-wallets", username],
109
+ mutationFn: async ({ currency, address, hiveKeys, walletAddresses }) => {
110
+ const addresses = {};
111
+ if (walletAddresses) {
112
+ for (const [k, v] of Object.entries(walletAddresses)) {
113
+ if (v) addresses[k] = v;
114
+ }
115
+ }
116
+ const response = await fetchApi(`${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
117
+ method: "POST",
118
+ headers: {
119
+ "Content-Type": "application/json"
120
+ },
121
+ body: JSON.stringify({
122
+ username,
123
+ token: currency,
124
+ address,
125
+ meta: {
126
+ ...hiveKeys,
127
+ ...addresses,
128
+ [currency]: address
129
+ }
130
+ })
131
+ });
132
+ if (!response.ok) {
133
+ throw new Error(`Account creation failed (${response.status})`);
134
+ }
135
+ return response;
136
+ }
137
+ });
138
+ }
139
+ function useCheckWalletExistence() {
140
+ return reactQuery.useMutation({
141
+ mutationKey: ["ecency-wallets", "check-wallet-existence"],
142
+ mutationFn: async ({ address, currency }) => {
143
+ const response = await fetch(
144
+ `${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-exist`,
145
+ {
146
+ method: "POST",
147
+ headers: {
148
+ "Content-Type": "application/json"
149
+ },
150
+ body: JSON.stringify({
151
+ address,
152
+ token: currency
153
+ })
154
+ }
155
+ );
156
+ const data = await response.json();
157
+ return data.length === 0;
158
+ }
159
+ });
160
+ }
161
+ function useUpdateAccountWithWallets(username, accessToken) {
162
+ const fetchApi = getBoundFetch();
163
+ return reactQuery.useMutation({
164
+ mutationKey: ["ecency-wallets", "update-account-with-wallets", username],
165
+ mutationFn: async ({ tokens, hiveKeys }) => {
166
+ const entries = Object.entries(tokens).filter(([, address]) => Boolean(address));
167
+ if (entries.length === 0) {
168
+ return new Response(null, { status: 204 });
169
+ }
170
+ const [primaryToken, primaryAddress] = entries[0] ?? ["", ""];
171
+ if (!accessToken) {
172
+ throw new Error(
173
+ "[SDK][Wallets][PrivateApi][WalletsAdd] \u2013 access token wasn`t found"
174
+ );
175
+ }
176
+ return fetchApi(`${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
177
+ method: "POST",
178
+ headers: {
179
+ "Content-Type": "application/json"
180
+ },
181
+ body: JSON.stringify({
182
+ username,
183
+ code: accessToken,
184
+ token: primaryToken,
185
+ address: primaryAddress,
186
+ status: 3,
187
+ meta: {
188
+ ...Object.fromEntries(entries),
189
+ ownerPublicKey: hiveKeys.ownerPublicKey,
190
+ activePublicKey: hiveKeys.activePublicKey,
191
+ postingPublicKey: hiveKeys.postingPublicKey,
192
+ memoPublicKey: hiveKeys.memoPublicKey
193
+ }
194
+ })
195
+ });
196
+ }
197
+ });
198
+ }
99
199
  var currencyChainMap = {
100
200
  ["BTC" /* BTC */]: "btc",
101
201
  ["ETH" /* ETH */]: "eth",
102
202
  ["BNB" /* BNB */]: "bnb",
103
- ["SOL" /* SOL */]: "sol",
104
- ["TRX" /* TRON */]: "tron",
105
- ["TON" /* TON */]: "ton",
106
- ["APT" /* APT */]: "apt"
203
+ ["SOL" /* SOL */]: "sol"
107
204
  };
108
205
  function normalizeBalance(balance) {
109
206
  if (typeof balance === "number") {
@@ -212,19 +309,6 @@ function useGetExternalWalletBalanceQuery(currency, address) {
212
309
  }
213
310
  });
214
311
  }
215
- function useSeedPhrase(username) {
216
- return reactQuery.useQuery({
217
- queryKey: ["ecency-wallets", "seed", username],
218
- queryFn: async () => bip39__default.default.generateMnemonic(128),
219
- // CRITICAL: Prevent seed regeneration - cache forever
220
- // Once generated, the seed must NEVER change to ensure consistency between:
221
- // 1. Displayed seed phrase
222
- // 2. Downloaded seed file
223
- // 3. Keys sent to API for account creation
224
- staleTime: Infinity,
225
- gcTime: Infinity
226
- });
227
- }
228
312
  var options = {
229
313
  max: 500,
230
314
  // how long to live in ms
@@ -245,9 +329,6 @@ var CURRENCY_TO_TOKEN_MAP = {
245
329
  ["BTC" /* BTC */]: "btc",
246
330
  ["ETH" /* ETH */]: "eth",
247
331
  ["SOL" /* SOL */]: "sol",
248
- ["TON" /* TON */]: "ton",
249
- ["TRX" /* TRON */]: "trx",
250
- ["APT" /* APT */]: "apt",
251
332
  ["BNB" /* BNB */]: "bnb",
252
333
  HBD: "hbd",
253
334
  HIVE: "hive"
@@ -302,374 +383,80 @@ function getTokenPriceQueryOptions(currency) {
302
383
  enabled: !!currency
303
384
  });
304
385
  }
305
-
306
- // src/modules/wallets/utils/delay.ts
307
- function delay(ms) {
308
- return new Promise((resolve) => setTimeout(resolve, ms));
309
- }
310
- function getWallet(currency) {
311
- switch (currency) {
312
- case "BTC" /* BTC */:
313
- return new coinBitcoin.BtcWallet();
314
- case "ETH" /* ETH */:
315
- case "BNB" /* BNB */:
316
- return new coinEthereum.EthWallet();
317
- case "TRX" /* TRON */:
318
- return new coinTron.TrxWallet();
319
- case "TON" /* TON */:
320
- return new coinTon.TonWallet();
321
- case "SOL" /* SOL */:
322
- return new coinSolana.SolWallet();
323
- case "APT" /* APT */:
324
- return new coinAptos.AptosWallet();
325
- default:
326
- return void 0;
327
- }
328
- }
329
- function mnemonicToSeedBip39(value) {
330
- return bip39.mnemonicToSeedSync(value).toString("hex");
331
- }
332
- var ROLE_INDEX = {
333
- owner: 0,
334
- active: 1,
335
- posting: 2,
336
- memo: 3
337
- };
338
- function deriveHiveKey(mnemonic, role, accountIndex = 0) {
339
- const seed = bip39.mnemonicToSeedSync(mnemonic);
340
- const master = cryptoLib.bip32.fromSeed(seed);
341
- const path = `m/44'/3054'/${accountIndex}'/0'/${ROLE_INDEX[role]}'`;
342
- const child = master.derivePath(path);
343
- if (!child.privateKey) {
344
- throw new Error("[Ecency][Wallets] - hive key derivation failed");
345
- }
346
- const pk = dhive.PrivateKey.from(child.privateKey);
347
- return {
348
- privateKey: pk.toString(),
349
- publicKey: pk.createPublic().toString()
350
- };
351
- }
352
- function deriveHiveKeys(mnemonic, accountIndex = 0) {
353
- const owner = deriveHiveKey(mnemonic, "owner", accountIndex);
354
- const active = deriveHiveKey(mnemonic, "active", accountIndex);
355
- const posting = deriveHiveKey(mnemonic, "posting", accountIndex);
356
- const memo = deriveHiveKey(mnemonic, "memo", accountIndex);
357
- return {
358
- owner: owner.privateKey,
359
- active: active.privateKey,
360
- posting: posting.privateKey,
361
- memo: memo.privateKey,
362
- ownerPubkey: owner.publicKey,
363
- activePubkey: active.publicKey,
364
- postingPubkey: posting.publicKey,
365
- memoPubkey: memo.publicKey
366
- };
367
- }
368
- function deriveHiveMasterPasswordKey(username, masterPassword, role) {
369
- const pk = dhive.PrivateKey.fromLogin(username, masterPassword, role);
386
+ function createFallbackTokenMetadata(symbol) {
370
387
  return {
371
- privateKey: pk.toString(),
372
- publicKey: pk.createPublic().toString()
388
+ issuer: "",
389
+ symbol,
390
+ name: symbol,
391
+ metadata: "{}",
392
+ precision: 0,
393
+ maxSupply: "0",
394
+ supply: "0",
395
+ circulatingSupply: "0",
396
+ stakingEnabled: false,
397
+ unstakingCooldown: 0,
398
+ delegationEnabled: false,
399
+ undelegationCooldown: 0,
400
+ numberTransactions: 0,
401
+ totalStaked: "0"
373
402
  };
374
403
  }
375
- function deriveHiveMasterPasswordKeys(username, masterPassword) {
376
- const owner = deriveHiveMasterPasswordKey(username, masterPassword, "owner");
377
- const active = deriveHiveMasterPasswordKey(username, masterPassword, "active");
378
- const posting = deriveHiveMasterPasswordKey(
379
- username,
380
- masterPassword,
381
- "posting"
404
+ async function getLayer2TokensMetadata(username) {
405
+ if (!username) {
406
+ return [];
407
+ }
408
+ let balances = [];
409
+ try {
410
+ balances = await sdk.getQueryClient().fetchQuery(
411
+ sdk.getHiveEngineTokensBalancesQueryOptions(username)
412
+ );
413
+ } catch {
414
+ balances = [];
415
+ }
416
+ const uniqueSymbols = Array.from(
417
+ new Set(
418
+ balances.map((balance) => balance.symbol).filter((symbol) => Boolean(symbol))
419
+ )
382
420
  );
383
- const memo = deriveHiveMasterPasswordKey(username, masterPassword, "memo");
384
- return {
385
- owner: owner.privateKey,
386
- active: active.privateKey,
387
- posting: posting.privateKey,
388
- memo: memo.privateKey,
389
- ownerPubkey: owner.publicKey,
390
- activePubkey: active.publicKey,
391
- postingPubkey: posting.publicKey,
392
- memoPubkey: memo.publicKey
393
- };
394
- }
395
- async function detectHiveKeyDerivation(username, seed, type = "active") {
396
- const uname = username.trim().toLowerCase();
397
- const account = await sdk.CONFIG.queryClient.fetchQuery(
398
- sdk.getAccountFullQueryOptions(uname)
421
+ if (uniqueSymbols.length === 0) {
422
+ return [];
423
+ }
424
+ let metadataList = [];
425
+ try {
426
+ metadataList = await sdk.getQueryClient().fetchQuery(
427
+ sdk.getHiveEngineTokensMetadataQueryOptions(uniqueSymbols)
428
+ );
429
+ } catch {
430
+ metadataList = [];
431
+ }
432
+ const metadataBySymbol = new Map(
433
+ metadataList.map((token) => [token.symbol, token])
434
+ );
435
+ return uniqueSymbols.map(
436
+ (symbol) => metadataBySymbol.get(symbol) ?? createFallbackTokenMetadata(symbol)
399
437
  );
400
- const auth = account[type];
401
- const bip44 = deriveHiveKeys(seed);
402
- const bip44Pub = type === "owner" ? bip44.ownerPubkey : bip44.activePubkey;
403
- const matchBip44 = auth.key_auths.some(([pub]) => String(pub) === bip44Pub);
404
- if (matchBip44) return "bip44";
405
- const legacyPub = dhive.PrivateKey.fromLogin(uname, seed, type).createPublic().toString();
406
- const matchLegacy = auth.key_auths.some(([pub]) => String(pub) === legacyPub);
407
- if (matchLegacy) return "master-password";
408
- return "unknown";
409
- }
410
- function signDigest(digest, privateKey) {
411
- const key = dhive.PrivateKey.fromString(privateKey);
412
- const buf = typeof digest === "string" ? Buffer.from(digest, "hex") : digest;
413
- return key.sign(buf).toString();
414
- }
415
- function signTx(tx, privateKey, chainId) {
416
- const key = dhive.PrivateKey.fromString(privateKey);
417
- const chain = chainId ? Buffer.from(chainId, "hex") : void 0;
418
- return crypto.cryptoUtils.signTransaction(tx, key, chain);
419
- }
420
- async function signTxAndBroadcast(client, tx, privateKey, chainId) {
421
- const signed = signTx(tx, privateKey, chainId);
422
- return client.broadcast.send(signed);
423
438
  }
424
- function encryptMemoWithKeys(privateKey, publicKey, memo$1) {
425
- return memo.Memo.encode(dhive.PrivateKey.fromString(privateKey), publicKey, memo$1);
439
+ function getAllTokensListQueryOptions(username) {
440
+ return reactQuery.queryOptions({
441
+ queryKey: ["ecency-wallets", "all-tokens-list", username ?? null],
442
+ queryFn: async () => {
443
+ return {
444
+ basic: [
445
+ "POINTS" /* Points */,
446
+ "HIVE" /* Hive */,
447
+ "HP" /* HivePower */,
448
+ "HBD" /* HiveDollar */
449
+ ],
450
+ external: Object.values(EcencyWalletCurrency),
451
+ spk: ["SPK", "LARYNX", "LP"],
452
+ layer2: await getLayer2TokensMetadata(username)
453
+ };
454
+ }
455
+ });
426
456
  }
427
- async function encryptMemoWithAccounts(client, fromPrivateKey, toAccount, memo$1) {
428
- const [account] = await client.database.getAccounts([toAccount]);
429
- if (!account) {
430
- throw new Error("Account not found");
431
- }
432
- return memo.Memo.encode(dhive.PrivateKey.fromString(fromPrivateKey), account.memo_key, memo$1);
433
- }
434
- function decryptMemoWithKeys(privateKey, memo$1) {
435
- return memo.Memo.decode(dhive.PrivateKey.fromString(privateKey), memo$1);
436
- }
437
- var decryptMemoWithAccounts = decryptMemoWithKeys;
438
- async function signExternalTx(currency, params) {
439
- const wallet = getWallet(currency);
440
- if (!wallet) throw new Error("Unsupported currency");
441
- return wallet.signTransaction(params);
442
- }
443
- async function signExternalTxAndBroadcast(currency, params) {
444
- const signed = await signExternalTx(currency, params);
445
- switch (currency) {
446
- case "BTC" /* BTC */: {
447
- const res = await fetch("https://mempool.space/api/tx", {
448
- method: "POST",
449
- body: signed
450
- });
451
- if (!res.ok) throw new Error("Broadcast failed");
452
- return res.text();
453
- }
454
- case "ETH" /* ETH */:
455
- case "BNB" /* BNB */: {
456
- const rpcUrl = currency === "ETH" /* ETH */ ? "https://rpc.ankr.com/eth" : "https://bsc-dataseed.binance.org";
457
- const res = await fetch(rpcUrl, {
458
- method: "POST",
459
- headers: { "Content-Type": "application/json" },
460
- body: JSON.stringify({
461
- jsonrpc: "2.0",
462
- id: 1,
463
- method: "eth_sendRawTransaction",
464
- params: [signed]
465
- })
466
- });
467
- const json = await res.json();
468
- if (json.error) throw new Error(json.error.message);
469
- return json.result;
470
- }
471
- case "SOL" /* SOL */: {
472
- const res = await fetch(
473
- `https://rpc.helius.xyz/?api-key=${sdk.CONFIG.heliusApiKey}`,
474
- {
475
- method: "POST",
476
- headers: { "Content-Type": "application/json" },
477
- body: JSON.stringify({
478
- jsonrpc: "2.0",
479
- id: 1,
480
- method: "sendTransaction",
481
- params: [signed]
482
- })
483
- }
484
- );
485
- const json = await res.json();
486
- if (json.error) throw new Error(json.error.message);
487
- return json.result;
488
- }
489
- case "TRX" /* TRON */: {
490
- const res = await fetch(
491
- "https://api.trongrid.io/wallet/broadcasttransaction",
492
- {
493
- method: "POST",
494
- headers: { "Content-Type": "application/json" },
495
- body: typeof signed === "string" ? signed : JSON.stringify(signed)
496
- }
497
- );
498
- const json = await res.json();
499
- if (json.result === false) throw new Error(json.message);
500
- return json.txid || json.result;
501
- }
502
- case "TON" /* TON */: {
503
- const res = await fetch("https://toncenter.com/api/v2/sendTransaction", {
504
- method: "POST",
505
- headers: { "Content-Type": "application/json" },
506
- body: JSON.stringify({ boc: signed })
507
- });
508
- const json = await res.json();
509
- if (json.error) throw new Error(json.error.message || json.result);
510
- return json.result;
511
- }
512
- case "APT" /* APT */: {
513
- const res = await fetch(
514
- "https://fullnode.mainnet.aptoslabs.com/v1/transactions",
515
- {
516
- method: "POST",
517
- headers: { "Content-Type": "application/json" },
518
- body: typeof signed === "string" ? signed : JSON.stringify(signed)
519
- }
520
- );
521
- if (!res.ok) throw new Error("Broadcast failed");
522
- return res.json();
523
- }
524
- default:
525
- throw new Error("Unsupported currency");
526
- }
527
- }
528
- function buildPsbt(tx, network, maximumFeeRate) {
529
- return coinBitcoin.buildPsbt(tx, network, maximumFeeRate);
530
- }
531
- function buildEthTx(data) {
532
- return data;
533
- }
534
- function buildSolTx(data) {
535
- return data;
536
- }
537
- function buildTronTx(data) {
538
- return data;
539
- }
540
- function buildTonTx(data) {
541
- return data;
542
- }
543
- function buildAptTx(data) {
544
- return data;
545
- }
546
- function buildExternalTx(currency, tx) {
547
- switch (currency) {
548
- case "BTC" /* BTC */:
549
- return buildPsbt(tx);
550
- case "ETH" /* ETH */:
551
- case "BNB" /* BNB */:
552
- return buildEthTx(tx);
553
- case "SOL" /* SOL */:
554
- return buildSolTx(tx);
555
- case "TRX" /* TRON */:
556
- return buildTronTx(tx);
557
- case "TON" /* TON */:
558
- return buildTonTx(tx);
559
- case "APT" /* APT */:
560
- return buildAptTx(tx);
561
- default:
562
- throw new Error("Unsupported currency");
563
- }
564
- }
565
-
566
- // src/modules/wallets/utils/get-bound-fetch.ts
567
- var cachedFetch;
568
- function getBoundFetch() {
569
- if (!cachedFetch) {
570
- if (typeof globalThis.fetch !== "function") {
571
- throw new Error("[Ecency][Wallets] - global fetch is not available");
572
- }
573
- cachedFetch = globalThis.fetch.bind(globalThis);
574
- }
575
- return cachedFetch;
576
- }
577
-
578
- // src/modules/wallets/queries/use-hive-keys-query.ts
579
- function useHiveKeysQuery(username) {
580
- const { data: seed } = useSeedPhrase(username);
581
- return reactQuery.useQuery({
582
- queryKey: ["ecenc\u0443-wallets", "hive-keys", username, seed],
583
- staleTime: Infinity,
584
- queryFn: async () => {
585
- if (!seed) {
586
- throw new Error("[Ecency][Wallets] - no seed to create Hive account");
587
- }
588
- const method = await detectHiveKeyDerivation(username, seed).catch(
589
- () => "bip44"
590
- );
591
- const keys = method === "master-password" ? deriveHiveMasterPasswordKeys(username, seed) : deriveHiveKeys(seed);
592
- return {
593
- username,
594
- ...keys
595
- };
596
- }
597
- });
598
- }
599
- function createFallbackTokenMetadata(symbol) {
600
- return {
601
- issuer: "",
602
- symbol,
603
- name: symbol,
604
- metadata: "{}",
605
- precision: 0,
606
- maxSupply: "0",
607
- supply: "0",
608
- circulatingSupply: "0",
609
- stakingEnabled: false,
610
- unstakingCooldown: 0,
611
- delegationEnabled: false,
612
- undelegationCooldown: 0,
613
- numberTransactions: 0,
614
- totalStaked: "0"
615
- };
616
- }
617
- async function getLayer2TokensMetadata(username) {
618
- if (!username) {
619
- return [];
620
- }
621
- let balances = [];
622
- try {
623
- balances = await sdk.getQueryClient().fetchQuery(
624
- sdk.getHiveEngineTokensBalancesQueryOptions(username)
625
- );
626
- } catch {
627
- balances = [];
628
- }
629
- const uniqueSymbols = Array.from(
630
- new Set(
631
- balances.map((balance) => balance.symbol).filter((symbol) => Boolean(symbol))
632
- )
633
- );
634
- if (uniqueSymbols.length === 0) {
635
- return [];
636
- }
637
- let metadataList = [];
638
- try {
639
- metadataList = await sdk.getQueryClient().fetchQuery(
640
- sdk.getHiveEngineTokensMetadataQueryOptions(uniqueSymbols)
641
- );
642
- } catch {
643
- metadataList = [];
644
- }
645
- const metadataBySymbol = new Map(
646
- metadataList.map((token) => [token.symbol, token])
647
- );
648
- return uniqueSymbols.map(
649
- (symbol) => metadataBySymbol.get(symbol) ?? createFallbackTokenMetadata(symbol)
650
- );
651
- }
652
- function getAllTokensListQueryOptions(username) {
653
- return reactQuery.queryOptions({
654
- queryKey: ["ecency-wallets", "all-tokens-list", username ?? null],
655
- queryFn: async () => {
656
- return {
657
- basic: [
658
- "POINTS" /* Points */,
659
- "HIVE" /* Hive */,
660
- "HP" /* HivePower */,
661
- "HBD" /* HiveDollar */
662
- ],
663
- external: Object.values(EcencyWalletCurrency),
664
- spk: ["SPK", "LARYNX", "LP"],
665
- layer2: await getLayer2TokensMetadata(username)
666
- };
667
- }
668
- });
669
- }
670
- function normalizeAccountTokens(tokens) {
671
- if (Array.isArray(tokens)) {
672
- return tokens.filter(Boolean);
457
+ function normalizeAccountTokens(tokens) {
458
+ if (Array.isArray(tokens)) {
459
+ return tokens.filter(Boolean);
673
460
  }
674
461
  if (tokens && typeof tokens === "object") {
675
462
  return Object.values(tokens).flatMap(
@@ -856,269 +643,8 @@ function getTokenOperationsQueryOptions(token, username, isForOwner = false, cur
856
643
  }
857
644
  });
858
645
  }
859
- function useWalletsCacheQuery(username) {
860
- const queryClient = reactQuery.useQueryClient();
861
- const queryKey = ["ecency-wallets", "wallets", username];
862
- const getCachedWallets = () => queryClient.getQueryData(queryKey);
863
- const createEmptyWalletMap = () => /* @__PURE__ */ new Map();
864
- return reactQuery.useQuery({
865
- queryKey,
866
- enabled: Boolean(username),
867
- initialData: () => getCachedWallets() ?? createEmptyWalletMap(),
868
- queryFn: async () => getCachedWallets() ?? createEmptyWalletMap(),
869
- staleTime: Infinity
870
- });
871
- }
872
- var PATHS = {
873
- ["BTC" /* BTC */]: "m/44'/0'/0'/0/0",
874
- // Bitcoin (BIP44)
875
- ["ETH" /* ETH */]: "m/44'/60'/0'/0/0",
876
- // Ethereum (BIP44)
877
- ["BNB" /* BNB */]: "m/44'/60'/0'/0/0",
878
- // BNB Smart Chain (BIP44)
879
- ["SOL" /* SOL */]: "m/44'/501'/0'/0'",
880
- // Solana (BIP44)
881
- ["TON" /* TON */]: "m/44'/607'/0'",
882
- // TON (BIP44)
883
- ["TRX" /* TRON */]: "m/44'/195'/0'/0/0",
884
- // Tron (BIP44)
885
- ["APT" /* APT */]: "m/44'/637'/0'/0'/0'"
886
- // Aptos (BIP44)
887
- };
888
- function useWalletCreate(username, currency, importedSeed) {
889
- const { data: generatedMnemonic } = useSeedPhrase(username);
890
- const queryClient = reactQuery.useQueryClient();
891
- const createWallet = reactQuery.useMutation({
892
- mutationKey: ["ecency-wallets", "create-wallet", username, currency],
893
- mutationFn: async () => {
894
- const mnemonic = importedSeed || generatedMnemonic;
895
- if (!mnemonic) {
896
- throw new Error("[Ecency][Wallets] - No seed to create a wallet");
897
- }
898
- const wallet = getWallet(currency);
899
- const privateKey = await wallet?.getDerivedPrivateKey({
900
- mnemonic,
901
- hdPath: PATHS[currency]
902
- });
903
- await delay(1e3);
904
- const address = await wallet?.getNewAddress({
905
- privateKey
906
- });
907
- return {
908
- privateKey,
909
- address: address.address,
910
- publicKey: address.publicKey,
911
- username,
912
- currency
913
- };
914
- },
915
- onSuccess: (info) => {
916
- queryClient.setQueryData(
917
- ["ecency-wallets", "wallets", info.username],
918
- (data) => new Map(data ? Array.from(data.entries()) : []).set(
919
- info.currency,
920
- info
921
- )
922
- );
923
- }
924
- });
925
- const importWallet = () => {
926
- };
927
- return {
928
- createWallet,
929
- importWallet
930
- };
931
- }
932
646
 
933
- // src/modules/wallets/mutations/private-api/index.ts
934
- var private_api_exports = {};
935
- __export(private_api_exports, {
936
- useCheckWalletExistence: () => useCheckWalletExistence,
937
- useCreateAccountWithWallets: () => useCreateAccountWithWallets,
938
- useUpdateAccountWithWallets: () => useUpdateAccountWithWallets
939
- });
940
- function useCreateAccountWithWallets(username) {
941
- const { data } = useWalletsCacheQuery(username);
942
- const { data: hiveKeys } = useHiveKeysQuery(username);
943
- const fetchApi = getBoundFetch();
944
- return reactQuery.useMutation({
945
- mutationKey: ["ecency-wallets", "create-account-with-wallets", username],
946
- mutationFn: ({ currency, address }) => fetchApi(`${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
947
- method: "POST",
948
- headers: {
949
- "Content-Type": "application/json"
950
- },
951
- body: JSON.stringify({
952
- username,
953
- token: currency,
954
- address,
955
- meta: {
956
- ownerPublicKey: hiveKeys?.ownerPubkey,
957
- activePublicKey: hiveKeys?.activePubkey,
958
- postingPublicKey: hiveKeys?.postingPubkey,
959
- memoPublicKey: hiveKeys?.memoPubkey,
960
- ...Array.from(data?.entries() ?? []).reduce(
961
- (acc, [curr, info]) => ({
962
- ...acc,
963
- [curr]: info.address
964
- }),
965
- {}
966
- )
967
- }
968
- })
969
- })
970
- });
971
- }
972
- function useCheckWalletExistence() {
973
- return reactQuery.useMutation({
974
- mutationKey: ["ecency-wallets", "check-wallet-existence"],
975
- mutationFn: async ({ address, currency }) => {
976
- const response = await fetch(
977
- `${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-exist`,
978
- {
979
- method: "POST",
980
- headers: {
981
- "Content-Type": "application/json"
982
- },
983
- body: JSON.stringify({
984
- address,
985
- token: currency
986
- })
987
- }
988
- );
989
- const data = await response.json();
990
- return data.length === 0;
991
- }
992
- });
993
- }
994
- function useUpdateAccountWithWallets(username, accessToken) {
995
- const fetchApi = getBoundFetch();
996
- return reactQuery.useMutation({
997
- mutationKey: ["ecency-wallets", "update-account-with-wallets", username],
998
- mutationFn: async ({ tokens, hiveKeys }) => {
999
- const entries = Object.entries(tokens).filter(([, address]) => Boolean(address));
1000
- if (entries.length === 0) {
1001
- return new Response(null, { status: 204 });
1002
- }
1003
- const [primaryToken, primaryAddress] = entries[0] ?? ["", ""];
1004
- if (!accessToken) {
1005
- throw new Error(
1006
- "[SDK][Wallets][PrivateApi][WalletsAdd] \u2013 access token wasn`t found"
1007
- );
1008
- }
1009
- return fetchApi(`${sdk.ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
1010
- method: "POST",
1011
- headers: {
1012
- "Content-Type": "application/json"
1013
- },
1014
- body: JSON.stringify({
1015
- username,
1016
- code: accessToken,
1017
- token: primaryToken,
1018
- address: primaryAddress,
1019
- status: 3,
1020
- meta: {
1021
- ...Object.fromEntries(entries),
1022
- ownerPublicKey: hiveKeys.ownerPublicKey,
1023
- activePublicKey: hiveKeys.activePublicKey,
1024
- postingPublicKey: hiveKeys.postingPublicKey,
1025
- memoPublicKey: hiveKeys.memoPublicKey
1026
- }
1027
- })
1028
- });
1029
- }
1030
- });
1031
- }
1032
-
1033
- // src/modules/wallets/functions/get-keys-from-seed.ts
1034
- var HD_PATHS = {
1035
- ["BTC" /* BTC */]: ["m/84'/0'/0'/0/0"],
1036
- ["ETH" /* ETH */]: ["m/84'/60'/0'/0/0"],
1037
- // its not working for Trust, Exodus, todo: check others below
1038
- ["BNB" /* BNB */]: ["m/84'/60'/0'/0/0"],
1039
- ["SOL" /* SOL */]: ["m/84'/501'/0'/0/0"],
1040
- ["TRX" /* TRON */]: ["m/44'/195'/0'/0'/0'"],
1041
- ["APT" /* APT */]: ["m/84'/637'/0'/0/0"],
1042
- ["TON" /* TON */]: ["m/44'/607'/0'"]
1043
- };
1044
- async function getKeysFromSeed(mnemonic, wallet, currency) {
1045
- for (const hdPath of HD_PATHS[currency] || []) {
1046
- try {
1047
- const derivedPrivateKey = await wallet.getDerivedPrivateKey({
1048
- mnemonic,
1049
- hdPath
1050
- });
1051
- const derivedPublicKey = await wallet.getNewAddress({
1052
- privateKey: derivedPrivateKey,
1053
- addressType: currency === "BTC" /* BTC */ ? "segwit_native" : void 0
1054
- });
1055
- return [derivedPrivateKey.toString(), derivedPublicKey.address];
1056
- } catch (error) {
1057
- return [];
1058
- }
1059
- }
1060
- return [];
1061
- }
1062
- function useImportWallet(username, currency) {
1063
- const queryClient = reactQuery.useQueryClient();
1064
- const { mutateAsync: checkWalletExistence } = private_api_exports.useCheckWalletExistence();
1065
- return reactQuery.useMutation({
1066
- mutationKey: ["ecency-wallets", "import-wallet", username, currency],
1067
- mutationFn: async ({ privateKeyOrSeed }) => {
1068
- const wallet = getWallet(currency);
1069
- if (!wallet) {
1070
- throw new Error("Cannot find token for this currency");
1071
- }
1072
- const isSeed = privateKeyOrSeed.split(" ").length === 12;
1073
- let address;
1074
- let privateKey = privateKeyOrSeed;
1075
- if (isSeed) {
1076
- [privateKey, address] = await getKeysFromSeed(
1077
- privateKeyOrSeed,
1078
- wallet,
1079
- currency
1080
- );
1081
- } else {
1082
- address = (await wallet.getNewAddress({
1083
- privateKey: privateKeyOrSeed
1084
- })).address;
1085
- }
1086
- if (!address || !privateKeyOrSeed) {
1087
- throw new Error(
1088
- "Private key/seed phrase isn't matching with public key or token"
1089
- );
1090
- }
1091
- const hasChecked = await checkWalletExistence({
1092
- address,
1093
- currency
1094
- });
1095
- if (!hasChecked) {
1096
- throw new Error(
1097
- "This wallet has already in use by Hive account. Please, try another one"
1098
- );
1099
- }
1100
- return {
1101
- privateKey,
1102
- address,
1103
- publicKey: ""
1104
- };
1105
- },
1106
- onSuccess: ({ privateKey, publicKey, address }) => {
1107
- queryClient.setQueryData(
1108
- ["ecency-wallets", "wallets", username],
1109
- (data) => new Map(data ? Array.from(data.entries()) : []).set(currency, {
1110
- privateKey,
1111
- publicKey,
1112
- address,
1113
- username,
1114
- currency,
1115
- type: "CHAIN",
1116
- custom: true
1117
- })
1118
- );
1119
- }
1120
- });
1121
- }
647
+ // src/modules/wallets/mutations/save-wallet-information-to-metadata.ts
1122
648
  function getGroupedChainTokens(tokens, defaultShow) {
1123
649
  if (!tokens) {
1124
650
  return {};
@@ -1195,6 +721,415 @@ function useSaveWalletInformationToMetadata(username, auth, options2) {
1195
721
  });
1196
722
  }
1197
723
 
724
+ // src/modules/wallets/utils/metamask-evm-transfer.ts
725
+ function getEthereum() {
726
+ if (typeof window === "undefined" || !window.ethereum) {
727
+ throw new Error("MetaMask not found");
728
+ }
729
+ return window.ethereum;
730
+ }
731
+ var WEI_PER_ETH = 1000000000000000000n;
732
+ var EVM_CHAIN_CONFIG = {
733
+ ["ETH" /* ETH */]: {
734
+ chainId: "0x1",
735
+ name: "Ethereum Mainnet",
736
+ rpcUrl: "https://rpc.ankr.com/eth",
737
+ explorerUrl: "https://etherscan.io/tx/"
738
+ },
739
+ ["BNB" /* BNB */]: {
740
+ chainId: "0x38",
741
+ name: "BNB Smart Chain",
742
+ rpcUrl: "https://bsc-dataseed.binance.org",
743
+ explorerUrl: "https://bscscan.com/tx/"
744
+ }
745
+ };
746
+ function getEvmChainConfig(currency) {
747
+ const config = EVM_CHAIN_CONFIG[currency];
748
+ if (!config) throw new Error(`Unsupported EVM currency: ${currency}`);
749
+ return config;
750
+ }
751
+ function getEvmExplorerUrl(currency, txHash) {
752
+ return `${getEvmChainConfig(currency).explorerUrl}${txHash}`;
753
+ }
754
+ async function ensureEvmChain(currency) {
755
+ const ethereum = getEthereum();
756
+ const { chainId, name, rpcUrl } = getEvmChainConfig(currency);
757
+ const currentChainId = await ethereum.request({ method: "eth_chainId" });
758
+ if (currentChainId === chainId) return;
759
+ try {
760
+ await ethereum.request({
761
+ method: "wallet_switchEthereumChain",
762
+ params: [{ chainId }]
763
+ });
764
+ } catch (err) {
765
+ if (typeof err === "object" && err !== null && "code" in err && err.code === 4902) {
766
+ await ethereum.request({
767
+ method: "wallet_addEthereumChain",
768
+ params: [{
769
+ chainId,
770
+ chainName: name,
771
+ rpcUrls: [rpcUrl],
772
+ nativeCurrency: {
773
+ name: currency === "ETH" /* ETH */ ? "Ether" : "BNB",
774
+ symbol: currency === "ETH" /* ETH */ ? "ETH" : "BNB",
775
+ decimals: 18
776
+ }
777
+ }]
778
+ });
779
+ } else {
780
+ throw err;
781
+ }
782
+ }
783
+ }
784
+ async function estimateEvmGas(from, to, valueHex, currency) {
785
+ const ethereum = getEthereum();
786
+ await ensureEvmChain(currency);
787
+ const [gasLimit, gasPrice] = await Promise.all([
788
+ ethereum.request({
789
+ method: "eth_estimateGas",
790
+ params: [{ from, to, value: valueHex }]
791
+ }),
792
+ ethereum.request({ method: "eth_gasPrice" })
793
+ ]);
794
+ const estimatedFeeWei = BigInt(gasLimit) * BigInt(gasPrice);
795
+ return { gasLimit, gasPrice, estimatedFeeWei };
796
+ }
797
+ function formatWei(wei, decimals = 6) {
798
+ const whole = wei / WEI_PER_ETH;
799
+ const rem = wei % WEI_PER_ETH;
800
+ if (rem === 0n) return whole.toString();
801
+ const scale = 10n ** BigInt(decimals);
802
+ const fractional = rem * scale / WEI_PER_ETH;
803
+ const fracStr = fractional.toString().padStart(decimals, "0").replace(/0+$/, "");
804
+ return fracStr ? `${whole}.${fracStr}` : whole.toString();
805
+ }
806
+ var AMOUNT_REGEX = /^\d+(\.\d+)?$/;
807
+ function parseToWei(amount) {
808
+ const trimmed = amount.trim();
809
+ if (!AMOUNT_REGEX.test(trimmed)) {
810
+ throw new Error(`Invalid amount: "${amount}"`);
811
+ }
812
+ const [whole, fraction = ""] = trimmed.split(".");
813
+ if (!/^\d+$/.test(whole) || fraction && !/^\d+$/.test(fraction)) {
814
+ throw new Error(`Invalid amount: "${amount}"`);
815
+ }
816
+ const paddedFraction = fraction.padEnd(18, "0").slice(0, 18);
817
+ const wei = BigInt(whole) * WEI_PER_ETH + BigInt(paddedFraction);
818
+ return "0x" + wei.toString(16);
819
+ }
820
+ async function sendEvmTransfer(to, amountWei, currency) {
821
+ const ethereum = getEthereum();
822
+ await ensureEvmChain(currency);
823
+ const accounts = await ethereum.request({ method: "eth_requestAccounts" });
824
+ const from = accounts[0];
825
+ if (!from) throw new Error("No MetaMask account connected");
826
+ const txHash = await ethereum.request({
827
+ method: "eth_sendTransaction",
828
+ params: [{
829
+ from,
830
+ to,
831
+ value: amountWei
832
+ }]
833
+ });
834
+ return txHash;
835
+ }
836
+ var SOL_EXPLORER_URL = "https://explorer.solana.com/tx/";
837
+ var LAMPORTS_PER_SOL = 1000000000n;
838
+ var AMOUNT_REGEX2 = /^\d+(\.\d+)?$/;
839
+ function getSolExplorerUrl(signature) {
840
+ return `${SOL_EXPLORER_URL}${signature}`;
841
+ }
842
+ function parseToLamports(amount) {
843
+ const trimmed = amount.trim();
844
+ if (!AMOUNT_REGEX2.test(trimmed)) {
845
+ throw new Error(`Invalid amount: "${amount}"`);
846
+ }
847
+ const [whole, fraction = ""] = trimmed.split(".");
848
+ if (!/^\d+$/.test(whole) || fraction && !/^\d+$/.test(fraction)) {
849
+ throw new Error(`Invalid amount: "${amount}"`);
850
+ }
851
+ if (fraction.length > 9 && fraction.slice(9).replace(/0/g, "").length > 0) {
852
+ throw new Error(`Amount has more than 9 decimal places: "${amount}"`);
853
+ }
854
+ const paddedFraction = fraction.padEnd(9, "0").slice(0, 9);
855
+ return BigInt(whole) * LAMPORTS_PER_SOL + BigInt(paddedFraction);
856
+ }
857
+ function formatLamports(lamports, decimals = 6) {
858
+ const whole = lamports / LAMPORTS_PER_SOL;
859
+ const rem = lamports % LAMPORTS_PER_SOL;
860
+ if (rem === 0n) return whole.toString();
861
+ const scale = 10n ** BigInt(decimals);
862
+ const fractional = rem * scale / LAMPORTS_PER_SOL;
863
+ const fracStr = fractional.toString().padStart(decimals, "0").replace(/0+$/, "");
864
+ return fracStr ? `${whole}.${fracStr}` : whole.toString();
865
+ }
866
+ function getSolRpcUrl() {
867
+ if (sdk.CONFIG.heliusApiKey) {
868
+ return `https://rpc.helius.xyz/?api-key=${sdk.CONFIG.heliusApiKey}`;
869
+ }
870
+ return "https://api.mainnet-beta.solana.com";
871
+ }
872
+ async function getMetaMaskSolanaWallet() {
873
+ const { getWallets } = await import('@wallet-standard/app');
874
+ const walletsApi = getWallets();
875
+ const wallets = walletsApi.get();
876
+ const mmWallet = wallets.find(
877
+ (w) => w.name.toLowerCase().includes("metamask") && w.features["standard:connect"] && w.features["solana:signAndSendTransaction"]
878
+ );
879
+ if (!mmWallet) {
880
+ throw new Error("MetaMask Solana wallet not found. Enable Solana in MetaMask settings.");
881
+ }
882
+ return mmWallet;
883
+ }
884
+ async function sendSolTransfer(to, amountSol) {
885
+ const mmWallet = await getMetaMaskSolanaWallet();
886
+ const connectFeature = mmWallet.features["standard:connect"];
887
+ await connectFeature.connect();
888
+ const solAccount = mmWallet.accounts?.find(
889
+ (acc) => acc.chains?.some((c) => c.startsWith("solana:"))
890
+ );
891
+ if (!solAccount) {
892
+ throw new Error("No Solana account found in MetaMask.");
893
+ }
894
+ const { Connection, PublicKey, SystemProgram, Transaction } = await import('@solana/web3.js');
895
+ const connection = new Connection(getSolRpcUrl(), "confirmed");
896
+ const fromPubkey = new PublicKey(solAccount.address);
897
+ const toPubkey = new PublicKey(to);
898
+ const lamports = parseToLamports(amountSol);
899
+ const transaction = new Transaction().add(
900
+ SystemProgram.transfer({
901
+ fromPubkey,
902
+ toPubkey,
903
+ lamports
904
+ })
905
+ );
906
+ const { blockhash } = await connection.getLatestBlockhash();
907
+ transaction.recentBlockhash = blockhash;
908
+ transaction.feePayer = fromPubkey;
909
+ const serializedTx = transaction.serialize({
910
+ requireAllSignatures: false,
911
+ verifySignatures: false
912
+ });
913
+ const signAndSendFeature = mmWallet.features["solana:signAndSendTransaction"];
914
+ if (!signAndSendFeature) {
915
+ throw new Error("MetaMask does not support Solana transaction signing. Please update MetaMask.");
916
+ }
917
+ const [result] = await signAndSendFeature.signAndSendTransaction({
918
+ account: solAccount,
919
+ transaction: serializedTx,
920
+ chain: "solana:mainnet"
921
+ });
922
+ if (typeof result.signature === "string") {
923
+ return result.signature;
924
+ }
925
+ const { base58 } = await import('@scure/base');
926
+ return base58.encode(new Uint8Array(result.signature));
927
+ }
928
+ function useExternalTransfer(currency) {
929
+ const queryClient = reactQuery.useQueryClient();
930
+ return reactQuery.useMutation({
931
+ mutationKey: ["ecency-wallets", "external-transfer", currency],
932
+ mutationFn: async ({ to, amount }) => {
933
+ switch (currency) {
934
+ case "ETH" /* ETH */:
935
+ case "BNB" /* BNB */: {
936
+ const valueHex = parseToWei(amount);
937
+ const txHash = await sendEvmTransfer(to, valueHex, currency);
938
+ return { txHash, currency };
939
+ }
940
+ case "SOL" /* SOL */: {
941
+ const signature = await sendSolTransfer(to, amount);
942
+ return { txHash: signature, currency };
943
+ }
944
+ }
945
+ },
946
+ onSuccess: () => {
947
+ queryClient.invalidateQueries({
948
+ queryKey: ["ecency-wallets", "external-wallet-balance"]
949
+ });
950
+ }
951
+ });
952
+ }
953
+ var ROLE_INDEX = {
954
+ owner: 0,
955
+ active: 1,
956
+ posting: 2,
957
+ memo: 3
958
+ };
959
+ function deriveHiveKey(mnemonic, role, accountIndex = 0) {
960
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
961
+ const master = bip32.HDKey.fromMasterSeed(seed);
962
+ const path = `m/44'/3054'/${accountIndex}'/0'/${ROLE_INDEX[role]}'`;
963
+ const child = master.derive(path);
964
+ if (!child.privateKey) {
965
+ throw new Error("[Ecency][Wallets] - hive key derivation failed");
966
+ }
967
+ const pk = dhive.PrivateKey.from(Buffer.from(child.privateKey));
968
+ return {
969
+ privateKey: pk.toString(),
970
+ publicKey: pk.createPublic().toString()
971
+ };
972
+ }
973
+ function deriveHiveKeys(mnemonic, accountIndex = 0) {
974
+ const owner = deriveHiveKey(mnemonic, "owner", accountIndex);
975
+ const active = deriveHiveKey(mnemonic, "active", accountIndex);
976
+ const posting = deriveHiveKey(mnemonic, "posting", accountIndex);
977
+ const memo = deriveHiveKey(mnemonic, "memo", accountIndex);
978
+ return {
979
+ owner: owner.privateKey,
980
+ active: active.privateKey,
981
+ posting: posting.privateKey,
982
+ memo: memo.privateKey,
983
+ ownerPubkey: owner.publicKey,
984
+ activePubkey: active.publicKey,
985
+ postingPubkey: posting.publicKey,
986
+ memoPubkey: memo.publicKey
987
+ };
988
+ }
989
+ function deriveHiveMasterPasswordKey(username, masterPassword, role) {
990
+ const pk = dhive.PrivateKey.fromLogin(username, masterPassword, role);
991
+ return {
992
+ privateKey: pk.toString(),
993
+ publicKey: pk.createPublic().toString()
994
+ };
995
+ }
996
+ function deriveHiveMasterPasswordKeys(username, masterPassword) {
997
+ const owner = deriveHiveMasterPasswordKey(username, masterPassword, "owner");
998
+ const active = deriveHiveMasterPasswordKey(username, masterPassword, "active");
999
+ const posting = deriveHiveMasterPasswordKey(
1000
+ username,
1001
+ masterPassword,
1002
+ "posting"
1003
+ );
1004
+ const memo = deriveHiveMasterPasswordKey(username, masterPassword, "memo");
1005
+ return {
1006
+ owner: owner.privateKey,
1007
+ active: active.privateKey,
1008
+ posting: posting.privateKey,
1009
+ memo: memo.privateKey,
1010
+ ownerPubkey: owner.publicKey,
1011
+ activePubkey: active.publicKey,
1012
+ postingPubkey: posting.publicKey,
1013
+ memoPubkey: memo.publicKey
1014
+ };
1015
+ }
1016
+ async function detectHiveKeyDerivation(username, seed, type = "active") {
1017
+ const uname = username.trim().toLowerCase();
1018
+ const account = await sdk.CONFIG.queryClient.fetchQuery(
1019
+ sdk.getAccountFullQueryOptions(uname)
1020
+ );
1021
+ const auth = account[type];
1022
+ const bip44 = deriveHiveKeys(seed);
1023
+ const bip44Pub = type === "owner" ? bip44.ownerPubkey : bip44.activePubkey;
1024
+ const matchBip44 = auth.key_auths.some(([pub]) => String(pub) === bip44Pub);
1025
+ if (matchBip44) return "bip44";
1026
+ const legacyPub = dhive.PrivateKey.fromLogin(uname, seed, type).createPublic().toString();
1027
+ const matchLegacy = auth.key_auths.some(([pub]) => String(pub) === legacyPub);
1028
+ if (matchLegacy) return "master-password";
1029
+ return "unknown";
1030
+ }
1031
+
1032
+ // src/modules/wallets/utils/metamask-discovery.ts
1033
+ var CHAIN_PREFIX_MAP = {
1034
+ "solana:": "SOL" /* SOL */,
1035
+ "bip122:": "BTC" /* BTC */
1036
+ };
1037
+ var HIVE_SNAP_ID = "npm:@hiveio/metamask-snap";
1038
+ async function fetchMultichainAddresses() {
1039
+ const addresses = {};
1040
+ try {
1041
+ const { getWallets } = await import('@wallet-standard/app');
1042
+ const walletsApi = getWallets();
1043
+ const wallets = walletsApi.get();
1044
+ const mmWallets = wallets.filter(
1045
+ (w) => w.name.toLowerCase().includes("metamask") && w.features["standard:connect"]
1046
+ );
1047
+ for (const mmWallet of mmWallets) {
1048
+ try {
1049
+ const connectFeature = mmWallet.features["standard:connect"];
1050
+ await connectFeature.connect();
1051
+ } catch (connectErr) {
1052
+ if (process.env.NODE_ENV === "development") {
1053
+ console.log("[MetaMask multichain] wallet connect failed, trying next:", connectErr);
1054
+ }
1055
+ continue;
1056
+ }
1057
+ for (const account of mmWallet.accounts ?? []) {
1058
+ if (!account.address || !Array.isArray(account.chains)) continue;
1059
+ for (const [prefix, currency] of Object.entries(CHAIN_PREFIX_MAP)) {
1060
+ if (addresses[currency]) continue;
1061
+ if (account.chains.some((c) => c.startsWith(prefix))) {
1062
+ addresses[currency] = account.address;
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+ } catch (e) {
1068
+ if (process.env.NODE_ENV === "development") {
1069
+ console.log("[MetaMask multichain] wallet standard discovery failed:", e);
1070
+ }
1071
+ }
1072
+ return addresses;
1073
+ }
1074
+ async function fetchEvmAddress() {
1075
+ if (typeof window === "undefined" || !window.ethereum?.isMetaMask) return void 0;
1076
+ try {
1077
+ const accounts = await window.ethereum.request({
1078
+ method: "eth_requestAccounts"
1079
+ });
1080
+ return accounts?.[0] ?? void 0;
1081
+ } catch {
1082
+ return void 0;
1083
+ }
1084
+ }
1085
+ async function discoverMetaMaskWallets() {
1086
+ const addresses = {};
1087
+ const evmAddress = await fetchEvmAddress();
1088
+ if (evmAddress) {
1089
+ addresses["ETH" /* ETH */] = evmAddress;
1090
+ addresses["BNB" /* BNB */] = evmAddress;
1091
+ }
1092
+ const multichainAddresses = await fetchMultichainAddresses();
1093
+ Object.assign(addresses, multichainAddresses);
1094
+ return addresses;
1095
+ }
1096
+ async function installHiveSnap() {
1097
+ if (typeof window === "undefined" || !window.ethereum) {
1098
+ throw new Error("MetaMask is not available");
1099
+ }
1100
+ await window.ethereum.request({
1101
+ method: "wallet_requestSnaps",
1102
+ params: { [HIVE_SNAP_ID]: {} }
1103
+ });
1104
+ }
1105
+ async function getHivePublicKeys() {
1106
+ if (typeof window === "undefined" || !window.ethereum) {
1107
+ throw new Error("MetaMask is not available");
1108
+ }
1109
+ const result = await window.ethereum.request({
1110
+ method: "wallet_invokeSnap",
1111
+ params: {
1112
+ snapId: HIVE_SNAP_ID,
1113
+ request: {
1114
+ method: "hive_getPublicKeys",
1115
+ params: {
1116
+ keys: [
1117
+ { role: "owner", accountIndex: 0 },
1118
+ { role: "active", accountIndex: 0 },
1119
+ { role: "posting", accountIndex: 0 },
1120
+ { role: "memo", accountIndex: 0 }
1121
+ ]
1122
+ }
1123
+ }
1124
+ }
1125
+ });
1126
+ const keys = result?.publicKeys;
1127
+ if (!Array.isArray(keys)) {
1128
+ throw new Error("Hive Snap returned invalid response \u2014 expected publicKeys array");
1129
+ }
1130
+ return keys;
1131
+ }
1132
+
1198
1133
  // src/index.ts
1199
1134
  rememberScryptBsvVersion();
1200
1135
 
@@ -1381,41 +1316,33 @@ Object.defineProperty(exports, "vestsToHp", {
1381
1316
  exports.EcencyWalletBasicTokens = EcencyWalletBasicTokens;
1382
1317
  exports.EcencyWalletCurrency = EcencyWalletCurrency;
1383
1318
  exports.EcencyWalletsPrivateApi = private_api_exports;
1384
- exports.buildAptTx = buildAptTx;
1385
- exports.buildEthTx = buildEthTx;
1386
- exports.buildExternalTx = buildExternalTx;
1387
- exports.buildPsbt = buildPsbt;
1388
- exports.buildSolTx = buildSolTx;
1389
- exports.buildTonTx = buildTonTx;
1390
- exports.buildTronTx = buildTronTx;
1391
- exports.decryptMemoWithAccounts = decryptMemoWithAccounts;
1392
- exports.decryptMemoWithKeys = decryptMemoWithKeys;
1393
- exports.delay = delay;
1394
1319
  exports.deriveHiveKey = deriveHiveKey;
1395
1320
  exports.deriveHiveKeys = deriveHiveKeys;
1396
1321
  exports.deriveHiveMasterPasswordKey = deriveHiveMasterPasswordKey;
1397
1322
  exports.deriveHiveMasterPasswordKeys = deriveHiveMasterPasswordKeys;
1398
1323
  exports.detectHiveKeyDerivation = detectHiveKeyDerivation;
1399
- exports.encryptMemoWithAccounts = encryptMemoWithAccounts;
1400
- exports.encryptMemoWithKeys = encryptMemoWithKeys;
1324
+ exports.discoverMetaMaskWallets = discoverMetaMaskWallets;
1325
+ exports.ensureEvmChain = ensureEvmChain;
1326
+ exports.estimateEvmGas = estimateEvmGas;
1327
+ exports.fetchEvmAddress = fetchEvmAddress;
1328
+ exports.fetchMultichainAddresses = fetchMultichainAddresses;
1329
+ exports.formatLamports = formatLamports;
1330
+ exports.formatWei = formatWei;
1401
1331
  exports.getAccountWalletListQueryOptions = getAccountWalletListQueryOptions;
1402
1332
  exports.getAllTokensListQueryOptions = getAllTokensListQueryOptions;
1403
- exports.getBoundFetch = getBoundFetch;
1333
+ exports.getEvmChainConfig = getEvmChainConfig;
1334
+ exports.getEvmExplorerUrl = getEvmExplorerUrl;
1335
+ exports.getHivePublicKeys = getHivePublicKeys;
1336
+ exports.getSolExplorerUrl = getSolExplorerUrl;
1404
1337
  exports.getTokenOperationsQueryOptions = getTokenOperationsQueryOptions;
1405
1338
  exports.getTokenPriceQueryOptions = getTokenPriceQueryOptions;
1406
- exports.getWallet = getWallet;
1407
- exports.mnemonicToSeedBip39 = mnemonicToSeedBip39;
1408
- exports.signDigest = signDigest;
1409
- exports.signExternalTx = signExternalTx;
1410
- exports.signExternalTxAndBroadcast = signExternalTxAndBroadcast;
1411
- exports.signTx = signTx;
1412
- exports.signTxAndBroadcast = signTxAndBroadcast;
1339
+ exports.installHiveSnap = installHiveSnap;
1340
+ exports.parseToLamports = parseToLamports;
1341
+ exports.parseToWei = parseToWei;
1342
+ exports.sendEvmTransfer = sendEvmTransfer;
1343
+ exports.sendSolTransfer = sendSolTransfer;
1344
+ exports.useExternalTransfer = useExternalTransfer;
1413
1345
  exports.useGetExternalWalletBalanceQuery = useGetExternalWalletBalanceQuery;
1414
- exports.useHiveKeysQuery = useHiveKeysQuery;
1415
- exports.useImportWallet = useImportWallet;
1416
1346
  exports.useSaveWalletInformationToMetadata = useSaveWalletInformationToMetadata;
1417
- exports.useSeedPhrase = useSeedPhrase;
1418
- exports.useWalletCreate = useWalletCreate;
1419
- exports.useWalletsCacheQuery = useWalletsCacheQuery;
1420
1347
  //# sourceMappingURL=index.cjs.map
1421
1348
  //# sourceMappingURL=index.cjs.map