446 lines
15 KiB
C#
446 lines
15 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using WpfApp1TRC20.Data;
|
|
using WpfApp1TRC20.Services;
|
|
using TransactionStatus = WpfApp1TRC20.Data.TransactionStatus;
|
|
|
|
namespace WpfApp1TRC20.ViewModels
|
|
{
|
|
|
|
public class MainViewModel : ViewModelBase
|
|
{
|
|
private readonly IDataService _dataService;
|
|
private readonly ITronService _tronService;
|
|
private readonly ILogger<MainViewModel> _logger;
|
|
|
|
private TokenInfo _selectedToken;
|
|
private WalletAccount _selectedWallet;
|
|
private string _selectedTabItem = "Dashboard";
|
|
|
|
public MainViewModel(IDataService dataService, ITronService tronService, ILogger<MainViewModel> logger)
|
|
{
|
|
_dataService = dataService;
|
|
_tronService = tronService;
|
|
_logger = logger;
|
|
|
|
Tokens = new ObservableCollection<TokenInfo>();
|
|
Wallets = new ObservableCollection<WalletAccount>();
|
|
Transactions = new ObservableCollection<TransactionRecord>();
|
|
TokenBalances = new ObservableCollection<TokenBalance>();
|
|
|
|
// Commands
|
|
CreateTokenCommand = new RelayCommand(async () => await CreateTokenAsync());
|
|
CreateWalletCommand = new RelayCommand(async () => await CreateWalletAsync());
|
|
ImportWalletCommand = new RelayCommand(async () => await ImportWalletAsync());
|
|
TransferTokenCommand = new RelayCommand(async () => await TransferTokenAsync(), CanTransferToken);
|
|
RefreshDataCommand = new RelayCommand(async () => await RefreshDataAsync());
|
|
|
|
// Load initial data
|
|
_ = Task.Run(RefreshDataAsync);
|
|
}
|
|
|
|
// Properties
|
|
public ObservableCollection<TokenInfo> Tokens { get; }
|
|
public ObservableCollection<WalletAccount> Wallets { get; }
|
|
public ObservableCollection<TransactionRecord> Transactions { get; }
|
|
public ObservableCollection<TokenBalance> TokenBalances { get; }
|
|
|
|
public TokenInfo SelectedToken
|
|
{
|
|
get => _selectedToken;
|
|
set => SetProperty(ref _selectedToken, value);
|
|
}
|
|
|
|
public WalletAccount SelectedWallet
|
|
{
|
|
get => _selectedWallet;
|
|
set
|
|
{
|
|
SetProperty(ref _selectedWallet, value);
|
|
if (value != null)
|
|
_ = Task.Run(() => LoadTokenBalancesAsync(value.Address));
|
|
}
|
|
}
|
|
|
|
public string SelectedTabItem
|
|
{
|
|
get => _selectedTabItem;
|
|
set => SetProperty(ref _selectedTabItem, value);
|
|
}
|
|
|
|
// Token Creation Properties
|
|
private string _newTokenName;
|
|
public string NewTokenName
|
|
{
|
|
get => _newTokenName;
|
|
set => SetProperty(ref _newTokenName, value);
|
|
}
|
|
|
|
private string _newTokenSymbol;
|
|
public string NewTokenSymbol
|
|
{
|
|
get => _newTokenSymbol;
|
|
set => SetProperty(ref _newTokenSymbol, value);
|
|
}
|
|
|
|
private int _newTokenDecimals = 18;
|
|
public int NewTokenDecimals
|
|
{
|
|
get => _newTokenDecimals;
|
|
set => SetProperty(ref _newTokenDecimals, value);
|
|
}
|
|
|
|
private decimal _newTokenSupply = 1000000;
|
|
public decimal NewTokenSupply
|
|
{
|
|
get => _newTokenSupply;
|
|
set => SetProperty(ref _newTokenSupply, value);
|
|
}
|
|
|
|
private int _newTokenExpiryDays = 30;
|
|
public int NewTokenExpiryDays
|
|
{
|
|
get => _newTokenExpiryDays;
|
|
set => SetProperty(ref _newTokenExpiryDays, value);
|
|
}
|
|
|
|
// Transfer Properties
|
|
private string _transferToAddress;
|
|
public string TransferToAddress
|
|
{
|
|
get => _transferToAddress;
|
|
set => SetProperty(ref _transferToAddress, value);
|
|
}
|
|
|
|
private decimal _transferAmount;
|
|
public decimal TransferAmount
|
|
{
|
|
get => _transferAmount;
|
|
set => SetProperty(ref _transferAmount, value);
|
|
}
|
|
|
|
private TokenBalance _selectedTokenBalance;
|
|
public TokenBalance SelectedTokenBalance
|
|
{
|
|
get => _selectedTokenBalance;
|
|
set => SetProperty(ref _selectedTokenBalance, value);
|
|
}
|
|
|
|
private string _newWalletName;
|
|
public string NewWalletName
|
|
{
|
|
get => _newWalletName;
|
|
set => SetProperty(ref _newWalletName, value);
|
|
}
|
|
|
|
private string _importPrivateKey;
|
|
public string ImportPrivateKey
|
|
{
|
|
get => _importPrivateKey;
|
|
set => SetProperty(ref _importPrivateKey, value);
|
|
}
|
|
|
|
private bool _isLoading;
|
|
public bool IsLoading
|
|
{
|
|
get => _isLoading;
|
|
set => SetProperty(ref _isLoading, value);
|
|
}
|
|
|
|
private string _statusMessage;
|
|
public string StatusMessage
|
|
{
|
|
get => _statusMessage;
|
|
set => SetProperty(ref _statusMessage, value);
|
|
}
|
|
|
|
// Commands
|
|
public ICommand CreateTokenCommand { get; }
|
|
public ICommand CreateWalletCommand { get; }
|
|
public ICommand ImportWalletCommand { get; }
|
|
public ICommand TransferTokenCommand { get; }
|
|
public ICommand RefreshDataCommand { get; }
|
|
|
|
// Methods
|
|
private async Task CreateTokenAsync()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(NewTokenName) || string.IsNullOrWhiteSpace(NewTokenSymbol) || SelectedWallet == null)
|
|
{
|
|
StatusMessage = "Please fill all required fields and select a wallet";
|
|
return;
|
|
}
|
|
|
|
IsLoading = true;
|
|
StatusMessage = "Creating token...";
|
|
|
|
try
|
|
{
|
|
var parameters = new TokenCreationParams
|
|
{
|
|
Name = NewTokenName,
|
|
Symbol = NewTokenSymbol,
|
|
Decimals = NewTokenDecimals,
|
|
TotalSupply = NewTokenSupply,
|
|
ExpiryDays = NewTokenExpiryDays,
|
|
OwnerAddress = SelectedWallet.Address
|
|
};
|
|
|
|
var privateKey = _tronService.DecryptPrivateKey(SelectedWallet.EncryptedPrivateKey);
|
|
var txHash = await _tronService.CreateTokenAsync(parameters, privateKey);
|
|
|
|
var token = new TokenInfo
|
|
{
|
|
Name = parameters.Name,
|
|
Symbol = parameters.Symbol,
|
|
Decimals = parameters.Decimals,
|
|
TotalSupply = parameters.TotalSupply,
|
|
OwnerAddress = parameters.OwnerAddress,
|
|
CreationDate = DateTime.UtcNow,
|
|
ExpiryDate = DateTime.UtcNow.AddDays(parameters.ExpiryDays),
|
|
ExpiryDays = parameters.ExpiryDays,
|
|
TransactionHash = txHash,
|
|
Status = TokenStatus.Creating
|
|
};
|
|
|
|
await _dataService.SaveTokenAsync(token);
|
|
Tokens.Add(token);
|
|
|
|
// Clear form
|
|
NewTokenName = "";
|
|
NewTokenSymbol = "";
|
|
NewTokenDecimals = 18;
|
|
NewTokenSupply = 1000000;
|
|
NewTokenExpiryDays = 30;
|
|
|
|
StatusMessage = $"Token creation initiated. Transaction: {txHash}";
|
|
|
|
// Monitor transaction status
|
|
_ = Task.Run(() => MonitorTokenCreation(token));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error creating token");
|
|
StatusMessage = $"Error creating token: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
private async Task CreateWalletAsync()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(NewWalletName))
|
|
{
|
|
StatusMessage = "Please enter a wallet name";
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
var wallet = _tronService.CreateWallet(NewWalletName);
|
|
await _dataService.SaveWalletAsync(wallet);
|
|
Wallets.Add(wallet);
|
|
|
|
NewWalletName = "";
|
|
StatusMessage = $"Wallet '{wallet.Name}' created successfully";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error creating wallet");
|
|
StatusMessage = $"Error creating wallet: {ex.Message}";
|
|
}
|
|
}
|
|
|
|
private async Task ImportWalletAsync()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(NewWalletName) || string.IsNullOrWhiteSpace(ImportPrivateKey))
|
|
{
|
|
StatusMessage = "Please enter wallet name and private key";
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
var wallet = _tronService.ImportWallet(NewWalletName, ImportPrivateKey);
|
|
await _dataService.SaveWalletAsync(wallet);
|
|
Wallets.Add(wallet);
|
|
|
|
NewWalletName = "";
|
|
ImportPrivateKey = "";
|
|
StatusMessage = $"Wallet '{wallet.Name}' imported successfully";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error importing wallet");
|
|
StatusMessage = $"Error importing wallet: {ex.Message}";
|
|
}
|
|
}
|
|
|
|
private bool CanTransferToken()
|
|
{
|
|
return SelectedWallet != null && SelectedTokenBalance != null &&
|
|
!string.IsNullOrWhiteSpace(TransferToAddress) && TransferAmount > 0;
|
|
}
|
|
|
|
private async Task TransferTokenAsync()
|
|
{
|
|
if (!CanTransferToken()) return;
|
|
|
|
IsLoading = true;
|
|
StatusMessage = "Transferring tokens...";
|
|
|
|
try
|
|
{
|
|
var privateKey = _tronService.DecryptPrivateKey(SelectedWallet.EncryptedPrivateKey);
|
|
var txHash = await _tronService.TransferTokenAsync(
|
|
SelectedTokenBalance.ContractAddress,
|
|
privateKey,
|
|
TransferToAddress,
|
|
TransferAmount
|
|
);
|
|
|
|
var transaction = new TransactionRecord
|
|
{
|
|
TransactionHash = txHash,
|
|
FromAddress = SelectedWallet.Address,
|
|
ToAddress = TransferToAddress,
|
|
Amount = TransferAmount,
|
|
TokenSymbol = SelectedTokenBalance.TokenSymbol,
|
|
ContractAddress = SelectedTokenBalance.ContractAddress,
|
|
Timestamp = DateTime.UtcNow,
|
|
Status = TransactionStatus.Pending
|
|
};
|
|
|
|
await _dataService.SaveTransactionAsync(transaction);
|
|
Transactions.Insert(0, transaction);
|
|
|
|
// Clear form
|
|
TransferToAddress = "";
|
|
TransferAmount = 0;
|
|
|
|
StatusMessage = $"Transfer initiated. Transaction: {txHash}";
|
|
|
|
// Refresh balances
|
|
await LoadTokenBalancesAsync(SelectedWallet.Address);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error transferring tokens");
|
|
StatusMessage = $"Error transferring tokens: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
private async Task RefreshDataAsync()
|
|
{
|
|
try
|
|
{
|
|
var tokens = await _dataService.GetTokensAsync();
|
|
var wallets = await _dataService.GetWalletsAsync();
|
|
var transactions = await _dataService.GetTransactionsAsync();
|
|
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
Tokens.Clear();
|
|
foreach (var token in tokens) Tokens.Add(token);
|
|
|
|
Wallets.Clear();
|
|
foreach (var wallet in wallets) Wallets.Add(wallet);
|
|
|
|
Transactions.Clear();
|
|
foreach (var transaction in transactions) Transactions.Add(transaction);
|
|
});
|
|
|
|
if (SelectedWallet != null)
|
|
{
|
|
await LoadTokenBalancesAsync(SelectedWallet.Address);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error refreshing data");
|
|
}
|
|
}
|
|
|
|
private async Task LoadTokenBalancesAsync(string walletAddress)
|
|
{
|
|
try
|
|
{
|
|
var balances = await _dataService.GetTokenBalancesAsync(walletAddress);
|
|
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
TokenBalances.Clear();
|
|
foreach (var balance in balances) TokenBalances.Add(balance);
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error loading token balances");
|
|
}
|
|
}
|
|
|
|
private async Task MonitorTokenCreation(TokenInfo token)
|
|
{
|
|
// Wait for transaction confirmation
|
|
for (int i = 0; i < 30; i++) // Wait up to 5 minutes
|
|
{
|
|
await Task.Delay(10000); // Wait 10 seconds
|
|
|
|
try
|
|
{
|
|
var txInfo = await _tronService.GetTransactionAsync(token.TransactionHash);
|
|
|
|
if (txInfo.Status == TransactionStatus.Confirmed)
|
|
{
|
|
// Extract contract address from transaction (simplified)
|
|
// In real implementation, parse the transaction receipt
|
|
token.ContractAddress = GenerateContractAddress(token.TransactionHash);
|
|
token.Status = TokenStatus.Active;
|
|
|
|
await _dataService.SaveTokenAsync(token);
|
|
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
StatusMessage = $"Token '{token.Symbol}' deployed successfully!";
|
|
});
|
|
|
|
break;
|
|
}
|
|
else if (txInfo.Status == TransactionStatus.Failed)
|
|
{
|
|
token.Status = TokenStatus.Failed;
|
|
await _dataService.SaveTokenAsync(token);
|
|
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
StatusMessage = $"Token '{token.Symbol}' deployment failed";
|
|
});
|
|
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error monitoring token creation");
|
|
}
|
|
}
|
|
}
|
|
|
|
private string GenerateContractAddress(string transactionHash)
|
|
{
|
|
// Simplified contract address generation
|
|
// In real implementation, calculate from transaction details
|
|
return "T" + transactionHash.Substring(0, 33);
|
|
}
|
|
}
|
|
}
|