117 lines
3.7 KiB
JavaScript
117 lines
3.7 KiB
JavaScript
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 (isNaN(num)) return '0';
|
||
return parseFloat(num.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; |