This commit is contained in:
lzx
2025-10-27 16:27:33 +08:00
parent b7c84fd101
commit b1d3e07c36
14 changed files with 2982 additions and 948 deletions

View File

@@ -125,27 +125,25 @@ func NewETHNode(cfg message.ETHConfig, decodeKey string) (*ETHNode, error) {
}
// ============================ 抽象接口 ============================
func (e *ETHNode) AddAddress(address string, rmq_msg any) {
func (e *ETHNode) AddAddress(address string, rmq_msg any) error {
// 统一转换为小写
address = strings.ToLower(address)
log.Printf("新增钱包监听消息:%v", rmq_msg)
e.ListenAddresses.Store(address, true)
e.mu.Lock()
if len(e.RmqMsgs[address]) == 0 {
e.RmqMsgs[address] = []any{rmq_msg}
} else {
e.RmqMsgs[address] = append(e.RmqMsgs[address], rmq_msg)
}
e.RmqMsgs[address] = append(e.RmqMsgs[address], rmq_msg)
e.mu.Unlock()
return nil
}
func (e *ETHNode) RemoveAddress(address string) {
func (e *ETHNode) RemoveAddress(address string) error {
// 统一转换为小写
address = strings.ToLower(address)
e.ListenAddresses.Delete(address)
e.mu.Lock()
delete(e.RmqMsgs, address)
e.mu.Unlock()
return nil
}
func (e *ETHNode) Listen(symbol string, ch chan any) {
@@ -174,6 +172,10 @@ func (e *ETHNode) Transfer(symbol string, msg any) error {
return nil
}
func (e *ETHNode) Stop() {
e.Cancel()
}
// ============================ rpc节点方法 ============================
func (e *ETHNode) getETHBlance(address string) (*big.Int, error) {
@@ -221,12 +223,11 @@ func (e *ETHNode) getUSDTBalance(address string) (float64, error) {
return bal, nil
}
func (e *ETHNode) getBlockHeight() (uint64, error) {
header, err := e.RpcClient.HeaderByNumber(e.Ctx, nil)
if err != nil {
return 0, fmt.Errorf("failed to get latest block header: %w", err)
}
return header.Number.Uint64(), nil
func (e *ETHNode) getGasLimit() (uint64, error) {
// 对于ERC20转账使用固定的gas limit
// 通常ERC20 transfer需要约65,000-100,000 gas
// 这里设置为80,000足够覆盖大部分情况
return 80000, nil
}
func (e *ETHNode) getSuggestGasPrice() (*big.Int, error) {
@@ -235,9 +236,56 @@ func (e *ETHNode) getSuggestGasPrice() (*big.Int, error) {
if err != nil {
return nil, fmt.Errorf("get suggest-gasprice error:%v", err)
}
// 设置gas price上限避免在网络拥堵时费用过高
// 这里设置为20 Gwei (20 * 10^9 wei)
maxGasPrice := new(big.Int).SetUint64(20000000000) // 20 Gwei
if gasPrice.Cmp(maxGasPrice) > 0 {
log.Printf("⚠️ 建议gas price过高 (%v Gwei),使用上限 20 Gwei", new(big.Int).Div(gasPrice, big.NewInt(1000000000)))
return maxGasPrice, nil
}
log.Printf("✅ 使用建议gas price: %v Gwei", new(big.Int).Div(gasPrice, big.NewInt(1000000000)))
return gasPrice, nil
}
// getEIP1559GasFees 获取EIP-1559的gas费用参数
func (e *ETHNode) getEIP1559GasFees() (*big.Int, *big.Int, error) {
ctx := context.Background()
// 获取基础费用
latestBlock, err := e.RpcClient.BlockByNumber(ctx, nil)
if err != nil {
return nil, nil, fmt.Errorf("failed to get latest block: %w", err)
}
baseFee := latestBlock.BaseFee()
if baseFee == nil {
return nil, nil, fmt.Errorf("base fee not available")
}
// 设置优先级费用tip这里设置为2 Gwei
maxPriorityFeePerGas := new(big.Int).SetUint64(2000000000) // 2 Gwei
// 计算最大费用 = 基础费用 + 优先级费用
maxFeePerGas := new(big.Int).Add(baseFee, maxPriorityFeePerGas)
// 设置最大费用上限为30 Gwei
maxFeeLimit := new(big.Int).SetUint64(30000000000) // 30 Gwei
if maxFeePerGas.Cmp(maxFeeLimit) > 0 {
log.Printf("⚠️ 计算的最大费用过高 (%v Gwei),使用上限 30 Gwei", new(big.Int).Div(maxFeePerGas, big.NewInt(1000000000)))
maxFeePerGas = maxFeeLimit
}
log.Printf("✅ EIP-1559 Gas费用: BaseFee=%v Gwei, MaxPriorityFee=%v Gwei, MaxFee=%v Gwei",
new(big.Int).Div(baseFee, big.NewInt(1000000000)),
new(big.Int).Div(maxPriorityFeePerGas, big.NewInt(1000000000)),
new(big.Int).Div(maxFeePerGas, big.NewInt(1000000000)))
return maxFeePerGas, maxPriorityFeePerGas, nil
}
// ============================ 业务方法 ============================
func (e *ETHNode) listen_usdt(ch chan any) error {
fmt.Println("🔍 ETH 开始监听 USDT Transfer 事件...")
@@ -257,6 +305,7 @@ func (e *ETHNode) listen_usdt(ch chan any) error {
fmt.Println("✅ 订阅成功")
// 处理事件
for {
select {
case err := <-sub.Err():
fmt.Println("⚠️ 订阅异常,准备重连:", err)
@@ -578,7 +627,6 @@ func (e *ETHNode) decodePrivatekey(address string) string {
}
// 使用key解密
privateKey := encryptedKey // 实际使用时替换成具体的解密代码
// fmt.Println(privateKey)
return privateKey
}
@@ -624,7 +672,6 @@ func (e *ETHNode) usdt_transfer(msg any) error {
if originalKey == "" {
return fmt.Errorf("failed to query privatekey")
}
fmt.Println(originalKey)
privateKey, err := crypto.HexToECDSA(originalKey)
if err != nil {
return fmt.Errorf("failed to parse private key: %w", err)
@@ -640,41 +687,125 @@ func (e *ETHNode) usdt_transfer(msg any) error {
if err != nil {
return fmt.Errorf("failed to pack transfer data: %w", err)
}
gasPrice, err := e.getSuggestGasPrice() // 获得当前建议gasPrice
gasLimit, err := e.getGasLimit() // 获得gasLimit
if err != nil {
return fmt.Errorf("get suggest-gasprice error:%v", err)
return fmt.Errorf("get gas limit error:%v", err)
}
eth_balance, err := e.getETHBlance(final_from) // 获得钱包eth余额
// 获取EIP-1559 gas费用参数
maxFeePerGas, maxPriorityFeePerGas, err := e.getEIP1559GasFees()
if err != nil {
log.Printf("⚠️ 获取EIP-1559费用失败回退到传统gas price: %v", err)
// 回退到传统gas price
gasPrice, err := e.getSuggestGasPrice()
if err != nil {
return fmt.Errorf("get suggest-gasprice error:%v", err)
}
eth_balance, err := e.getETHBlance(final_from)
if err != nil {
return fmt.Errorf("%w", err)
}
gasLimit_b := new(big.Int).SetUint64(gasLimit)
gas := new(big.Int).Mul(gasLimit_b, gasPrice)
// 计算gas费用以ETH为单位
gasInETH := new(big.Float).SetInt(gas)
gasInETH.Quo(gasInETH, new(big.Float).SetInt64(1000000000000000000))
log.Printf("💰 传统Gas费用预估: Limit=%d, Price=%v Gwei, 总费用=%.6f ETH",
gasLimit,
new(big.Int).Div(gasPrice, big.NewInt(1000000000)),
gasInETH)
// 判断钱包eth是否支持本次交易gas费用
if eth_balance.Cmp(gas) == -1 {
ethBalanceInETH := new(big.Float).SetInt(eth_balance)
ethBalanceInETH.Quo(ethBalanceInETH, new(big.Float).SetInt64(1000000000000000000))
return fmt.Errorf("❌ 地址 %s ETH余额不足: %.6f ETH < %.6f ETH (gas费用)",
final_from, ethBalanceInETH, gasInETH)
}
// 构造传统交易
tx := types.NewTransaction(
nonce,
e.USDT.Address,
big.NewInt(0),
gasLimit,
gasPrice,
data,
)
// 签名并发送传统交易
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(e.NetId), privateKey)
if err != nil {
return fmt.Errorf("failed to sign transaction: %w", err)
}
txHash := signedTx.Hash().Hex()
err = e.RpcClient.SendTransaction(e.Ctx, signedTx)
if err != nil {
return fmt.Errorf("failed to send transaction: %w", err)
}
log.Printf("✅ 传统交易已提交至mempool%s金额:%.2f USDT, 手续费:%.6f ETH", txHash, amount, gasInETH)
return nil
}
// 使用EIP-1559交易
eth_balance, err := e.getETHBlance(final_from)
if err != nil {
return fmt.Errorf("%w", err)
}
var gasLimit uint64 = 100000
gasLimit_b := new(big.Int).SetUint64(gasLimit)
gas := new(big.Int).Mul(gasLimit_b, gasPrice)
// 计算最大可能的gas费用
maxGasCost := new(big.Int).Mul(new(big.Int).SetUint64(gasLimit), maxFeePerGas)
// 计算gas费用以ETH为单位
maxGasCostInETH := new(big.Float).SetInt(maxGasCost)
maxGasCostInETH.Quo(maxGasCostInETH, new(big.Float).SetInt64(1000000000000000000))
log.Printf("💰 EIP-1559 Gas费用预估: Limit=%d, MaxFee=%v Gwei, MaxPriorityFee=%v Gwei, 最大费用=%.6f ETH",
gasLimit,
new(big.Int).Div(maxFeePerGas, big.NewInt(1000000000)),
new(big.Int).Div(maxPriorityFeePerGas, big.NewInt(1000000000)),
maxGasCostInETH)
// 判断钱包eth是否支持本次交易gas费用
if eth_balance.Cmp(gas) == -1 {
return fmt.Errorf("address=%s balance less than gas=%v(wei)", final_from, eth_balance)
if eth_balance.Cmp(maxGasCost) == -1 {
ethBalanceInETH := new(big.Float).SetInt(eth_balance)
ethBalanceInETH.Quo(ethBalanceInETH, new(big.Float).SetInt64(1000000000000000000))
return fmt.Errorf("❌ 地址 %s ETH余额不足: %.6f ETH < %.6f ETH (最大gas费用)",
final_from, ethBalanceInETH, maxGasCostInETH)
}
// 构造发送到 USDT 合约地址的交易
tx := types.NewTransaction(
nonce,
e.USDT.Address, // 发送到USDT合约地址
big.NewInt(0), // value为0ERC20转账不需要ETH
gasLimit, // GasLimit设置为100000ERC20转账需要更多gas
gasPrice, // GasPrice: 20 Gwei
data, // 附加数据transfer方法调用
)
// 6, 签名交易并获得txHash
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(e.NetId), privateKey)
// txHash := signedTx.Hash().Hex() // 通过签名信息解析出交易hash
// 构造EIP-1559交易
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: e.NetId,
Nonce: nonce,
GasTipCap: maxPriorityFeePerGas,
GasFeeCap: maxFeePerGas,
Gas: gasLimit,
To: &e.USDT.Address,
Value: big.NewInt(0),
Data: data,
})
// 6, 签名EIP-1559交易并获得txHash
signedTx, err := types.SignTx(tx, types.NewLondonSigner(e.NetId), privateKey)
if err != nil {
return fmt.Errorf("failed to sign transaction: %w", err)
return fmt.Errorf("failed to sign EIP-1559 transaction: %w", err)
}
// 7, 发送交易
txHash := signedTx.Hash().Hex()
// 7, 发送EIP-1559交易
err = e.RpcClient.SendTransaction(e.Ctx, signedTx)
if err != nil {
return fmt.Errorf("failed to send transaction: %w", err)
return fmt.Errorf("failed to send EIP-1559 transaction: %w", err)
}
log.Printf("✅ EIP-1559交易已提交至mempool%s金额:%.2f USDT, 最大手续费:%.6f ETH", txHash, amount, maxGasCostInETH)
// // 8, 构造交易消息
// tx_msg := message.Tx_msg{
// TxType: tx_type,
@@ -692,7 +823,3 @@ func (e *ETHNode) usdt_transfer(msg any) error {
// e.UnConfirmTxs[txHash] = tx_msg
return nil
}
func (e *ETHNode) Stop() {
e.Cancel()
}