chroid 1.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/README.md +2 -0
- package/cli/bitcoin.js +207 -0
- package/cli/evm.js +214 -0
- package/cli/tron.js +91 -0
- package/index.js +17 -0
- package/package.json +30 -0
- package/utils/askForPassword.js +23 -0
- package/utils/bitcoin.js +746 -0
- package/utils/const.js +8 -0
- package/utils/evm.js +425 -0
- package/utils/tron.js +163 -0
package/utils/const.js
ADDED
package/utils/evm.js
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
const bip39 = require('bip39');
|
|
2
|
+
const hdkey = require('hdkey');
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const ethers = require('ethers')
|
|
5
|
+
const networks = {
|
|
6
|
+
ETH: {
|
|
7
|
+
chainId: 1,
|
|
8
|
+
rpcUrl: "https://ethereum-rpc.publicnode.com",
|
|
9
|
+
explorerUrl: "https://etherscan.io",
|
|
10
|
+
symbol: "ETH",
|
|
11
|
+
name: "Ethereum Mainnet",
|
|
12
|
+
USDT_CONTRACT_ADDRESS: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
13
|
+
USDC_CONTRACT_ADDRESS: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
14
|
+
},
|
|
15
|
+
BSC: {
|
|
16
|
+
chainId: 56,
|
|
17
|
+
rpcUrl: "https://bsc-dataseed.binance.org",
|
|
18
|
+
explorerUrl: "https://bscscan.com",
|
|
19
|
+
symbol: "BNB",
|
|
20
|
+
name: "Binance Smart Chain",
|
|
21
|
+
USDT_CONTRACT_ADDRESS: "0x55d398326f99059fF775485246999027B3197955",
|
|
22
|
+
USDC_CONTRACT_ADDRESS: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
23
|
+
},
|
|
24
|
+
OP: {
|
|
25
|
+
chainId: 10,
|
|
26
|
+
rpcUrl: "https://optimism-rpc.publicnode.com",
|
|
27
|
+
explorerUrl: "https://optimistic.etherscan.io",
|
|
28
|
+
symbol: "ETH",
|
|
29
|
+
name: "Optimism Mainnet",
|
|
30
|
+
USDT_CONTRACT_ADDRESS: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
|
|
31
|
+
USDC_CONTRACT_ADDRESS: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
32
|
+
OP_CONTRACT_ADDRESS: "0x4200000000000000000000000000000000000042",
|
|
33
|
+
},
|
|
34
|
+
AVA: {
|
|
35
|
+
chainId: 43114,
|
|
36
|
+
rpcUrl: "https://avalanche-c-chain-rpc.publicnode.com",
|
|
37
|
+
explorerUrl: "https://snowtrace.io",
|
|
38
|
+
symbol: "AVAX",
|
|
39
|
+
name: "Avalanche C-Chain",
|
|
40
|
+
USDT_CONTRACT_ADDRESS: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
|
|
41
|
+
USDC_CONTRACT_ADDRESS: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
42
|
+
},
|
|
43
|
+
POL: {
|
|
44
|
+
chainId: 137,
|
|
45
|
+
rpcUrl: "https://polygon-rpc.com",
|
|
46
|
+
explorerUrl: "https://polygonscan.com",
|
|
47
|
+
symbol: "MATIC",
|
|
48
|
+
name: "Polygon Mainnet",
|
|
49
|
+
USDT_CONTRACT_ADDRESS: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
50
|
+
USDC_CONTRACT_ADDRESS: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
51
|
+
},
|
|
52
|
+
ARB: {
|
|
53
|
+
chainId: 42161,
|
|
54
|
+
rpcUrl: "https://arbitrum-one-rpc.publicnode.com",
|
|
55
|
+
explorerUrl: "https://arbiscan.io",
|
|
56
|
+
symbol: "ETH",
|
|
57
|
+
name: "Arbitrum One",
|
|
58
|
+
USDT_CONTRACT_ADDRESS: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
59
|
+
USDC_CONTRACT_ADDRESS: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
60
|
+
},
|
|
61
|
+
BASE: {
|
|
62
|
+
chainId: 8453,
|
|
63
|
+
rpcUrl: "https://mainnet.base.org",
|
|
64
|
+
explorerUrl: "https://basescan.org",
|
|
65
|
+
symbol: "ETH",
|
|
66
|
+
name: "Base Mainnet",
|
|
67
|
+
USDT_CONTRACT_ADDRESS: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
68
|
+
USDC_CONTRACT_ADDRESS: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function generateHash(input) {
|
|
73
|
+
return crypto.createHash('sha256') // Use SHA-256 algorithm
|
|
74
|
+
.update(input) // Hash the input string
|
|
75
|
+
.digest('hex'); // Output the hash in hex format
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function generateMnemonicFromPassword (pwd) {
|
|
79
|
+
const hash = generateHash(pwd)
|
|
80
|
+
const mnemonic = bip39.entropyToMnemonic(hash)
|
|
81
|
+
if (!bip39.validateMnemonic(mnemonic)) {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
return mnemonic
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function generatePrivateKeyHexFromMnemonic(seedPhrase) {
|
|
88
|
+
|
|
89
|
+
const derivationPath = "m/88'/1'/9'/9/8"
|
|
90
|
+
const seed = await bip39.mnemonicToSeed(seedPhrase);
|
|
91
|
+
const hdwallet = hdkey.fromMasterSeed(seed);
|
|
92
|
+
const wallet = hdwallet.derive(derivationPath);
|
|
93
|
+
|
|
94
|
+
const privateKey = wallet.privateKey;
|
|
95
|
+
|
|
96
|
+
return Buffer.from(privateKey, "binary").toString("hex")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function generateWalletFromPassword (pwd) {
|
|
100
|
+
const { Wallet } = ethers
|
|
101
|
+
const mnemonic = generateMnemonicFromPassword(pwd)
|
|
102
|
+
const privateKeyHex = await generatePrivateKeyHexFromMnemonic(mnemonic)
|
|
103
|
+
const account = new Wallet(privateKeyHex);
|
|
104
|
+
return {
|
|
105
|
+
privateKeyHex,
|
|
106
|
+
address: account.address
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function getCustomBalanceFromAddress(address, tokenAddress, network) {
|
|
111
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
112
|
+
if (!networkConfig) {
|
|
113
|
+
throw new Error(`Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
118
|
+
|
|
119
|
+
// Check native balance
|
|
120
|
+
const nativeBalance = await provider.getBalance(address);
|
|
121
|
+
|
|
122
|
+
// Check token balance
|
|
123
|
+
const tokenContract = new ethers.Contract(
|
|
124
|
+
tokenAddress,
|
|
125
|
+
['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)'],
|
|
126
|
+
provider
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const [tokenBalance, decimals] = await Promise.all([
|
|
130
|
+
tokenContract.balanceOf(address),
|
|
131
|
+
tokenContract.decimals()
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
native_balance: ethers.formatEther(nativeBalance),
|
|
136
|
+
token_balance: ethers.formatUnits(tokenBalance, decimals)
|
|
137
|
+
};
|
|
138
|
+
} catch (error) {
|
|
139
|
+
throw new Error(`Error checking balances: ${error.message}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function getBalanceFromAddress(address, network) {
|
|
144
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
145
|
+
if (!networkConfig) {
|
|
146
|
+
throw new Error(`Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
151
|
+
|
|
152
|
+
// Check native balance
|
|
153
|
+
const nativeBalance = await provider.getBalance(address);
|
|
154
|
+
|
|
155
|
+
// Check USDT balance
|
|
156
|
+
const usdtContract = new ethers.Contract(
|
|
157
|
+
networkConfig.USDT_CONTRACT_ADDRESS,
|
|
158
|
+
['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)'],
|
|
159
|
+
provider
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Check USDT balance
|
|
163
|
+
const usdcContract = new ethers.Contract(
|
|
164
|
+
networkConfig.USDC_CONTRACT_ADDRESS,
|
|
165
|
+
['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)'],
|
|
166
|
+
provider
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const [usdtBalance, usdtDecimals, usdcBalance, usdcDecimals] = await Promise.all([
|
|
170
|
+
usdtContract.balanceOf(address),
|
|
171
|
+
usdtContract.decimals(),
|
|
172
|
+
usdcContract.balanceOf(address),
|
|
173
|
+
usdcContract.decimals()
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
native_balance: ethers.formatEther(nativeBalance),
|
|
178
|
+
usdt_balance: ethers.formatUnits(usdtBalance, usdtDecimals),
|
|
179
|
+
usdc_balance: ethers.formatUnits(usdcBalance, usdcDecimals)
|
|
180
|
+
};
|
|
181
|
+
} catch (error) {
|
|
182
|
+
throw new Error(`Error checking balances: ${error.message}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function transferNative({ address, privateKeyHex }, destination, amount, network) {
|
|
187
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
188
|
+
if (!networkConfig) {
|
|
189
|
+
return {
|
|
190
|
+
success: false,
|
|
191
|
+
error: `Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
197
|
+
const wallet = new ethers.Wallet(privateKeyHex, provider);
|
|
198
|
+
|
|
199
|
+
// Check if we have enough balance
|
|
200
|
+
const balance = await provider.getBalance(address);
|
|
201
|
+
const amountWei = ethers.parseEther(amount);
|
|
202
|
+
|
|
203
|
+
if (balance < amountWei) {
|
|
204
|
+
return {
|
|
205
|
+
success: false,
|
|
206
|
+
error: `Insufficient ${networkConfig.symbol} balance. You have ${ethers.formatEther(balance)} but trying to send ${amount}`
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Get gas price and estimate gas
|
|
211
|
+
const gasPrice = await provider.getFeeData();
|
|
212
|
+
const gasLimit = await provider.estimateGas({
|
|
213
|
+
from: address,
|
|
214
|
+
to: destination,
|
|
215
|
+
value: amountWei
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Create and send transaction
|
|
219
|
+
const tx = await wallet.sendTransaction({
|
|
220
|
+
to: destination,
|
|
221
|
+
value: amountWei,
|
|
222
|
+
gasLimit: gasLimit,
|
|
223
|
+
maxFeePerGas: gasPrice.maxFeePerGas,
|
|
224
|
+
maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const receipt = await tx.wait();
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
success: true,
|
|
231
|
+
txUrl: `${networkConfig.explorerUrl}/tx/${receipt.hash}`
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
} catch (error) {
|
|
235
|
+
return {
|
|
236
|
+
success: false,
|
|
237
|
+
error: error.message
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function transferUSDT({ address, privateKeyHex }, destination, amount, network) {
|
|
243
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
244
|
+
if (!networkConfig) {
|
|
245
|
+
return {
|
|
246
|
+
success: false,
|
|
247
|
+
error: `Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
253
|
+
const wallet = new ethers.Wallet(privateKeyHex, provider);
|
|
254
|
+
|
|
255
|
+
// USDT contract interface - only including functions we need
|
|
256
|
+
const usdtAbi = [
|
|
257
|
+
'function balanceOf(address) view returns (uint256)',
|
|
258
|
+
'function decimals() view returns (uint8)',
|
|
259
|
+
'function transfer(address, uint256) returns (bool)'
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
const usdtContract = new ethers.Contract(
|
|
263
|
+
networkConfig.USDT_CONTRACT_ADDRESS,
|
|
264
|
+
usdtAbi,
|
|
265
|
+
wallet // Use wallet as signer
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// Get USDT decimals
|
|
269
|
+
const decimals = await usdtContract.decimals();
|
|
270
|
+
|
|
271
|
+
// Convert amount to USDT units
|
|
272
|
+
const amountInUnits = ethers.parseUnits(amount, decimals);
|
|
273
|
+
|
|
274
|
+
// Check USDT balance
|
|
275
|
+
const balance = await usdtContract.balanceOf(address);
|
|
276
|
+
if (balance < amountInUnits) {
|
|
277
|
+
return {
|
|
278
|
+
success: false,
|
|
279
|
+
error: `Insufficient USDT balance. You are trying to send ${amount}`
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Send USDT
|
|
284
|
+
const tx = await usdtContract.transfer(destination, amountInUnits);
|
|
285
|
+
const receipt = await tx.wait();
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
success: true,
|
|
289
|
+
txUrl: `${networkConfig.explorerUrl}/tx/${receipt.hash}`
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
error: error.message
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async function transferUSDC({ address, privateKeyHex }, destination, amount, network) {
|
|
301
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
302
|
+
if (!networkConfig) {
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
error: `Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
311
|
+
const wallet = new ethers.Wallet(privateKeyHex, provider);
|
|
312
|
+
|
|
313
|
+
// USDC contract interface - only including functions we need
|
|
314
|
+
const usdcAbi = [
|
|
315
|
+
'function balanceOf(address) view returns (uint256)',
|
|
316
|
+
'function decimals() view returns (uint8)',
|
|
317
|
+
'function transfer(address, uint256) returns (bool)'
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
const usdcContract = new ethers.Contract(
|
|
321
|
+
networkConfig.USDC_CONTRACT_ADDRESS,
|
|
322
|
+
usdcAbi,
|
|
323
|
+
wallet // Use wallet as signer
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// Get USDC decimals
|
|
327
|
+
const decimals = await usdtContract.decimals();
|
|
328
|
+
|
|
329
|
+
// Convert amount to USDC units
|
|
330
|
+
const amountInUnits = ethers.parseUnits(amount, decimals);
|
|
331
|
+
|
|
332
|
+
// Check USDC balance
|
|
333
|
+
const balance = await usdcContract.balanceOf(address);
|
|
334
|
+
if (balance < amountInUnits) {
|
|
335
|
+
return {
|
|
336
|
+
success: false,
|
|
337
|
+
error: `Insufficient USDC balance. You are trying to send ${amount}`
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Send USDC
|
|
342
|
+
const tx = await usdcContract.transfer(destination, amountInUnits);
|
|
343
|
+
const receipt = await tx.wait();
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
success: true,
|
|
347
|
+
txUrl: `${networkConfig.explorerUrl}/tx/${receipt.hash}`
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
} catch (error) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: error.message
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async function transferCustomToken({ address, privateKeyHex }, destination, tokenAddress, amount, network) {
|
|
359
|
+
const networkConfig = networks[network.toUpperCase()];
|
|
360
|
+
if (!networkConfig) {
|
|
361
|
+
return {
|
|
362
|
+
success: false,
|
|
363
|
+
error: `Network ${network} not found. Available networks: ${Object.keys(networks).join(", ")}`
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
369
|
+
const wallet = new ethers.Wallet(privateKeyHex, provider);
|
|
370
|
+
|
|
371
|
+
// USDT contract interface - only including functions we need
|
|
372
|
+
const tokenAbi = [
|
|
373
|
+
'function balanceOf(address) view returns (uint256)',
|
|
374
|
+
'function decimals() view returns (uint8)',
|
|
375
|
+
'function transfer(address, uint256) returns (bool)'
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
const tokenContract = new ethers.Contract(
|
|
379
|
+
tokenAddress,
|
|
380
|
+
tokenAbi,
|
|
381
|
+
wallet // Use wallet as signer
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
// Get USDT decimals
|
|
385
|
+
const decimals = await tokenContract.decimals();
|
|
386
|
+
|
|
387
|
+
// Convert amount to USDT units
|
|
388
|
+
const amountInUnits = ethers.parseUnits(amount, decimals);
|
|
389
|
+
|
|
390
|
+
// Check USDT balance
|
|
391
|
+
const balance = await tokenContract.balanceOf(address);
|
|
392
|
+
if (balance < amountInUnits) {
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
error: `Insufficient token balance. You are trying to send ${amount}`
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Send token
|
|
400
|
+
const tx = await tokenContract.transfer(destination, amountInUnits);
|
|
401
|
+
const receipt = await tx.wait();
|
|
402
|
+
|
|
403
|
+
return {
|
|
404
|
+
success: true,
|
|
405
|
+
txUrl: `${networkConfig.explorerUrl}/tx/${receipt.hash}`
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
} catch (error) {
|
|
409
|
+
return {
|
|
410
|
+
success: false,
|
|
411
|
+
error: error.message
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
module.exports = {
|
|
417
|
+
generateMnemonicFromPassword,
|
|
418
|
+
generateWalletFromPassword,
|
|
419
|
+
getBalanceFromAddress,
|
|
420
|
+
getCustomBalanceFromAddress,
|
|
421
|
+
transferNative,
|
|
422
|
+
transferUSDT,
|
|
423
|
+
transferUSDC,
|
|
424
|
+
transferCustomToken
|
|
425
|
+
}
|
package/utils/tron.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
const bip39 = require('bip39');
|
|
2
|
+
const hdkey = require('hdkey');
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const { TronWeb } = require('tronweb');
|
|
5
|
+
|
|
6
|
+
// mainnet
|
|
7
|
+
const hostURI = "https://api.trongrid.io"
|
|
8
|
+
const usdtContract = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
|
|
9
|
+
|
|
10
|
+
// testnet
|
|
11
|
+
// const hostURI = "https://api.shasta.trongrid.io"
|
|
12
|
+
// const usdtContract = 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs';
|
|
13
|
+
|
|
14
|
+
const USDT_CONTRACT_ABI = [
|
|
15
|
+
{
|
|
16
|
+
'outputs': [{ 'type': 'uint256' }],
|
|
17
|
+
'constant': true,
|
|
18
|
+
'inputs': [{ 'name': 'who', 'type': 'address' }],
|
|
19
|
+
'name': 'balanceOf',
|
|
20
|
+
'stateMutability': 'View',
|
|
21
|
+
'type': 'Function'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
'outputs': [{ 'type': 'bool' }],
|
|
25
|
+
'inputs': [
|
|
26
|
+
{ 'name': '_to', 'type': 'address' },
|
|
27
|
+
{ 'name': '_value', 'type': 'uint256' }
|
|
28
|
+
],
|
|
29
|
+
'name': 'transfer',
|
|
30
|
+
'stateMutability': 'Nonpayable',
|
|
31
|
+
'type': 'Function'
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function generateHash(input) {
|
|
36
|
+
return crypto.createHash('sha256') // Use SHA-256 algorithm
|
|
37
|
+
.update(input) // Hash the input string
|
|
38
|
+
.digest('hex'); // Output the hash in hex format
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function generateMnemonicFromPassword (pwd) {
|
|
42
|
+
const hash = generateHash(pwd)
|
|
43
|
+
const mnemonic = bip39.entropyToMnemonic(hash)
|
|
44
|
+
if (!bip39.validateMnemonic(mnemonic)) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
return mnemonic
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function generatePrivateKeyHexFromMnemonic(seedPhrase) {
|
|
51
|
+
|
|
52
|
+
const derivationPath = "m/44'/1'/9'/9/8"
|
|
53
|
+
const seed = await bip39.mnemonicToSeed(seedPhrase);
|
|
54
|
+
const hdwallet = hdkey.fromMasterSeed(seed);
|
|
55
|
+
const wallet = hdwallet.derive(derivationPath);
|
|
56
|
+
|
|
57
|
+
const privateKey = wallet.privateKey;
|
|
58
|
+
|
|
59
|
+
return Buffer.from(privateKey, "binary").toString("hex")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function generateWalletFromPassword (pwd) {
|
|
63
|
+
const mnemonic = generateMnemonicFromPassword(pwd)
|
|
64
|
+
const privateKeyHex = await generatePrivateKeyHexFromMnemonic(mnemonic)
|
|
65
|
+
const tronWeb = new TronWeb({
|
|
66
|
+
fullHost: hostURI
|
|
67
|
+
});
|
|
68
|
+
const address = tronWeb.address.fromPrivateKey(privateKeyHex);
|
|
69
|
+
return {
|
|
70
|
+
privateKeyHex,
|
|
71
|
+
address
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function getTRXBalance(address) {
|
|
76
|
+
try {
|
|
77
|
+
const tronWeb = new TronWeb({
|
|
78
|
+
fullHost: hostURI
|
|
79
|
+
});
|
|
80
|
+
const balanceInSun = await tronWeb.trx.getBalance(address); // Balance in SUN (1 TRX = 1,000,000 SUN)
|
|
81
|
+
const balanceInTRX = tronWeb.fromSun(balanceInSun); // Convert to TRX
|
|
82
|
+
return balanceInTRX
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('Error fetching TRX balance:', error);
|
|
85
|
+
return -1
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function getUSDTBalance(address) {
|
|
90
|
+
try {
|
|
91
|
+
const tronWeb = new TronWeb({
|
|
92
|
+
fullHost: hostURI
|
|
93
|
+
});
|
|
94
|
+
tronWeb.setAddress(usdtContract)
|
|
95
|
+
|
|
96
|
+
const contract = await tronWeb.contract(USDT_CONTRACT_ABI, usdtContract);
|
|
97
|
+
const balance = await contract.balanceOf(address).call();
|
|
98
|
+
|
|
99
|
+
const usdtBalance = tronWeb.toDecimal(balance) / Math.pow(10, 6);
|
|
100
|
+
return usdtBalance
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error('Error fetching USDT balance:', error);
|
|
103
|
+
return -1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function getBalanceFromAddress (address) {
|
|
108
|
+
const trx_balance = await getTRXBalance(address)
|
|
109
|
+
const usdt_balance = await getUSDTBalance(address)
|
|
110
|
+
return {
|
|
111
|
+
trx_balance,
|
|
112
|
+
usdt_balance
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function transferTRX (creds, destination, amountInTRX) {
|
|
117
|
+
|
|
118
|
+
const { privateKeyHex } = creds;
|
|
119
|
+
|
|
120
|
+
const tronWeb = new TronWeb({
|
|
121
|
+
fullHost: hostURI,
|
|
122
|
+
privateKey: privateKeyHex
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const transaction = await tronWeb.trx.sendTransaction(destination, tronWeb.toSun(amountInTRX));
|
|
127
|
+
const { result, txid } = transaction
|
|
128
|
+
if (result)
|
|
129
|
+
return { success: true, result: txid }
|
|
130
|
+
console.log(transaction)
|
|
131
|
+
return { success: false, result: "error" };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Error transferring TRX:', error);
|
|
134
|
+
return { success: false, result: "error" };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function transferUSDT (creds, destination, amountInUSDT) {
|
|
139
|
+
|
|
140
|
+
const { privateKeyHex, address } = creds;
|
|
141
|
+
|
|
142
|
+
const tronWeb = new TronWeb({
|
|
143
|
+
fullHost: hostURI,
|
|
144
|
+
privateKey: privateKeyHex
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const contract = await tronWeb.contract().at(usdtContract);
|
|
149
|
+
const transaction = await contract.methods.transfer(destination, tronWeb.toSun(amountInUSDT)).send({ from: address });
|
|
150
|
+
return { success: true, result: transaction }
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error('Error transferring USDT:', error);
|
|
153
|
+
return { success: false, result: "error" };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
generateMnemonicFromPassword,
|
|
159
|
+
generateWalletFromPassword,
|
|
160
|
+
getBalanceFromAddress,
|
|
161
|
+
transferTRX,
|
|
162
|
+
transferUSDT
|
|
163
|
+
}
|