batch-bsc-sender/utils.js
2026-01-24 22:31:49 +08:00

126 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class TransferUtils {
static parseCSV(csvText) {
const lines = csvText.split('\n');
const transfers = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (!line) continue;
// 支持逗号分隔或制表符分隔
const parts = line.includes('\t') ? line.split('\t') : line.split(',');
if (parts.length >= 2) {
const address = parts[0].trim();
const amount = parts[1].trim();
const note = parts[2] ? parts[2].trim() : '';
// 基本验证
if (address && amount) {
transfers.push({
address,
amount: parseFloat(amount),
note
});
}
}
}
return transfers;
}
static formatAddress(address) {
if (!address || address.length < 10) return address;
return `${address.slice(0, 6)}...${address.slice(-4)}`;
}
static formatNumber(num, decimals = 4) {
// 处理各种输入类型
if (num === null || num === undefined) return '0';
// 转换为数字
const numValue = typeof num === 'string' ? parseFloat(num) : Number(num);
// 检查是否为有效数字
if (isNaN(numValue)) return '0';
// 格式化并返回
return parseFloat(numValue.toFixed(decimals)).toString();
}
static generateLogMessage(type, message) {
const time = new Date().toLocaleTimeString();
const types = {
success: { icon: '✅', class: 'success' },
error: { icon: '❌', class: 'error' },
info: { icon: '', class: 'info' },
warning: { icon: '⚠️', class: 'warning' }
};
const typeInfo = types[type] || types.info;
return {
time,
type: typeInfo.class,
message: `${typeInfo.icon} ${message}`,
html: `
<div class="log-item ${typeInfo.class}">
<div class="log-time">${time}</div>
<div class="log-message">${typeInfo.icon} ${message}</div>
</div>
`
};
}
static exportToCSV(data, filename = 'transfer-results.csv') {
const headers = ['序号', '收款地址', '金额(BNB)', '状态', '交易哈希', '备注'];
const rows = data.map(item => [
item.index + 1,
item.to,
item.amount,
item.success ? '成功' : '失败',
item.hash || '',
item.error || ''
]);
const csvContent = [headers, ...rows]
.map(row => row.map(cell => `"${cell}"`).join(','))
.join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
} else {
link.href = URL.createObjectURL(blob);
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
static validateEthereumAddress(address) {
try {
return ethers.utils.isAddress(address);
} catch {
return false;
}
}
static async checkBalanceSufficient(provider, address, requiredAmount) {
try {
const balance = await provider.getBalance(address);
const required = ethers.utils.parseEther(requiredAmount.toString());
return balance.gte(required);
} catch (error) {
console.error('检查余额失败:', error);
return false;
}
}
}
// 导出工具类
window.TransferUtils = TransferUtils;