@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.
- package/dist/browser/index.d.ts +109 -187
- package/dist/browser/index.js +526 -593
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +612 -685
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.mjs +531 -593
- package/dist/node/index.mjs.map +1 -1
- package/package.json +14 -10
package/dist/browser/index.js
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { ConfigManager,
|
|
1
|
+
import { ConfigManager, getPortfolioQueryOptions, getQueryClient, getAccountFullQueryOptions, AssetOperation, useAccountUpdate, CONFIG, getHiveEngineTokensBalancesQueryOptions, getHiveEngineTokensMetadataQueryOptions } from '@ecency/sdk';
|
|
2
2
|
export { AssetOperation, HIVE_ACCOUNT_OPERATION_GROUPS, HIVE_OPERATION_LIST, HIVE_OPERATION_NAME_BY_ID, HIVE_OPERATION_ORDERS, HiveEngineToken, NaiMap, PointTransactionType, Symbol, formattedNumber, getAccountWalletAssetInfoQueryOptions, getAllHiveEngineTokensQueryOptions, getHbdAssetGeneralInfoQueryOptions, getHbdAssetTransactionsQueryOptions, getHiveAssetGeneralInfoQueryOptions, getHiveAssetMetricQueryOptions, getHiveAssetTransactionsQueryOptions, getHiveAssetWithdrawalRoutesQueryOptions, getHiveEngineBalancesWithUsdQueryOptions, getHiveEngineTokenGeneralInfoQueryOptions, getHiveEngineTokenTransactionsQueryOptions, getHiveEngineTokensBalancesQueryOptions, getHiveEngineTokensMarketQueryOptions, getHiveEngineTokensMetadataQueryOptions, getHiveEngineTokensMetricsQueryOptions, getHiveEngineUnclaimedRewardsQueryOptions, getHivePowerAssetGeneralInfoQueryOptions, getHivePowerAssetTransactionsQueryOptions, getHivePowerDelegatesInfiniteQueryOptions, getHivePowerDelegatingsQueryOptions, getLarynxAssetGeneralInfoQueryOptions, getLarynxPowerAssetGeneralInfoQueryOptions, getPointsAssetGeneralInfoQueryOptions, getPointsAssetTransactionsQueryOptions, getPointsQueryOptions, getSpkAssetGeneralInfoQueryOptions, getSpkMarketsQueryOptions, getSpkWalletQueryOptions, isEmptyDate, parseAsset, resolveHiveOperationFilters, rewardSpk, useClaimPoints, useWalletOperation, vestsToHp } from '@ecency/sdk';
|
|
3
|
-
import { useQuery, queryOptions, useQueryClient
|
|
4
|
-
import
|
|
3
|
+
import { useMutation, useQuery, queryOptions, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import * as R from 'remeda';
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { TrxWallet } from '@okxweb3/coin-tron';
|
|
9
|
-
import { TonWallet } from '@okxweb3/coin-ton';
|
|
10
|
-
import { SolWallet } from '@okxweb3/coin-solana';
|
|
11
|
-
import { AptosWallet } from '@okxweb3/coin-aptos';
|
|
12
|
-
import { bip32 } from '@okxweb3/crypto-lib';
|
|
6
|
+
import { mnemonicToSeedSync } from 'bip39';
|
|
7
|
+
import { HDKey } from '@scure/bip32';
|
|
13
8
|
import { PrivateKey } from '@hiveio/dhive';
|
|
14
|
-
import { cryptoUtils } from '@hiveio/dhive/lib/crypto';
|
|
15
|
-
import { Memo } from '@hiveio/dhive/lib/memo';
|
|
16
|
-
import * as R from 'remeda';
|
|
17
9
|
|
|
18
10
|
var __defProp = Object.defineProperty;
|
|
19
11
|
var __export = (target, all) => {
|
|
@@ -57,9 +49,6 @@ var EcencyWalletCurrency = /* @__PURE__ */ ((EcencyWalletCurrency2) => {
|
|
|
57
49
|
EcencyWalletCurrency2["BTC"] = "BTC";
|
|
58
50
|
EcencyWalletCurrency2["ETH"] = "ETH";
|
|
59
51
|
EcencyWalletCurrency2["BNB"] = "BNB";
|
|
60
|
-
EcencyWalletCurrency2["APT"] = "APT";
|
|
61
|
-
EcencyWalletCurrency2["TON"] = "TON";
|
|
62
|
-
EcencyWalletCurrency2["TRON"] = "TRX";
|
|
63
52
|
EcencyWalletCurrency2["SOL"] = "SOL";
|
|
64
53
|
return EcencyWalletCurrency2;
|
|
65
54
|
})(EcencyWalletCurrency || {});
|
|
@@ -72,14 +61,125 @@ var EcencyWalletBasicTokens = /* @__PURE__ */ ((EcencyWalletBasicTokens2) => {
|
|
|
72
61
|
EcencyWalletBasicTokens2["HiveDollar"] = "HBD";
|
|
73
62
|
return EcencyWalletBasicTokens2;
|
|
74
63
|
})(EcencyWalletBasicTokens || {});
|
|
64
|
+
|
|
65
|
+
// src/modules/wallets/mutations/private-api/index.ts
|
|
66
|
+
var private_api_exports = {};
|
|
67
|
+
__export(private_api_exports, {
|
|
68
|
+
useCheckWalletExistence: () => useCheckWalletExistence,
|
|
69
|
+
useCreateAccountWithWallets: () => useCreateAccountWithWallets,
|
|
70
|
+
useUpdateAccountWithWallets: () => useUpdateAccountWithWallets
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// src/modules/wallets/utils/get-bound-fetch.ts
|
|
74
|
+
var cachedFetch;
|
|
75
|
+
function getBoundFetch() {
|
|
76
|
+
if (!cachedFetch) {
|
|
77
|
+
if (typeof globalThis.fetch !== "function") {
|
|
78
|
+
throw new Error("[Ecency][Wallets] - global fetch is not available");
|
|
79
|
+
}
|
|
80
|
+
cachedFetch = globalThis.fetch.bind(globalThis);
|
|
81
|
+
}
|
|
82
|
+
return cachedFetch;
|
|
83
|
+
}
|
|
84
|
+
function useCreateAccountWithWallets(username) {
|
|
85
|
+
const fetchApi = getBoundFetch();
|
|
86
|
+
return useMutation({
|
|
87
|
+
mutationKey: ["ecency-wallets", "create-account-with-wallets", username],
|
|
88
|
+
mutationFn: async ({ currency, address, hiveKeys, walletAddresses }) => {
|
|
89
|
+
const addresses = {};
|
|
90
|
+
if (walletAddresses) {
|
|
91
|
+
for (const [k, v] of Object.entries(walletAddresses)) {
|
|
92
|
+
if (v) addresses[k] = v;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const response = await fetchApi(`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: {
|
|
98
|
+
"Content-Type": "application/json"
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify({
|
|
101
|
+
username,
|
|
102
|
+
token: currency,
|
|
103
|
+
address,
|
|
104
|
+
meta: {
|
|
105
|
+
...hiveKeys,
|
|
106
|
+
...addresses,
|
|
107
|
+
[currency]: address
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
throw new Error(`Account creation failed (${response.status})`);
|
|
113
|
+
}
|
|
114
|
+
return response;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function useCheckWalletExistence() {
|
|
119
|
+
return useMutation({
|
|
120
|
+
mutationKey: ["ecency-wallets", "check-wallet-existence"],
|
|
121
|
+
mutationFn: async ({ address, currency }) => {
|
|
122
|
+
const response = await fetch(
|
|
123
|
+
`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-exist`,
|
|
124
|
+
{
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json"
|
|
128
|
+
},
|
|
129
|
+
body: JSON.stringify({
|
|
130
|
+
address,
|
|
131
|
+
token: currency
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
return data.length === 0;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function useUpdateAccountWithWallets(username, accessToken) {
|
|
141
|
+
const fetchApi = getBoundFetch();
|
|
142
|
+
return useMutation({
|
|
143
|
+
mutationKey: ["ecency-wallets", "update-account-with-wallets", username],
|
|
144
|
+
mutationFn: async ({ tokens, hiveKeys }) => {
|
|
145
|
+
const entries = Object.entries(tokens).filter(([, address]) => Boolean(address));
|
|
146
|
+
if (entries.length === 0) {
|
|
147
|
+
return new Response(null, { status: 204 });
|
|
148
|
+
}
|
|
149
|
+
const [primaryToken, primaryAddress] = entries[0] ?? ["", ""];
|
|
150
|
+
if (!accessToken) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
"[SDK][Wallets][PrivateApi][WalletsAdd] \u2013 access token wasn`t found"
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return fetchApi(`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
|
|
156
|
+
method: "POST",
|
|
157
|
+
headers: {
|
|
158
|
+
"Content-Type": "application/json"
|
|
159
|
+
},
|
|
160
|
+
body: JSON.stringify({
|
|
161
|
+
username,
|
|
162
|
+
code: accessToken,
|
|
163
|
+
token: primaryToken,
|
|
164
|
+
address: primaryAddress,
|
|
165
|
+
status: 3,
|
|
166
|
+
meta: {
|
|
167
|
+
...Object.fromEntries(entries),
|
|
168
|
+
ownerPublicKey: hiveKeys.ownerPublicKey,
|
|
169
|
+
activePublicKey: hiveKeys.activePublicKey,
|
|
170
|
+
postingPublicKey: hiveKeys.postingPublicKey,
|
|
171
|
+
memoPublicKey: hiveKeys.memoPublicKey
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
75
178
|
var currencyChainMap = {
|
|
76
179
|
["BTC" /* BTC */]: "btc",
|
|
77
180
|
["ETH" /* ETH */]: "eth",
|
|
78
181
|
["BNB" /* BNB */]: "bnb",
|
|
79
|
-
["SOL" /* SOL */]: "sol"
|
|
80
|
-
["TRX" /* TRON */]: "tron",
|
|
81
|
-
["TON" /* TON */]: "ton",
|
|
82
|
-
["APT" /* APT */]: "apt"
|
|
182
|
+
["SOL" /* SOL */]: "sol"
|
|
83
183
|
};
|
|
84
184
|
function normalizeBalance(balance) {
|
|
85
185
|
if (typeof balance === "number") {
|
|
@@ -188,19 +288,6 @@ function useGetExternalWalletBalanceQuery(currency, address) {
|
|
|
188
288
|
}
|
|
189
289
|
});
|
|
190
290
|
}
|
|
191
|
-
function useSeedPhrase(username) {
|
|
192
|
-
return useQuery({
|
|
193
|
-
queryKey: ["ecency-wallets", "seed", username],
|
|
194
|
-
queryFn: async () => bip39.generateMnemonic(128),
|
|
195
|
-
// CRITICAL: Prevent seed regeneration - cache forever
|
|
196
|
-
// Once generated, the seed must NEVER change to ensure consistency between:
|
|
197
|
-
// 1. Displayed seed phrase
|
|
198
|
-
// 2. Downloaded seed file
|
|
199
|
-
// 3. Keys sent to API for account creation
|
|
200
|
-
staleTime: Infinity,
|
|
201
|
-
gcTime: Infinity
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
291
|
var options = {
|
|
205
292
|
max: 500,
|
|
206
293
|
// how long to live in ms
|
|
@@ -221,9 +308,6 @@ var CURRENCY_TO_TOKEN_MAP = {
|
|
|
221
308
|
["BTC" /* BTC */]: "btc",
|
|
222
309
|
["ETH" /* ETH */]: "eth",
|
|
223
310
|
["SOL" /* SOL */]: "sol",
|
|
224
|
-
["TON" /* TON */]: "ton",
|
|
225
|
-
["TRX" /* TRON */]: "trx",
|
|
226
|
-
["APT" /* APT */]: "apt",
|
|
227
311
|
["BNB" /* BNB */]: "bnb",
|
|
228
312
|
HBD: "hbd",
|
|
229
313
|
HIVE: "hive"
|
|
@@ -278,300 +362,6 @@ function getTokenPriceQueryOptions(currency) {
|
|
|
278
362
|
enabled: !!currency
|
|
279
363
|
});
|
|
280
364
|
}
|
|
281
|
-
|
|
282
|
-
// src/modules/wallets/utils/delay.ts
|
|
283
|
-
function delay(ms) {
|
|
284
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
285
|
-
}
|
|
286
|
-
function getWallet(currency) {
|
|
287
|
-
switch (currency) {
|
|
288
|
-
case "BTC" /* BTC */:
|
|
289
|
-
return new BtcWallet();
|
|
290
|
-
case "ETH" /* ETH */:
|
|
291
|
-
case "BNB" /* BNB */:
|
|
292
|
-
return new EthWallet();
|
|
293
|
-
case "TRX" /* TRON */:
|
|
294
|
-
return new TrxWallet();
|
|
295
|
-
case "TON" /* TON */:
|
|
296
|
-
return new TonWallet();
|
|
297
|
-
case "SOL" /* SOL */:
|
|
298
|
-
return new SolWallet();
|
|
299
|
-
case "APT" /* APT */:
|
|
300
|
-
return new AptosWallet();
|
|
301
|
-
default:
|
|
302
|
-
return void 0;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
function mnemonicToSeedBip39(value) {
|
|
306
|
-
return mnemonicToSeedSync(value).toString("hex");
|
|
307
|
-
}
|
|
308
|
-
var ROLE_INDEX = {
|
|
309
|
-
owner: 0,
|
|
310
|
-
active: 1,
|
|
311
|
-
posting: 2,
|
|
312
|
-
memo: 3
|
|
313
|
-
};
|
|
314
|
-
function deriveHiveKey(mnemonic, role, accountIndex = 0) {
|
|
315
|
-
const seed = mnemonicToSeedSync(mnemonic);
|
|
316
|
-
const master = bip32.fromSeed(seed);
|
|
317
|
-
const path = `m/44'/3054'/${accountIndex}'/0'/${ROLE_INDEX[role]}'`;
|
|
318
|
-
const child = master.derivePath(path);
|
|
319
|
-
if (!child.privateKey) {
|
|
320
|
-
throw new Error("[Ecency][Wallets] - hive key derivation failed");
|
|
321
|
-
}
|
|
322
|
-
const pk = PrivateKey.from(child.privateKey);
|
|
323
|
-
return {
|
|
324
|
-
privateKey: pk.toString(),
|
|
325
|
-
publicKey: pk.createPublic().toString()
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
function deriveHiveKeys(mnemonic, accountIndex = 0) {
|
|
329
|
-
const owner = deriveHiveKey(mnemonic, "owner", accountIndex);
|
|
330
|
-
const active = deriveHiveKey(mnemonic, "active", accountIndex);
|
|
331
|
-
const posting = deriveHiveKey(mnemonic, "posting", accountIndex);
|
|
332
|
-
const memo = deriveHiveKey(mnemonic, "memo", accountIndex);
|
|
333
|
-
return {
|
|
334
|
-
owner: owner.privateKey,
|
|
335
|
-
active: active.privateKey,
|
|
336
|
-
posting: posting.privateKey,
|
|
337
|
-
memo: memo.privateKey,
|
|
338
|
-
ownerPubkey: owner.publicKey,
|
|
339
|
-
activePubkey: active.publicKey,
|
|
340
|
-
postingPubkey: posting.publicKey,
|
|
341
|
-
memoPubkey: memo.publicKey
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
function deriveHiveMasterPasswordKey(username, masterPassword, role) {
|
|
345
|
-
const pk = PrivateKey.fromLogin(username, masterPassword, role);
|
|
346
|
-
return {
|
|
347
|
-
privateKey: pk.toString(),
|
|
348
|
-
publicKey: pk.createPublic().toString()
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
function deriveHiveMasterPasswordKeys(username, masterPassword) {
|
|
352
|
-
const owner = deriveHiveMasterPasswordKey(username, masterPassword, "owner");
|
|
353
|
-
const active = deriveHiveMasterPasswordKey(username, masterPassword, "active");
|
|
354
|
-
const posting = deriveHiveMasterPasswordKey(
|
|
355
|
-
username,
|
|
356
|
-
masterPassword,
|
|
357
|
-
"posting"
|
|
358
|
-
);
|
|
359
|
-
const memo = deriveHiveMasterPasswordKey(username, masterPassword, "memo");
|
|
360
|
-
return {
|
|
361
|
-
owner: owner.privateKey,
|
|
362
|
-
active: active.privateKey,
|
|
363
|
-
posting: posting.privateKey,
|
|
364
|
-
memo: memo.privateKey,
|
|
365
|
-
ownerPubkey: owner.publicKey,
|
|
366
|
-
activePubkey: active.publicKey,
|
|
367
|
-
postingPubkey: posting.publicKey,
|
|
368
|
-
memoPubkey: memo.publicKey
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
async function detectHiveKeyDerivation(username, seed, type = "active") {
|
|
372
|
-
const uname = username.trim().toLowerCase();
|
|
373
|
-
const account = await CONFIG.queryClient.fetchQuery(
|
|
374
|
-
getAccountFullQueryOptions(uname)
|
|
375
|
-
);
|
|
376
|
-
const auth = account[type];
|
|
377
|
-
const bip44 = deriveHiveKeys(seed);
|
|
378
|
-
const bip44Pub = type === "owner" ? bip44.ownerPubkey : bip44.activePubkey;
|
|
379
|
-
const matchBip44 = auth.key_auths.some(([pub]) => String(pub) === bip44Pub);
|
|
380
|
-
if (matchBip44) return "bip44";
|
|
381
|
-
const legacyPub = PrivateKey.fromLogin(uname, seed, type).createPublic().toString();
|
|
382
|
-
const matchLegacy = auth.key_auths.some(([pub]) => String(pub) === legacyPub);
|
|
383
|
-
if (matchLegacy) return "master-password";
|
|
384
|
-
return "unknown";
|
|
385
|
-
}
|
|
386
|
-
function signDigest(digest, privateKey) {
|
|
387
|
-
const key = PrivateKey.fromString(privateKey);
|
|
388
|
-
const buf = typeof digest === "string" ? Buffer.from(digest, "hex") : digest;
|
|
389
|
-
return key.sign(buf).toString();
|
|
390
|
-
}
|
|
391
|
-
function signTx(tx, privateKey, chainId) {
|
|
392
|
-
const key = PrivateKey.fromString(privateKey);
|
|
393
|
-
const chain = chainId ? Buffer.from(chainId, "hex") : void 0;
|
|
394
|
-
return cryptoUtils.signTransaction(tx, key, chain);
|
|
395
|
-
}
|
|
396
|
-
async function signTxAndBroadcast(client, tx, privateKey, chainId) {
|
|
397
|
-
const signed = signTx(tx, privateKey, chainId);
|
|
398
|
-
return client.broadcast.send(signed);
|
|
399
|
-
}
|
|
400
|
-
function encryptMemoWithKeys(privateKey, publicKey, memo) {
|
|
401
|
-
return Memo.encode(PrivateKey.fromString(privateKey), publicKey, memo);
|
|
402
|
-
}
|
|
403
|
-
async function encryptMemoWithAccounts(client, fromPrivateKey, toAccount, memo) {
|
|
404
|
-
const [account] = await client.database.getAccounts([toAccount]);
|
|
405
|
-
if (!account) {
|
|
406
|
-
throw new Error("Account not found");
|
|
407
|
-
}
|
|
408
|
-
return Memo.encode(PrivateKey.fromString(fromPrivateKey), account.memo_key, memo);
|
|
409
|
-
}
|
|
410
|
-
function decryptMemoWithKeys(privateKey, memo) {
|
|
411
|
-
return Memo.decode(PrivateKey.fromString(privateKey), memo);
|
|
412
|
-
}
|
|
413
|
-
var decryptMemoWithAccounts = decryptMemoWithKeys;
|
|
414
|
-
async function signExternalTx(currency, params) {
|
|
415
|
-
const wallet = getWallet(currency);
|
|
416
|
-
if (!wallet) throw new Error("Unsupported currency");
|
|
417
|
-
return wallet.signTransaction(params);
|
|
418
|
-
}
|
|
419
|
-
async function signExternalTxAndBroadcast(currency, params) {
|
|
420
|
-
const signed = await signExternalTx(currency, params);
|
|
421
|
-
switch (currency) {
|
|
422
|
-
case "BTC" /* BTC */: {
|
|
423
|
-
const res = await fetch("https://mempool.space/api/tx", {
|
|
424
|
-
method: "POST",
|
|
425
|
-
body: signed
|
|
426
|
-
});
|
|
427
|
-
if (!res.ok) throw new Error("Broadcast failed");
|
|
428
|
-
return res.text();
|
|
429
|
-
}
|
|
430
|
-
case "ETH" /* ETH */:
|
|
431
|
-
case "BNB" /* BNB */: {
|
|
432
|
-
const rpcUrl = currency === "ETH" /* ETH */ ? "https://rpc.ankr.com/eth" : "https://bsc-dataseed.binance.org";
|
|
433
|
-
const res = await fetch(rpcUrl, {
|
|
434
|
-
method: "POST",
|
|
435
|
-
headers: { "Content-Type": "application/json" },
|
|
436
|
-
body: JSON.stringify({
|
|
437
|
-
jsonrpc: "2.0",
|
|
438
|
-
id: 1,
|
|
439
|
-
method: "eth_sendRawTransaction",
|
|
440
|
-
params: [signed]
|
|
441
|
-
})
|
|
442
|
-
});
|
|
443
|
-
const json = await res.json();
|
|
444
|
-
if (json.error) throw new Error(json.error.message);
|
|
445
|
-
return json.result;
|
|
446
|
-
}
|
|
447
|
-
case "SOL" /* SOL */: {
|
|
448
|
-
const res = await fetch(
|
|
449
|
-
`https://rpc.helius.xyz/?api-key=${CONFIG.heliusApiKey}`,
|
|
450
|
-
{
|
|
451
|
-
method: "POST",
|
|
452
|
-
headers: { "Content-Type": "application/json" },
|
|
453
|
-
body: JSON.stringify({
|
|
454
|
-
jsonrpc: "2.0",
|
|
455
|
-
id: 1,
|
|
456
|
-
method: "sendTransaction",
|
|
457
|
-
params: [signed]
|
|
458
|
-
})
|
|
459
|
-
}
|
|
460
|
-
);
|
|
461
|
-
const json = await res.json();
|
|
462
|
-
if (json.error) throw new Error(json.error.message);
|
|
463
|
-
return json.result;
|
|
464
|
-
}
|
|
465
|
-
case "TRX" /* TRON */: {
|
|
466
|
-
const res = await fetch(
|
|
467
|
-
"https://api.trongrid.io/wallet/broadcasttransaction",
|
|
468
|
-
{
|
|
469
|
-
method: "POST",
|
|
470
|
-
headers: { "Content-Type": "application/json" },
|
|
471
|
-
body: typeof signed === "string" ? signed : JSON.stringify(signed)
|
|
472
|
-
}
|
|
473
|
-
);
|
|
474
|
-
const json = await res.json();
|
|
475
|
-
if (json.result === false) throw new Error(json.message);
|
|
476
|
-
return json.txid || json.result;
|
|
477
|
-
}
|
|
478
|
-
case "TON" /* TON */: {
|
|
479
|
-
const res = await fetch("https://toncenter.com/api/v2/sendTransaction", {
|
|
480
|
-
method: "POST",
|
|
481
|
-
headers: { "Content-Type": "application/json" },
|
|
482
|
-
body: JSON.stringify({ boc: signed })
|
|
483
|
-
});
|
|
484
|
-
const json = await res.json();
|
|
485
|
-
if (json.error) throw new Error(json.error.message || json.result);
|
|
486
|
-
return json.result;
|
|
487
|
-
}
|
|
488
|
-
case "APT" /* APT */: {
|
|
489
|
-
const res = await fetch(
|
|
490
|
-
"https://fullnode.mainnet.aptoslabs.com/v1/transactions",
|
|
491
|
-
{
|
|
492
|
-
method: "POST",
|
|
493
|
-
headers: { "Content-Type": "application/json" },
|
|
494
|
-
body: typeof signed === "string" ? signed : JSON.stringify(signed)
|
|
495
|
-
}
|
|
496
|
-
);
|
|
497
|
-
if (!res.ok) throw new Error("Broadcast failed");
|
|
498
|
-
return res.json();
|
|
499
|
-
}
|
|
500
|
-
default:
|
|
501
|
-
throw new Error("Unsupported currency");
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
function buildPsbt(tx, network, maximumFeeRate) {
|
|
505
|
-
return buildPsbt$1(tx, network, maximumFeeRate);
|
|
506
|
-
}
|
|
507
|
-
function buildEthTx(data) {
|
|
508
|
-
return data;
|
|
509
|
-
}
|
|
510
|
-
function buildSolTx(data) {
|
|
511
|
-
return data;
|
|
512
|
-
}
|
|
513
|
-
function buildTronTx(data) {
|
|
514
|
-
return data;
|
|
515
|
-
}
|
|
516
|
-
function buildTonTx(data) {
|
|
517
|
-
return data;
|
|
518
|
-
}
|
|
519
|
-
function buildAptTx(data) {
|
|
520
|
-
return data;
|
|
521
|
-
}
|
|
522
|
-
function buildExternalTx(currency, tx) {
|
|
523
|
-
switch (currency) {
|
|
524
|
-
case "BTC" /* BTC */:
|
|
525
|
-
return buildPsbt(tx);
|
|
526
|
-
case "ETH" /* ETH */:
|
|
527
|
-
case "BNB" /* BNB */:
|
|
528
|
-
return buildEthTx(tx);
|
|
529
|
-
case "SOL" /* SOL */:
|
|
530
|
-
return buildSolTx(tx);
|
|
531
|
-
case "TRX" /* TRON */:
|
|
532
|
-
return buildTronTx(tx);
|
|
533
|
-
case "TON" /* TON */:
|
|
534
|
-
return buildTonTx(tx);
|
|
535
|
-
case "APT" /* APT */:
|
|
536
|
-
return buildAptTx(tx);
|
|
537
|
-
default:
|
|
538
|
-
throw new Error("Unsupported currency");
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// src/modules/wallets/utils/get-bound-fetch.ts
|
|
543
|
-
var cachedFetch;
|
|
544
|
-
function getBoundFetch() {
|
|
545
|
-
if (!cachedFetch) {
|
|
546
|
-
if (typeof globalThis.fetch !== "function") {
|
|
547
|
-
throw new Error("[Ecency][Wallets] - global fetch is not available");
|
|
548
|
-
}
|
|
549
|
-
cachedFetch = globalThis.fetch.bind(globalThis);
|
|
550
|
-
}
|
|
551
|
-
return cachedFetch;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// src/modules/wallets/queries/use-hive-keys-query.ts
|
|
555
|
-
function useHiveKeysQuery(username) {
|
|
556
|
-
const { data: seed } = useSeedPhrase(username);
|
|
557
|
-
return useQuery({
|
|
558
|
-
queryKey: ["ecenc\u0443-wallets", "hive-keys", username, seed],
|
|
559
|
-
staleTime: Infinity,
|
|
560
|
-
queryFn: async () => {
|
|
561
|
-
if (!seed) {
|
|
562
|
-
throw new Error("[Ecency][Wallets] - no seed to create Hive account");
|
|
563
|
-
}
|
|
564
|
-
const method = await detectHiveKeyDerivation(username, seed).catch(
|
|
565
|
-
() => "bip44"
|
|
566
|
-
);
|
|
567
|
-
const keys = method === "master-password" ? deriveHiveMasterPasswordKeys(username, seed) : deriveHiveKeys(seed);
|
|
568
|
-
return {
|
|
569
|
-
username,
|
|
570
|
-
...keys
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
365
|
function createFallbackTokenMetadata(symbol) {
|
|
576
366
|
return {
|
|
577
367
|
issuer: "",
|
|
@@ -832,269 +622,8 @@ function getTokenOperationsQueryOptions(token, username, isForOwner = false, cur
|
|
|
832
622
|
}
|
|
833
623
|
});
|
|
834
624
|
}
|
|
835
|
-
function useWalletsCacheQuery(username) {
|
|
836
|
-
const queryClient = useQueryClient();
|
|
837
|
-
const queryKey = ["ecency-wallets", "wallets", username];
|
|
838
|
-
const getCachedWallets = () => queryClient.getQueryData(queryKey);
|
|
839
|
-
const createEmptyWalletMap = () => /* @__PURE__ */ new Map();
|
|
840
|
-
return useQuery({
|
|
841
|
-
queryKey,
|
|
842
|
-
enabled: Boolean(username),
|
|
843
|
-
initialData: () => getCachedWallets() ?? createEmptyWalletMap(),
|
|
844
|
-
queryFn: async () => getCachedWallets() ?? createEmptyWalletMap(),
|
|
845
|
-
staleTime: Infinity
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
var PATHS = {
|
|
849
|
-
["BTC" /* BTC */]: "m/44'/0'/0'/0/0",
|
|
850
|
-
// Bitcoin (BIP44)
|
|
851
|
-
["ETH" /* ETH */]: "m/44'/60'/0'/0/0",
|
|
852
|
-
// Ethereum (BIP44)
|
|
853
|
-
["BNB" /* BNB */]: "m/44'/60'/0'/0/0",
|
|
854
|
-
// BNB Smart Chain (BIP44)
|
|
855
|
-
["SOL" /* SOL */]: "m/44'/501'/0'/0'",
|
|
856
|
-
// Solana (BIP44)
|
|
857
|
-
["TON" /* TON */]: "m/44'/607'/0'",
|
|
858
|
-
// TON (BIP44)
|
|
859
|
-
["TRX" /* TRON */]: "m/44'/195'/0'/0/0",
|
|
860
|
-
// Tron (BIP44)
|
|
861
|
-
["APT" /* APT */]: "m/44'/637'/0'/0'/0'"
|
|
862
|
-
// Aptos (BIP44)
|
|
863
|
-
};
|
|
864
|
-
function useWalletCreate(username, currency, importedSeed) {
|
|
865
|
-
const { data: generatedMnemonic } = useSeedPhrase(username);
|
|
866
|
-
const queryClient = useQueryClient();
|
|
867
|
-
const createWallet = useMutation({
|
|
868
|
-
mutationKey: ["ecency-wallets", "create-wallet", username, currency],
|
|
869
|
-
mutationFn: async () => {
|
|
870
|
-
const mnemonic = importedSeed || generatedMnemonic;
|
|
871
|
-
if (!mnemonic) {
|
|
872
|
-
throw new Error("[Ecency][Wallets] - No seed to create a wallet");
|
|
873
|
-
}
|
|
874
|
-
const wallet = getWallet(currency);
|
|
875
|
-
const privateKey = await wallet?.getDerivedPrivateKey({
|
|
876
|
-
mnemonic,
|
|
877
|
-
hdPath: PATHS[currency]
|
|
878
|
-
});
|
|
879
|
-
await delay(1e3);
|
|
880
|
-
const address = await wallet?.getNewAddress({
|
|
881
|
-
privateKey
|
|
882
|
-
});
|
|
883
|
-
return {
|
|
884
|
-
privateKey,
|
|
885
|
-
address: address.address,
|
|
886
|
-
publicKey: address.publicKey,
|
|
887
|
-
username,
|
|
888
|
-
currency
|
|
889
|
-
};
|
|
890
|
-
},
|
|
891
|
-
onSuccess: (info) => {
|
|
892
|
-
queryClient.setQueryData(
|
|
893
|
-
["ecency-wallets", "wallets", info.username],
|
|
894
|
-
(data) => new Map(data ? Array.from(data.entries()) : []).set(
|
|
895
|
-
info.currency,
|
|
896
|
-
info
|
|
897
|
-
)
|
|
898
|
-
);
|
|
899
|
-
}
|
|
900
|
-
});
|
|
901
|
-
const importWallet = () => {
|
|
902
|
-
};
|
|
903
|
-
return {
|
|
904
|
-
createWallet,
|
|
905
|
-
importWallet
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
625
|
|
|
909
|
-
// src/modules/wallets/mutations/
|
|
910
|
-
var private_api_exports = {};
|
|
911
|
-
__export(private_api_exports, {
|
|
912
|
-
useCheckWalletExistence: () => useCheckWalletExistence,
|
|
913
|
-
useCreateAccountWithWallets: () => useCreateAccountWithWallets,
|
|
914
|
-
useUpdateAccountWithWallets: () => useUpdateAccountWithWallets
|
|
915
|
-
});
|
|
916
|
-
function useCreateAccountWithWallets(username) {
|
|
917
|
-
const { data } = useWalletsCacheQuery(username);
|
|
918
|
-
const { data: hiveKeys } = useHiveKeysQuery(username);
|
|
919
|
-
const fetchApi = getBoundFetch();
|
|
920
|
-
return useMutation({
|
|
921
|
-
mutationKey: ["ecency-wallets", "create-account-with-wallets", username],
|
|
922
|
-
mutationFn: ({ currency, address }) => fetchApi(`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
|
|
923
|
-
method: "POST",
|
|
924
|
-
headers: {
|
|
925
|
-
"Content-Type": "application/json"
|
|
926
|
-
},
|
|
927
|
-
body: JSON.stringify({
|
|
928
|
-
username,
|
|
929
|
-
token: currency,
|
|
930
|
-
address,
|
|
931
|
-
meta: {
|
|
932
|
-
ownerPublicKey: hiveKeys?.ownerPubkey,
|
|
933
|
-
activePublicKey: hiveKeys?.activePubkey,
|
|
934
|
-
postingPublicKey: hiveKeys?.postingPubkey,
|
|
935
|
-
memoPublicKey: hiveKeys?.memoPubkey,
|
|
936
|
-
...Array.from(data?.entries() ?? []).reduce(
|
|
937
|
-
(acc, [curr, info]) => ({
|
|
938
|
-
...acc,
|
|
939
|
-
[curr]: info.address
|
|
940
|
-
}),
|
|
941
|
-
{}
|
|
942
|
-
)
|
|
943
|
-
}
|
|
944
|
-
})
|
|
945
|
-
})
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
function useCheckWalletExistence() {
|
|
949
|
-
return useMutation({
|
|
950
|
-
mutationKey: ["ecency-wallets", "check-wallet-existence"],
|
|
951
|
-
mutationFn: async ({ address, currency }) => {
|
|
952
|
-
const response = await fetch(
|
|
953
|
-
`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-exist`,
|
|
954
|
-
{
|
|
955
|
-
method: "POST",
|
|
956
|
-
headers: {
|
|
957
|
-
"Content-Type": "application/json"
|
|
958
|
-
},
|
|
959
|
-
body: JSON.stringify({
|
|
960
|
-
address,
|
|
961
|
-
token: currency
|
|
962
|
-
})
|
|
963
|
-
}
|
|
964
|
-
);
|
|
965
|
-
const data = await response.json();
|
|
966
|
-
return data.length === 0;
|
|
967
|
-
}
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
function useUpdateAccountWithWallets(username, accessToken) {
|
|
971
|
-
const fetchApi = getBoundFetch();
|
|
972
|
-
return useMutation({
|
|
973
|
-
mutationKey: ["ecency-wallets", "update-account-with-wallets", username],
|
|
974
|
-
mutationFn: async ({ tokens, hiveKeys }) => {
|
|
975
|
-
const entries = Object.entries(tokens).filter(([, address]) => Boolean(address));
|
|
976
|
-
if (entries.length === 0) {
|
|
977
|
-
return new Response(null, { status: 204 });
|
|
978
|
-
}
|
|
979
|
-
const [primaryToken, primaryAddress] = entries[0] ?? ["", ""];
|
|
980
|
-
if (!accessToken) {
|
|
981
|
-
throw new Error(
|
|
982
|
-
"[SDK][Wallets][PrivateApi][WalletsAdd] \u2013 access token wasn`t found"
|
|
983
|
-
);
|
|
984
|
-
}
|
|
985
|
-
return fetchApi(`${ConfigManager.getValidatedBaseUrl()}/private-api/wallets-add`, {
|
|
986
|
-
method: "POST",
|
|
987
|
-
headers: {
|
|
988
|
-
"Content-Type": "application/json"
|
|
989
|
-
},
|
|
990
|
-
body: JSON.stringify({
|
|
991
|
-
username,
|
|
992
|
-
code: accessToken,
|
|
993
|
-
token: primaryToken,
|
|
994
|
-
address: primaryAddress,
|
|
995
|
-
status: 3,
|
|
996
|
-
meta: {
|
|
997
|
-
...Object.fromEntries(entries),
|
|
998
|
-
ownerPublicKey: hiveKeys.ownerPublicKey,
|
|
999
|
-
activePublicKey: hiveKeys.activePublicKey,
|
|
1000
|
-
postingPublicKey: hiveKeys.postingPublicKey,
|
|
1001
|
-
memoPublicKey: hiveKeys.memoPublicKey
|
|
1002
|
-
}
|
|
1003
|
-
})
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
// src/modules/wallets/functions/get-keys-from-seed.ts
|
|
1010
|
-
var HD_PATHS = {
|
|
1011
|
-
["BTC" /* BTC */]: ["m/84'/0'/0'/0/0"],
|
|
1012
|
-
["ETH" /* ETH */]: ["m/84'/60'/0'/0/0"],
|
|
1013
|
-
// its not working for Trust, Exodus, todo: check others below
|
|
1014
|
-
["BNB" /* BNB */]: ["m/84'/60'/0'/0/0"],
|
|
1015
|
-
["SOL" /* SOL */]: ["m/84'/501'/0'/0/0"],
|
|
1016
|
-
["TRX" /* TRON */]: ["m/44'/195'/0'/0'/0'"],
|
|
1017
|
-
["APT" /* APT */]: ["m/84'/637'/0'/0/0"],
|
|
1018
|
-
["TON" /* TON */]: ["m/44'/607'/0'"]
|
|
1019
|
-
};
|
|
1020
|
-
async function getKeysFromSeed(mnemonic, wallet, currency) {
|
|
1021
|
-
for (const hdPath of HD_PATHS[currency] || []) {
|
|
1022
|
-
try {
|
|
1023
|
-
const derivedPrivateKey = await wallet.getDerivedPrivateKey({
|
|
1024
|
-
mnemonic,
|
|
1025
|
-
hdPath
|
|
1026
|
-
});
|
|
1027
|
-
const derivedPublicKey = await wallet.getNewAddress({
|
|
1028
|
-
privateKey: derivedPrivateKey,
|
|
1029
|
-
addressType: currency === "BTC" /* BTC */ ? "segwit_native" : void 0
|
|
1030
|
-
});
|
|
1031
|
-
return [derivedPrivateKey.toString(), derivedPublicKey.address];
|
|
1032
|
-
} catch (error) {
|
|
1033
|
-
return [];
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
return [];
|
|
1037
|
-
}
|
|
1038
|
-
function useImportWallet(username, currency) {
|
|
1039
|
-
const queryClient = useQueryClient();
|
|
1040
|
-
const { mutateAsync: checkWalletExistence } = private_api_exports.useCheckWalletExistence();
|
|
1041
|
-
return useMutation({
|
|
1042
|
-
mutationKey: ["ecency-wallets", "import-wallet", username, currency],
|
|
1043
|
-
mutationFn: async ({ privateKeyOrSeed }) => {
|
|
1044
|
-
const wallet = getWallet(currency);
|
|
1045
|
-
if (!wallet) {
|
|
1046
|
-
throw new Error("Cannot find token for this currency");
|
|
1047
|
-
}
|
|
1048
|
-
const isSeed = privateKeyOrSeed.split(" ").length === 12;
|
|
1049
|
-
let address;
|
|
1050
|
-
let privateKey = privateKeyOrSeed;
|
|
1051
|
-
if (isSeed) {
|
|
1052
|
-
[privateKey, address] = await getKeysFromSeed(
|
|
1053
|
-
privateKeyOrSeed,
|
|
1054
|
-
wallet,
|
|
1055
|
-
currency
|
|
1056
|
-
);
|
|
1057
|
-
} else {
|
|
1058
|
-
address = (await wallet.getNewAddress({
|
|
1059
|
-
privateKey: privateKeyOrSeed
|
|
1060
|
-
})).address;
|
|
1061
|
-
}
|
|
1062
|
-
if (!address || !privateKeyOrSeed) {
|
|
1063
|
-
throw new Error(
|
|
1064
|
-
"Private key/seed phrase isn't matching with public key or token"
|
|
1065
|
-
);
|
|
1066
|
-
}
|
|
1067
|
-
const hasChecked = await checkWalletExistence({
|
|
1068
|
-
address,
|
|
1069
|
-
currency
|
|
1070
|
-
});
|
|
1071
|
-
if (!hasChecked) {
|
|
1072
|
-
throw new Error(
|
|
1073
|
-
"This wallet has already in use by Hive account. Please, try another one"
|
|
1074
|
-
);
|
|
1075
|
-
}
|
|
1076
|
-
return {
|
|
1077
|
-
privateKey,
|
|
1078
|
-
address,
|
|
1079
|
-
publicKey: ""
|
|
1080
|
-
};
|
|
1081
|
-
},
|
|
1082
|
-
onSuccess: ({ privateKey, publicKey, address }) => {
|
|
1083
|
-
queryClient.setQueryData(
|
|
1084
|
-
["ecency-wallets", "wallets", username],
|
|
1085
|
-
(data) => new Map(data ? Array.from(data.entries()) : []).set(currency, {
|
|
1086
|
-
privateKey,
|
|
1087
|
-
publicKey,
|
|
1088
|
-
address,
|
|
1089
|
-
username,
|
|
1090
|
-
currency,
|
|
1091
|
-
type: "CHAIN",
|
|
1092
|
-
custom: true
|
|
1093
|
-
})
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
626
|
+
// src/modules/wallets/mutations/save-wallet-information-to-metadata.ts
|
|
1098
627
|
function getGroupedChainTokens(tokens, defaultShow) {
|
|
1099
628
|
if (!tokens) {
|
|
1100
629
|
return {};
|
|
@@ -1171,9 +700,413 @@ function useSaveWalletInformationToMetadata(username, auth, options2) {
|
|
|
1171
700
|
});
|
|
1172
701
|
}
|
|
1173
702
|
|
|
703
|
+
// src/modules/wallets/utils/metamask-evm-transfer.ts
|
|
704
|
+
function getEthereum() {
|
|
705
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
706
|
+
throw new Error("MetaMask not found");
|
|
707
|
+
}
|
|
708
|
+
return window.ethereum;
|
|
709
|
+
}
|
|
710
|
+
var WEI_PER_ETH = 1000000000000000000n;
|
|
711
|
+
var EVM_CHAIN_CONFIG = {
|
|
712
|
+
["ETH" /* ETH */]: {
|
|
713
|
+
chainId: "0x1",
|
|
714
|
+
name: "Ethereum Mainnet",
|
|
715
|
+
rpcUrl: "https://rpc.ankr.com/eth",
|
|
716
|
+
explorerUrl: "https://etherscan.io/tx/"
|
|
717
|
+
},
|
|
718
|
+
["BNB" /* BNB */]: {
|
|
719
|
+
chainId: "0x38",
|
|
720
|
+
name: "BNB Smart Chain",
|
|
721
|
+
rpcUrl: "https://bsc-dataseed.binance.org",
|
|
722
|
+
explorerUrl: "https://bscscan.com/tx/"
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
function getEvmChainConfig(currency) {
|
|
726
|
+
const config = EVM_CHAIN_CONFIG[currency];
|
|
727
|
+
if (!config) throw new Error(`Unsupported EVM currency: ${currency}`);
|
|
728
|
+
return config;
|
|
729
|
+
}
|
|
730
|
+
function getEvmExplorerUrl(currency, txHash) {
|
|
731
|
+
return `${getEvmChainConfig(currency).explorerUrl}${txHash}`;
|
|
732
|
+
}
|
|
733
|
+
async function ensureEvmChain(currency) {
|
|
734
|
+
const ethereum = getEthereum();
|
|
735
|
+
const { chainId, name, rpcUrl } = getEvmChainConfig(currency);
|
|
736
|
+
const currentChainId = await ethereum.request({ method: "eth_chainId" });
|
|
737
|
+
if (currentChainId === chainId) return;
|
|
738
|
+
try {
|
|
739
|
+
await ethereum.request({
|
|
740
|
+
method: "wallet_switchEthereumChain",
|
|
741
|
+
params: [{ chainId }]
|
|
742
|
+
});
|
|
743
|
+
} catch (err) {
|
|
744
|
+
if (typeof err === "object" && err !== null && "code" in err && err.code === 4902) {
|
|
745
|
+
await ethereum.request({
|
|
746
|
+
method: "wallet_addEthereumChain",
|
|
747
|
+
params: [{
|
|
748
|
+
chainId,
|
|
749
|
+
chainName: name,
|
|
750
|
+
rpcUrls: [rpcUrl],
|
|
751
|
+
nativeCurrency: {
|
|
752
|
+
name: currency === "ETH" /* ETH */ ? "Ether" : "BNB",
|
|
753
|
+
symbol: currency === "ETH" /* ETH */ ? "ETH" : "BNB",
|
|
754
|
+
decimals: 18
|
|
755
|
+
}
|
|
756
|
+
}]
|
|
757
|
+
});
|
|
758
|
+
} else {
|
|
759
|
+
throw err;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
async function estimateEvmGas(from, to, valueHex, currency) {
|
|
764
|
+
const ethereum = getEthereum();
|
|
765
|
+
await ensureEvmChain(currency);
|
|
766
|
+
const [gasLimit, gasPrice] = await Promise.all([
|
|
767
|
+
ethereum.request({
|
|
768
|
+
method: "eth_estimateGas",
|
|
769
|
+
params: [{ from, to, value: valueHex }]
|
|
770
|
+
}),
|
|
771
|
+
ethereum.request({ method: "eth_gasPrice" })
|
|
772
|
+
]);
|
|
773
|
+
const estimatedFeeWei = BigInt(gasLimit) * BigInt(gasPrice);
|
|
774
|
+
return { gasLimit, gasPrice, estimatedFeeWei };
|
|
775
|
+
}
|
|
776
|
+
function formatWei(wei, decimals = 6) {
|
|
777
|
+
const whole = wei / WEI_PER_ETH;
|
|
778
|
+
const rem = wei % WEI_PER_ETH;
|
|
779
|
+
if (rem === 0n) return whole.toString();
|
|
780
|
+
const scale = 10n ** BigInt(decimals);
|
|
781
|
+
const fractional = rem * scale / WEI_PER_ETH;
|
|
782
|
+
const fracStr = fractional.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
783
|
+
return fracStr ? `${whole}.${fracStr}` : whole.toString();
|
|
784
|
+
}
|
|
785
|
+
var AMOUNT_REGEX = /^\d+(\.\d+)?$/;
|
|
786
|
+
function parseToWei(amount) {
|
|
787
|
+
const trimmed = amount.trim();
|
|
788
|
+
if (!AMOUNT_REGEX.test(trimmed)) {
|
|
789
|
+
throw new Error(`Invalid amount: "${amount}"`);
|
|
790
|
+
}
|
|
791
|
+
const [whole, fraction = ""] = trimmed.split(".");
|
|
792
|
+
if (!/^\d+$/.test(whole) || fraction && !/^\d+$/.test(fraction)) {
|
|
793
|
+
throw new Error(`Invalid amount: "${amount}"`);
|
|
794
|
+
}
|
|
795
|
+
const paddedFraction = fraction.padEnd(18, "0").slice(0, 18);
|
|
796
|
+
const wei = BigInt(whole) * WEI_PER_ETH + BigInt(paddedFraction);
|
|
797
|
+
return "0x" + wei.toString(16);
|
|
798
|
+
}
|
|
799
|
+
async function sendEvmTransfer(to, amountWei, currency) {
|
|
800
|
+
const ethereum = getEthereum();
|
|
801
|
+
await ensureEvmChain(currency);
|
|
802
|
+
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
|
|
803
|
+
const from = accounts[0];
|
|
804
|
+
if (!from) throw new Error("No MetaMask account connected");
|
|
805
|
+
const txHash = await ethereum.request({
|
|
806
|
+
method: "eth_sendTransaction",
|
|
807
|
+
params: [{
|
|
808
|
+
from,
|
|
809
|
+
to,
|
|
810
|
+
value: amountWei
|
|
811
|
+
}]
|
|
812
|
+
});
|
|
813
|
+
return txHash;
|
|
814
|
+
}
|
|
815
|
+
var SOL_EXPLORER_URL = "https://explorer.solana.com/tx/";
|
|
816
|
+
var LAMPORTS_PER_SOL = 1000000000n;
|
|
817
|
+
var AMOUNT_REGEX2 = /^\d+(\.\d+)?$/;
|
|
818
|
+
function getSolExplorerUrl(signature) {
|
|
819
|
+
return `${SOL_EXPLORER_URL}${signature}`;
|
|
820
|
+
}
|
|
821
|
+
function parseToLamports(amount) {
|
|
822
|
+
const trimmed = amount.trim();
|
|
823
|
+
if (!AMOUNT_REGEX2.test(trimmed)) {
|
|
824
|
+
throw new Error(`Invalid amount: "${amount}"`);
|
|
825
|
+
}
|
|
826
|
+
const [whole, fraction = ""] = trimmed.split(".");
|
|
827
|
+
if (!/^\d+$/.test(whole) || fraction && !/^\d+$/.test(fraction)) {
|
|
828
|
+
throw new Error(`Invalid amount: "${amount}"`);
|
|
829
|
+
}
|
|
830
|
+
if (fraction.length > 9 && fraction.slice(9).replace(/0/g, "").length > 0) {
|
|
831
|
+
throw new Error(`Amount has more than 9 decimal places: "${amount}"`);
|
|
832
|
+
}
|
|
833
|
+
const paddedFraction = fraction.padEnd(9, "0").slice(0, 9);
|
|
834
|
+
return BigInt(whole) * LAMPORTS_PER_SOL + BigInt(paddedFraction);
|
|
835
|
+
}
|
|
836
|
+
function formatLamports(lamports, decimals = 6) {
|
|
837
|
+
const whole = lamports / LAMPORTS_PER_SOL;
|
|
838
|
+
const rem = lamports % LAMPORTS_PER_SOL;
|
|
839
|
+
if (rem === 0n) return whole.toString();
|
|
840
|
+
const scale = 10n ** BigInt(decimals);
|
|
841
|
+
const fractional = rem * scale / LAMPORTS_PER_SOL;
|
|
842
|
+
const fracStr = fractional.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
843
|
+
return fracStr ? `${whole}.${fracStr}` : whole.toString();
|
|
844
|
+
}
|
|
845
|
+
function getSolRpcUrl() {
|
|
846
|
+
if (CONFIG.heliusApiKey) {
|
|
847
|
+
return `https://rpc.helius.xyz/?api-key=${CONFIG.heliusApiKey}`;
|
|
848
|
+
}
|
|
849
|
+
return "https://api.mainnet-beta.solana.com";
|
|
850
|
+
}
|
|
851
|
+
async function getMetaMaskSolanaWallet() {
|
|
852
|
+
const { getWallets } = await import('@wallet-standard/app');
|
|
853
|
+
const walletsApi = getWallets();
|
|
854
|
+
const wallets = walletsApi.get();
|
|
855
|
+
const mmWallet = wallets.find(
|
|
856
|
+
(w) => w.name.toLowerCase().includes("metamask") && w.features["standard:connect"] && w.features["solana:signAndSendTransaction"]
|
|
857
|
+
);
|
|
858
|
+
if (!mmWallet) {
|
|
859
|
+
throw new Error("MetaMask Solana wallet not found. Enable Solana in MetaMask settings.");
|
|
860
|
+
}
|
|
861
|
+
return mmWallet;
|
|
862
|
+
}
|
|
863
|
+
async function sendSolTransfer(to, amountSol) {
|
|
864
|
+
const mmWallet = await getMetaMaskSolanaWallet();
|
|
865
|
+
const connectFeature = mmWallet.features["standard:connect"];
|
|
866
|
+
await connectFeature.connect();
|
|
867
|
+
const solAccount = mmWallet.accounts?.find(
|
|
868
|
+
(acc) => acc.chains?.some((c) => c.startsWith("solana:"))
|
|
869
|
+
);
|
|
870
|
+
if (!solAccount) {
|
|
871
|
+
throw new Error("No Solana account found in MetaMask.");
|
|
872
|
+
}
|
|
873
|
+
const { Connection, PublicKey, SystemProgram, Transaction } = await import('@solana/web3.js');
|
|
874
|
+
const connection = new Connection(getSolRpcUrl(), "confirmed");
|
|
875
|
+
const fromPubkey = new PublicKey(solAccount.address);
|
|
876
|
+
const toPubkey = new PublicKey(to);
|
|
877
|
+
const lamports = parseToLamports(amountSol);
|
|
878
|
+
const transaction = new Transaction().add(
|
|
879
|
+
SystemProgram.transfer({
|
|
880
|
+
fromPubkey,
|
|
881
|
+
toPubkey,
|
|
882
|
+
lamports
|
|
883
|
+
})
|
|
884
|
+
);
|
|
885
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
886
|
+
transaction.recentBlockhash = blockhash;
|
|
887
|
+
transaction.feePayer = fromPubkey;
|
|
888
|
+
const serializedTx = transaction.serialize({
|
|
889
|
+
requireAllSignatures: false,
|
|
890
|
+
verifySignatures: false
|
|
891
|
+
});
|
|
892
|
+
const signAndSendFeature = mmWallet.features["solana:signAndSendTransaction"];
|
|
893
|
+
if (!signAndSendFeature) {
|
|
894
|
+
throw new Error("MetaMask does not support Solana transaction signing. Please update MetaMask.");
|
|
895
|
+
}
|
|
896
|
+
const [result] = await signAndSendFeature.signAndSendTransaction({
|
|
897
|
+
account: solAccount,
|
|
898
|
+
transaction: serializedTx,
|
|
899
|
+
chain: "solana:mainnet"
|
|
900
|
+
});
|
|
901
|
+
if (typeof result.signature === "string") {
|
|
902
|
+
return result.signature;
|
|
903
|
+
}
|
|
904
|
+
const { base58 } = await import('@scure/base');
|
|
905
|
+
return base58.encode(new Uint8Array(result.signature));
|
|
906
|
+
}
|
|
907
|
+
function useExternalTransfer(currency) {
|
|
908
|
+
const queryClient = useQueryClient();
|
|
909
|
+
return useMutation({
|
|
910
|
+
mutationKey: ["ecency-wallets", "external-transfer", currency],
|
|
911
|
+
mutationFn: async ({ to, amount }) => {
|
|
912
|
+
switch (currency) {
|
|
913
|
+
case "ETH" /* ETH */:
|
|
914
|
+
case "BNB" /* BNB */: {
|
|
915
|
+
const valueHex = parseToWei(amount);
|
|
916
|
+
const txHash = await sendEvmTransfer(to, valueHex, currency);
|
|
917
|
+
return { txHash, currency };
|
|
918
|
+
}
|
|
919
|
+
case "SOL" /* SOL */: {
|
|
920
|
+
const signature = await sendSolTransfer(to, amount);
|
|
921
|
+
return { txHash: signature, currency };
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
onSuccess: () => {
|
|
926
|
+
queryClient.invalidateQueries({
|
|
927
|
+
queryKey: ["ecency-wallets", "external-wallet-balance"]
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
var ROLE_INDEX = {
|
|
933
|
+
owner: 0,
|
|
934
|
+
active: 1,
|
|
935
|
+
posting: 2,
|
|
936
|
+
memo: 3
|
|
937
|
+
};
|
|
938
|
+
function deriveHiveKey(mnemonic, role, accountIndex = 0) {
|
|
939
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
940
|
+
const master = HDKey.fromMasterSeed(seed);
|
|
941
|
+
const path = `m/44'/3054'/${accountIndex}'/0'/${ROLE_INDEX[role]}'`;
|
|
942
|
+
const child = master.derive(path);
|
|
943
|
+
if (!child.privateKey) {
|
|
944
|
+
throw new Error("[Ecency][Wallets] - hive key derivation failed");
|
|
945
|
+
}
|
|
946
|
+
const pk = PrivateKey.from(Buffer.from(child.privateKey));
|
|
947
|
+
return {
|
|
948
|
+
privateKey: pk.toString(),
|
|
949
|
+
publicKey: pk.createPublic().toString()
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
function deriveHiveKeys(mnemonic, accountIndex = 0) {
|
|
953
|
+
const owner = deriveHiveKey(mnemonic, "owner", accountIndex);
|
|
954
|
+
const active = deriveHiveKey(mnemonic, "active", accountIndex);
|
|
955
|
+
const posting = deriveHiveKey(mnemonic, "posting", accountIndex);
|
|
956
|
+
const memo = deriveHiveKey(mnemonic, "memo", accountIndex);
|
|
957
|
+
return {
|
|
958
|
+
owner: owner.privateKey,
|
|
959
|
+
active: active.privateKey,
|
|
960
|
+
posting: posting.privateKey,
|
|
961
|
+
memo: memo.privateKey,
|
|
962
|
+
ownerPubkey: owner.publicKey,
|
|
963
|
+
activePubkey: active.publicKey,
|
|
964
|
+
postingPubkey: posting.publicKey,
|
|
965
|
+
memoPubkey: memo.publicKey
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function deriveHiveMasterPasswordKey(username, masterPassword, role) {
|
|
969
|
+
const pk = PrivateKey.fromLogin(username, masterPassword, role);
|
|
970
|
+
return {
|
|
971
|
+
privateKey: pk.toString(),
|
|
972
|
+
publicKey: pk.createPublic().toString()
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function deriveHiveMasterPasswordKeys(username, masterPassword) {
|
|
976
|
+
const owner = deriveHiveMasterPasswordKey(username, masterPassword, "owner");
|
|
977
|
+
const active = deriveHiveMasterPasswordKey(username, masterPassword, "active");
|
|
978
|
+
const posting = deriveHiveMasterPasswordKey(
|
|
979
|
+
username,
|
|
980
|
+
masterPassword,
|
|
981
|
+
"posting"
|
|
982
|
+
);
|
|
983
|
+
const memo = deriveHiveMasterPasswordKey(username, masterPassword, "memo");
|
|
984
|
+
return {
|
|
985
|
+
owner: owner.privateKey,
|
|
986
|
+
active: active.privateKey,
|
|
987
|
+
posting: posting.privateKey,
|
|
988
|
+
memo: memo.privateKey,
|
|
989
|
+
ownerPubkey: owner.publicKey,
|
|
990
|
+
activePubkey: active.publicKey,
|
|
991
|
+
postingPubkey: posting.publicKey,
|
|
992
|
+
memoPubkey: memo.publicKey
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
async function detectHiveKeyDerivation(username, seed, type = "active") {
|
|
996
|
+
const uname = username.trim().toLowerCase();
|
|
997
|
+
const account = await CONFIG.queryClient.fetchQuery(
|
|
998
|
+
getAccountFullQueryOptions(uname)
|
|
999
|
+
);
|
|
1000
|
+
const auth = account[type];
|
|
1001
|
+
const bip44 = deriveHiveKeys(seed);
|
|
1002
|
+
const bip44Pub = type === "owner" ? bip44.ownerPubkey : bip44.activePubkey;
|
|
1003
|
+
const matchBip44 = auth.key_auths.some(([pub]) => String(pub) === bip44Pub);
|
|
1004
|
+
if (matchBip44) return "bip44";
|
|
1005
|
+
const legacyPub = PrivateKey.fromLogin(uname, seed, type).createPublic().toString();
|
|
1006
|
+
const matchLegacy = auth.key_auths.some(([pub]) => String(pub) === legacyPub);
|
|
1007
|
+
if (matchLegacy) return "master-password";
|
|
1008
|
+
return "unknown";
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/modules/wallets/utils/metamask-discovery.ts
|
|
1012
|
+
var CHAIN_PREFIX_MAP = {
|
|
1013
|
+
"solana:": "SOL" /* SOL */,
|
|
1014
|
+
"bip122:": "BTC" /* BTC */
|
|
1015
|
+
};
|
|
1016
|
+
var HIVE_SNAP_ID = "npm:@hiveio/metamask-snap";
|
|
1017
|
+
async function fetchMultichainAddresses() {
|
|
1018
|
+
const addresses = {};
|
|
1019
|
+
try {
|
|
1020
|
+
const { getWallets } = await import('@wallet-standard/app');
|
|
1021
|
+
const walletsApi = getWallets();
|
|
1022
|
+
const wallets = walletsApi.get();
|
|
1023
|
+
const mmWallets = wallets.filter(
|
|
1024
|
+
(w) => w.name.toLowerCase().includes("metamask") && w.features["standard:connect"]
|
|
1025
|
+
);
|
|
1026
|
+
for (const mmWallet of mmWallets) {
|
|
1027
|
+
try {
|
|
1028
|
+
const connectFeature = mmWallet.features["standard:connect"];
|
|
1029
|
+
await connectFeature.connect();
|
|
1030
|
+
} catch (connectErr) {
|
|
1031
|
+
if (false) ;
|
|
1032
|
+
continue;
|
|
1033
|
+
}
|
|
1034
|
+
for (const account of mmWallet.accounts ?? []) {
|
|
1035
|
+
if (!account.address || !Array.isArray(account.chains)) continue;
|
|
1036
|
+
for (const [prefix, currency] of Object.entries(CHAIN_PREFIX_MAP)) {
|
|
1037
|
+
if (addresses[currency]) continue;
|
|
1038
|
+
if (account.chains.some((c) => c.startsWith(prefix))) {
|
|
1039
|
+
addresses[currency] = account.address;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
} catch (e) {
|
|
1045
|
+
}
|
|
1046
|
+
return addresses;
|
|
1047
|
+
}
|
|
1048
|
+
async function fetchEvmAddress() {
|
|
1049
|
+
if (typeof window === "undefined" || !window.ethereum?.isMetaMask) return void 0;
|
|
1050
|
+
try {
|
|
1051
|
+
const accounts = await window.ethereum.request({
|
|
1052
|
+
method: "eth_requestAccounts"
|
|
1053
|
+
});
|
|
1054
|
+
return accounts?.[0] ?? void 0;
|
|
1055
|
+
} catch {
|
|
1056
|
+
return void 0;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
async function discoverMetaMaskWallets() {
|
|
1060
|
+
const addresses = {};
|
|
1061
|
+
const evmAddress = await fetchEvmAddress();
|
|
1062
|
+
if (evmAddress) {
|
|
1063
|
+
addresses["ETH" /* ETH */] = evmAddress;
|
|
1064
|
+
addresses["BNB" /* BNB */] = evmAddress;
|
|
1065
|
+
}
|
|
1066
|
+
const multichainAddresses = await fetchMultichainAddresses();
|
|
1067
|
+
Object.assign(addresses, multichainAddresses);
|
|
1068
|
+
return addresses;
|
|
1069
|
+
}
|
|
1070
|
+
async function installHiveSnap() {
|
|
1071
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
1072
|
+
throw new Error("MetaMask is not available");
|
|
1073
|
+
}
|
|
1074
|
+
await window.ethereum.request({
|
|
1075
|
+
method: "wallet_requestSnaps",
|
|
1076
|
+
params: { [HIVE_SNAP_ID]: {} }
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
async function getHivePublicKeys() {
|
|
1080
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
1081
|
+
throw new Error("MetaMask is not available");
|
|
1082
|
+
}
|
|
1083
|
+
const result = await window.ethereum.request({
|
|
1084
|
+
method: "wallet_invokeSnap",
|
|
1085
|
+
params: {
|
|
1086
|
+
snapId: HIVE_SNAP_ID,
|
|
1087
|
+
request: {
|
|
1088
|
+
method: "hive_getPublicKeys",
|
|
1089
|
+
params: {
|
|
1090
|
+
keys: [
|
|
1091
|
+
{ role: "owner", accountIndex: 0 },
|
|
1092
|
+
{ role: "active", accountIndex: 0 },
|
|
1093
|
+
{ role: "posting", accountIndex: 0 },
|
|
1094
|
+
{ role: "memo", accountIndex: 0 }
|
|
1095
|
+
]
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
const keys = result?.publicKeys;
|
|
1101
|
+
if (!Array.isArray(keys)) {
|
|
1102
|
+
throw new Error("Hive Snap returned invalid response \u2014 expected publicKeys array");
|
|
1103
|
+
}
|
|
1104
|
+
return keys;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1174
1107
|
// src/index.ts
|
|
1175
1108
|
rememberScryptBsvVersion();
|
|
1176
1109
|
|
|
1177
|
-
export { EcencyWalletBasicTokens, EcencyWalletCurrency, private_api_exports as EcencyWalletsPrivateApi,
|
|
1110
|
+
export { EcencyWalletBasicTokens, EcencyWalletCurrency, private_api_exports as EcencyWalletsPrivateApi, deriveHiveKey, deriveHiveKeys, deriveHiveMasterPasswordKey, deriveHiveMasterPasswordKeys, detectHiveKeyDerivation, discoverMetaMaskWallets, ensureEvmChain, estimateEvmGas, fetchEvmAddress, fetchMultichainAddresses, formatLamports, formatWei, getAccountWalletListQueryOptions, getAllTokensListQueryOptions, getEvmChainConfig, getEvmExplorerUrl, getHivePublicKeys, getSolExplorerUrl, getTokenOperationsQueryOptions, getTokenPriceQueryOptions, installHiveSnap, parseToLamports, parseToWei, sendEvmTransfer, sendSolTransfer, useExternalTransfer, useGetExternalWalletBalanceQuery, useSaveWalletInformationToMetadata };
|
|
1178
1111
|
//# sourceMappingURL=index.js.map
|
|
1179
1112
|
//# sourceMappingURL=index.js.map
|