@codegame.dev/wallet-cli
Version:
A CLI tool for managing wallets across multiple blockchains, supporting operations like wallet creation, balance checking, transfers, and fee estimation.
212 lines (211 loc) • 7.77 kB
JavaScript
import { ethers, formatUnits } from "ethers";
import { TronWeb } from 'tronweb';
import { sleep } from "../utils/index.js";
const trc20Abi = [
{
"constant": true,
"inputs": [{ "name": "owner", "type": "address" }],
"name": "balanceOf",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" }
],
"name": "transfer",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{ "name": "", "type": "uint8" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "from", "type": "address" },
{ "indexed": true, "name": "to", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "owner", "type": "address" },
{ "indexed": true, "name": "spender", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Approval",
"type": "event"
}
];
export const getBalance = async (params) => {
const tronWeb = new TronWeb({
fullHost: params.jsonRpcProvider,
});
tronWeb.setAddress(params.address);
if (params.tokenAddress) {
const tokenContract = tronWeb.contract(trc20Abi, params.tokenAddress);
const decimals = await tokenContract.decimals().call();
await sleep(params.delay);
const tokenBalance = formatUnits(await tokenContract.balanceOf(params.address).call(), decimals);
return {
success: true,
token_balance: tokenBalance,
};
}
else {
const coinBalance = formatUnits(await tronWeb.trx.getBalance(params.address), params.chainDecimals);
return {
success: true,
coin_balance: coinBalance,
};
}
};
export const transfer = async (params) => {
const tronWeb = new TronWeb({
fullHost: params.jsonRpcProvider,
});
tronWeb.setPrivateKey(Buffer.from(params.secretKey).toString('hex'));
tronWeb.setAddress(params.fromAddress);
if (params.tokenAddress) {
const tokenContract = tronWeb.contract(trc20Abi, params.tokenAddress);
const decimals = Number(await tokenContract.decimals().call());
await sleep(params.delay);
const amount = Number(params.amount).toFixed(decimals);
const amountInSun = ethers.parseUnits(amount, decimals);
const transaction = await tokenContract.transfer(params.toAddress, amountInSun).send();
const hash = transaction;
const fee = "0";
return {
success: true,
hash,
fee,
};
}
else {
const amount = Number(params.amount).toFixed(params.chainDecimals);
const amountInSun = Number(ethers.parseUnits(amount, params.chainDecimals));
const transaction = await tronWeb.trx.sendTransaction(params.toAddress, amountInSun);
const hash = transaction.txid;
const fee = "0";
return {
success: true,
hash,
fee,
};
}
};
export const estimateFee = async (params) => {
const tronWeb = new TronWeb({
fullHost: params.jsonRpcProvider,
});
tronWeb.setAddress(params.fromAddress);
if (params.tokenAddress) {
const tokenContract = tronWeb.contract(trc20Abi, params.tokenAddress);
const decimals = await tokenContract.decimals().call();
await sleep(params.delay);
const amountInSun = ethers.parseUnits("0", decimals);
const result = await tronWeb.transactionBuilder.triggerConstantContract(params.tokenAddress, 'transfer(address,uint256)', {}, [
{ type: 'address', value: params.toAddress },
{ type: 'uint256', value: amountInSun }
], params.fromAddress);
await sleep(params.delay);
const energyLimit = (result.energy_used || result.energy_required || 0) + (result.energy_penalty || 0);
const currentTimestamp = Date.now();
const energyPrices = (await tronWeb.trx.getEnergyPrices()).split(",").map(part => part.split(':').map(v => Number(v)));
energyPrices.reverse();
await sleep(params.delay);
const energyPrice = (energyPrices.find(part => currentTimestamp <= part[0]) || energyPrices[0])[1];
if (!energyPrice) {
return {
success: false,
code: 'empty-gas-price',
message: "Error in fetching energy price",
};
}
const energyCostInSum = energyLimit * energyPrice;
const energyCost = formatUnits(energyCostInSum, params.chainDecimals);
const bandwidthLimit = 400;
const bandwidthPrices = (await tronWeb.trx.getBandwidthPrices()).split(",").map(part => part.split(':').map(v => Number(v)));
bandwidthPrices.reverse();
const bandwidthPrice = (bandwidthPrices.find(part => currentTimestamp <= part[0]) || bandwidthPrices[0])[1];
if (!bandwidthPrice) {
return {
success: false,
code: 'empty-gas-price',
message: "Error in fetching bandwidth price",
};
}
const bandwidthCostInSum = bandwidthLimit * bandwidthPrice;
const bandwidthCost = formatUnits(bandwidthCostInSum, params.chainDecimals);
const gasCost = Number(bandwidthCost) + Number(energyCost);
return {
success: true,
fee: String(gasCost || 0),
};
}
else {
const bandwidthLimit = 400;
const bandwidthPrices = (await tronWeb.trx.getBandwidthPrices()).split(",").map(part => part.split(':').map(v => Number(v)));
bandwidthPrices.reverse();
const currentTimestamp = Date.now();
const bandwidthPrice = (bandwidthPrices.find(part => currentTimestamp <= part[0]) || bandwidthPrices[0])[1];
if (!bandwidthPrice) {
return {
success: false,
code: 'empty-gas-price',
message: "Error in fetching bandwidth price"
};
}
const bandwidthCostInSum = bandwidthLimit * bandwidthPrice;
const bandwidthCost = formatUnits(bandwidthCostInSum, params.chainDecimals);
const gasCost = bandwidthCost;
return {
success: true,
fee: gasCost,
};
}
};
export default { getBalance, transfer, estimateFee };