-
Notifications
You must be signed in to change notification settings - Fork 0
/
Form1.cs
189 lines (164 loc) · 7.52 KB
/
Form1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using Nethereum.Hex.HexTypes;
using Nethereum.JsonRpc.Client;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Util;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BatchAirdropClaim
{
public partial class Form1 : Form
{
private List<WalletInfo> walletInfos;
private readonly TokenTransferService tokenTransferService;
private readonly TokenCheckAndTransferService tokenCheckAndTransferService;
private readonly AirdropService airdropService;
private readonly AppSettings appSettings;
public Form1()
{
InitializeComponent();
try
{
appSettings = ConfigHelper.LoadAppSettings();
if (appSettings == null)
{
MessageBox.Show("appSettings could not be loaded.");
return;
}
}
catch (Exception ex)
{
MessageBox.Show($"Error loading appSettings: {ex.Message}");
return;
}
tokenTransferService = new TokenTransferService(appSettings.RpcUrl, appSettings.TargetWalletAddress, appSettings.TargetWalletPrivateKey);
tokenCheckAndTransferService = new TokenCheckAndTransferService(appSettings.RpcUrl, appSettings.TokenContractAddress, appSettings.TokenContractAbi, appSettings.ImportFileName);
airdropService = new AirdropService(appSettings.RpcUrl, appSettings.AirdropContractAddress, appSettings.AirdropContractAbi, appSettings.AirdropFunctionName, appSettings.AirdropFunctionData, appSettings.ImportFileName);
}
private void Form1_Load(object sender, System.EventArgs e)
{
if (appSettings == null)
{
MessageBox.Show("appSettings could not be loaded.");
return;
}
_ = MonitorWalletsAsync();
}
private void btnLoadFile_Click(object sender, System.EventArgs e)
{
using (var openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "CSV files (*.csv)|*.csv|Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
var filePath = openFileDialog.FileName;
if (filePath.EndsWith(".csv"))
{
walletInfos = FileHelper.ImportCsv(filePath);
}
else if (filePath.EndsWith(".xlsx"))
{
walletInfos = FileHelper.ImportExcel(filePath);
}
dataGridView1.DataSource = walletInfos;
}
}
}
private async void btnCheckAndTransferTokens_Click(object sender, System.EventArgs e)
{
if (walletInfos == null || walletInfos.Count == 0)
{
MessageBox.Show("No wallet information available.");
return;
}
foreach (var wallet in walletInfos)
{
var balance = await tokenCheckAndTransferService.GetTokenBalanceAsync(wallet.Address);
if (balance > 0)
{
try
{
await tokenCheckAndTransferService.TransferTokenAsync(wallet.Address, appSettings.TargetWalletAddress, balance);
}
catch (RpcResponseException ex)
{
if (ex.Message.Contains("insufficient funds for gas"))
{
await HandleInsufficientGasAsync(wallet.Address, balance);
}
else
{
MessageBox.Show($"An error occurred while transferring tokens for address {wallet.Address}: {ex.Message}");
Clipboard.SetText(ex.Message);
}
}
catch (Exception ex)
{
MessageBox.Show($"An error occurred while transferring tokens for address {wallet.Address}: {ex.Message}");
Clipboard.SetText(ex.Message);
}
}
}
}
private async Task HandleInsufficientGasAsync(string fromAddress, decimal amount)
{
try
{
// Fetch target wallet private key
string targetWalletPrivateKey = appSettings.TargetWalletPrivateKey;
// Create account for the target wallet
var targetAccount = new Account(targetWalletPrivateKey);
// Get gas price from the error message and increase by 25%
var gasPrice = await tokenCheckAndTransferService.GetGasPriceAsync();
//gasPrice *= 1.25m; // Dönüşüm yapılmalı
// Calculate gas amount needed for the transaction
var gasAmount = await tokenCheckAndTransferService.EstimateGasAsync(appSettings.TargetWalletAddress, fromAddress);
//var gasPriceHex = new HexBigInteger((gasPrice * 1000000000).ToString()); // Convert to Wei
var transactionInput = new TransactionInput
{
From = appSettings.TargetWalletAddress,
To = fromAddress,
Value = new HexBigInteger(Web3.Convert.ToWei(gasPrice * gasAmount, UnitConversion.EthUnit.Wei)),
};
transactionInput.Gas = new HexBigInteger(gasAmount);
// Send transaction to target wallet
var web3 = new Web3(targetAccount, appSettings.RpcUrl);
var transactionHash = await web3.Eth.TransactionManager.SendTransactionAsync(transactionInput);
// Retry the main transaction after successfully handling insufficient gas
await tokenCheckAndTransferService.TransferTokenAsync(fromAddress, appSettings.TargetWalletAddress, amount);
}
catch (Exception ex)
{
Clipboard.SetText(ex.Message);
MessageBox.Show($"An error occurred while handling insufficient gas for address {fromAddress}: {ex.Message}");
}
}
private async void btnExecuteAirdrop_Click(object sender, System.EventArgs e)
{
await airdropService.ExecuteAirdropAsync();
}
private async Task MonitorWalletsAsync()
{
while (true)
{
if (walletInfos == null || walletInfos.Count == 0)
{
await Task.Delay(500); // .5 second delay
continue;
}
foreach (var wallet in walletInfos)
{
var balance = await tokenCheckAndTransferService.GetTokenBalanceAsync(wallet.Address);
if (balance > 0)
{
await tokenCheckAndTransferService.TransferTokenAsync(wallet.Address, appSettings.TargetWalletAddress, balance);
}
await Task.Delay(500); // .5 second delay
}
}
}
}
}