From b9ea0d6988b21bb06dc6b3fb728299cbe5adcfee Mon Sep 17 00:00:00 2001 From: Michiel Post Date: Mon, 21 Oct 2024 11:59:57 +0200 Subject: [PATCH] Check for locked wallets --- src/aoWebWallet/Pages/ActionPage.razor | 6 ++ src/aoWebWallet/Pages/CreateTokenPage.razor | 5 + .../Pages/GenerateWalletPage.razor | 40 ++------ .../Pages/GenerateWalletPage.razor.cs | 58 +---------- src/aoWebWallet/Pages/ImportWalletPage.razor | 41 ++++++++ .../Pages/ImportWalletPage.razor.cs | 11 +++ src/aoWebWallet/Pages/Start.razor | 1 + .../Services/CreateTokenService.cs | 2 + .../Services/TransactionService.cs | 12 ++- .../Shared/AddUploadWalletComponent.razor | 9 +- .../Shared/AddWalletComponent.razor | 8 +- .../Shared/SetSecretKeyComponent.razor | 98 +++++++++++++++++++ .../Shared/UnlockWalletComponent.razor | 2 + .../Shared/UnlockWalletDialog.razor | 5 +- src/aoWebWallet/ViewModels/MainViewModel.cs | 35 ++++--- .../ViewModels/WalletDetailsViewModel.cs | 6 +- src/aoWebWallet/aoWebWallet.csproj | 2 +- 17 files changed, 232 insertions(+), 109 deletions(-) create mode 100644 src/aoWebWallet/Pages/ImportWalletPage.razor create mode 100644 src/aoWebWallet/Pages/ImportWalletPage.razor.cs create mode 100644 src/aoWebWallet/Shared/SetSecretKeyComponent.razor diff --git a/src/aoWebWallet/Pages/ActionPage.razor b/src/aoWebWallet/Pages/ActionPage.razor index c3eff3f..9221414 100644 --- a/src/aoWebWallet/Pages/ActionPage.razor +++ b/src/aoWebWallet/Pages/ActionPage.razor @@ -165,6 +165,12 @@ Wallet? ownerWallet = BindingContext.WalletList.Data?.Where(x => x.Address == wallet.OwnerAddress).FirstOrDefault(); started = true; + + if(wallet.NeedsUnlock || (ownerWallet?.NeedsUnlock ?? false)) + { + ///TODO: Trigger Unlock + } + await transactionService.SendAction(wallet, ownerWallet, AoAction); } diff --git a/src/aoWebWallet/Pages/CreateTokenPage.razor b/src/aoWebWallet/Pages/CreateTokenPage.razor index 7d188ce..d802813 100644 --- a/src/aoWebWallet/Pages/CreateTokenPage.razor +++ b/src/aoWebWallet/Pages/CreateTokenPage.razor @@ -102,6 +102,11 @@ if (wallet == null) return; + if (wallet.NeedsUnlock) + { + //TODO: Trigger unlock + } + //Run preview if not run yet if (data == null) data = CreateTokenService.GetTokenProcessCode(wallet.Address, tokenModel); diff --git a/src/aoWebWallet/Pages/GenerateWalletPage.razor b/src/aoWebWallet/Pages/GenerateWalletPage.razor index 9a632a1..7593dd0 100644 --- a/src/aoWebWallet/Pages/GenerateWalletPage.razor +++ b/src/aoWebWallet/Pages/GenerateWalletPage.razor @@ -15,37 +15,7 @@ } else { - - Generate Wallet - Enter a password to encrypt your wallet. The password must be at least 6 characters long. - - - - - - - Generate Wallet - - + } } else @@ -60,4 +30,12 @@ new BreadcrumbItem("Home", href: "/"), new BreadcrumbItem("Generate Wallet", href: null, disabled: true) }; + + protected override void OnInitialized() + { + WatchDataLoaderVM(BindingContext.WalletList); + WatchProp(nameof(BindingContext.SecretKey)); + + base.OnInitialized(); + } } diff --git a/src/aoWebWallet/Pages/GenerateWalletPage.razor.cs b/src/aoWebWallet/Pages/GenerateWalletPage.razor.cs index 443f6c3..7de9707 100644 --- a/src/aoWebWallet/Pages/GenerateWalletPage.razor.cs +++ b/src/aoWebWallet/Pages/GenerateWalletPage.razor.cs @@ -6,62 +6,6 @@ namespace aoWebWallet.Pages { public partial class GenerateWalletPage : MvvmComponentBase { - private string Password { get; set; } = string.Empty; - private string ConfirmPassword { get; set; } = string.Empty; - private bool PasswordVisible { get; set; } = false; - private InputType PasswordInput { get; set; } = InputType.Password; - private string PasswordInputIcon { get; set; } = Icons.Material.Filled.VisibilityOff; - private string PasswordError { get; set; } = string.Empty; - private string ConfirmPasswordError { get; set; } = string.Empty; - - private void TogglePasswordVisibility() - { - if (PasswordVisible) - { - PasswordVisible = false; - PasswordInputIcon = Icons.Material.Filled.VisibilityOff; - PasswordInput = InputType.Password; - } - else - { - PasswordVisible = true; - PasswordInputIcon = Icons.Material.Filled.Visibility; - PasswordInput = InputType.Text; - } - } - - private void GenerateWallet() - { - PasswordError = string.Empty; - ConfirmPasswordError = string.Empty; - - if (string.IsNullOrWhiteSpace(Password) || string.IsNullOrWhiteSpace(ConfirmPassword)) - { - PasswordError = "Please enter and confirm your password."; - return; - } - - if (Password != ConfirmPassword) - { - ConfirmPasswordError = "Passwords do not match."; - return; - } - - if (Password.Length < 6) - { - PasswordError = "Password must be at least 6 characters long."; - return; - } - - if(BindingContext.WalletList.Data?.Any(x => x.NeedsUnlock) ?? true) - { - PasswordError = "Unable to set a new password. Please unlock your wallet first."; - return; - } - - BindingContext.SecretKey = Password; - - Snackbar.Add("Password set successfully!", Severity.Success); - } + } } diff --git a/src/aoWebWallet/Pages/ImportWalletPage.razor b/src/aoWebWallet/Pages/ImportWalletPage.razor new file mode 100644 index 0000000..285a0d8 --- /dev/null +++ b/src/aoWebWallet/Pages/ImportWalletPage.razor @@ -0,0 +1,41 @@ +@page "/import-wallet" +@inherits MvvmComponentBase +@inject ISnackbar Snackbar + +Import Wallet - @Program.PageTitlePostFix + + + + + @if (BindingContext.SecretKey == null) + { + if (BindingContext.CheckNeedsUnlock()) + { + + } + else + { + + } + } + else + { + + } + + +@code { + private List _items = new List + { + new BreadcrumbItem("Home", href: "/"), + new BreadcrumbItem("Import Wallet", href: null, disabled: true) + }; + + protected override void OnInitialized() + { + WatchDataLoaderVM(BindingContext.WalletList); + WatchProp(nameof(BindingContext.SecretKey)); + + base.OnInitialized(); + } +} diff --git a/src/aoWebWallet/Pages/ImportWalletPage.razor.cs b/src/aoWebWallet/Pages/ImportWalletPage.razor.cs new file mode 100644 index 0000000..7de9707 --- /dev/null +++ b/src/aoWebWallet/Pages/ImportWalletPage.razor.cs @@ -0,0 +1,11 @@ +using aoWebWallet.ViewModels; +using Microsoft.AspNetCore.Components; +using MudBlazor; + +namespace aoWebWallet.Pages +{ + public partial class GenerateWalletPage : MvvmComponentBase + { + + } +} diff --git a/src/aoWebWallet/Pages/Start.razor b/src/aoWebWallet/Pages/Start.razor index 8d550af..59a6d51 100644 --- a/src/aoWebWallet/Pages/Start.razor +++ b/src/aoWebWallet/Pages/Start.razor @@ -6,3 +6,4 @@ + diff --git a/src/aoWebWallet/Services/CreateTokenService.cs b/src/aoWebWallet/Services/CreateTokenService.cs index 4dd2228..c97dbfa 100644 --- a/src/aoWebWallet/Services/CreateTokenService.cs +++ b/src/aoWebWallet/Services/CreateTokenService.cs @@ -33,6 +33,8 @@ public string GetTokenProcessCode(string address, CreateTokenModel tokenModel) var address = wallet.Address; string? jwk = wallet.GetJwkSecret(); + if (wallet.NeedsUnlock) + throw new Exception("Wallet is locked"); string newProcessId = await CreateEmptyProcess(tokenModel.Name, jwk); diff --git a/src/aoWebWallet/Services/TransactionService.cs b/src/aoWebWallet/Services/TransactionService.cs index 3098fa1..87ba5ee 100644 --- a/src/aoWebWallet/Services/TransactionService.cs +++ b/src/aoWebWallet/Services/TransactionService.cs @@ -114,13 +114,21 @@ static string RemoveColorCodes(string? input) } if (!string.IsNullOrEmpty(wallet.OwnerAddress) && ownerWallet?.Address == wallet.OwnerAddress - && !string.IsNullOrEmpty(ownerWallet?.GetJwkSecret())) + && (!string.IsNullOrEmpty(ownerWallet?.GetJwkSecret()) || (ownerWallet?.NeedsUnlock ?? false))) { + if(ownerWallet.NeedsUnlock) + throw new Exception("Wallet is locked"); + return await SendActionWithEval(ownerWallet.GetJwkSecret(), wallet.Address, action); } - if (!string.IsNullOrEmpty(wallet.GetJwkSecret())) + if (!string.IsNullOrEmpty(wallet.GetJwkSecret()) || wallet.NeedsUnlock) + { + if (wallet.NeedsUnlock) + throw new Exception("Wallet is locked"); + return await SendActionWithJwk(wallet.GetJwkSecret(), action); + } //Console.WriteLine("No Wallet to send"); return null; diff --git a/src/aoWebWallet/Shared/AddUploadWalletComponent.razor b/src/aoWebWallet/Shared/AddUploadWalletComponent.razor index 0a0e36b..3dfddca 100644 --- a/src/aoWebWallet/Shared/AddUploadWalletComponent.razor +++ b/src/aoWebWallet/Shared/AddUploadWalletComponent.razor @@ -1,4 +1,5 @@ @using aoWebWallet.Models +@using aoww.Services @inherits MvvmComponentBase @inject ArweaveService ArweaveService @inject ISnackbar Snackbar @@ -120,12 +121,18 @@ { Address = address, Name = name, - Jwk = jwk, + JwkSecret = jwk, Source = WalletTypes.Imported, IsReadOnly = false, AddedDate = DateTimeOffset.UtcNow }; + if (!string.IsNullOrEmpty(BindingContext.SecretKey)) + { + var jwkEncrypted = EncryptionService.EncryptWallet(BindingContext.SecretKey, jwk); + wallet.JwkEncrypted = jwkEncrypted; + } + _fileNames.Add(wallet); } catch diff --git a/src/aoWebWallet/Shared/AddWalletComponent.razor b/src/aoWebWallet/Shared/AddWalletComponent.razor index c31b064..480f152 100644 --- a/src/aoWebWallet/Shared/AddWalletComponent.razor +++ b/src/aoWebWallet/Shared/AddWalletComponent.razor @@ -33,7 +33,13 @@ - +
+ + Import wallet + +
diff --git a/src/aoWebWallet/Shared/SetSecretKeyComponent.razor b/src/aoWebWallet/Shared/SetSecretKeyComponent.razor new file mode 100644 index 0000000..cb33d6c --- /dev/null +++ b/src/aoWebWallet/Shared/SetSecretKeyComponent.razor @@ -0,0 +1,98 @@ +@using aoWebWallet.Models +@inherits MvvmComponentBase +@inject ISnackbar Snackbar + + + Generate Wallet + Enter a password to encrypt your wallet. The password must be at least 6 characters long. + + + + + + + Generate Wallet + + + + + +@code { + + private string Password { get; set; } = string.Empty; + private string ConfirmPassword { get; set; } = string.Empty; + private bool PasswordVisible { get; set; } = false; + private InputType PasswordInput { get; set; } = InputType.Password; + private string PasswordInputIcon { get; set; } = Icons.Material.Filled.VisibilityOff; + private string PasswordError { get; set; } = string.Empty; + private string ConfirmPasswordError { get; set; } = string.Empty; + + private void TogglePasswordVisibility() + { + if (PasswordVisible) + { + PasswordVisible = false; + PasswordInputIcon = Icons.Material.Filled.VisibilityOff; + PasswordInput = InputType.Password; + } + else + { + PasswordVisible = true; + PasswordInputIcon = Icons.Material.Filled.Visibility; + PasswordInput = InputType.Text; + } + } + + private void SetSecretKey() + { + PasswordError = string.Empty; + ConfirmPasswordError = string.Empty; + + if (string.IsNullOrWhiteSpace(Password) || string.IsNullOrWhiteSpace(ConfirmPassword)) + { + PasswordError = "Please enter and confirm your password."; + return; + } + + if (Password != ConfirmPassword) + { + ConfirmPasswordError = "Passwords do not match."; + return; + } + + if (Password.Length < 6) + { + PasswordError = "Password must be at least 6 characters long."; + return; + } + + if (BindingContext.WalletList.Data?.Any(x => x.NeedsUnlock) ?? true) + { + PasswordError = "Unable to set a new password. Please unlock your wallet first."; + return; + } + + BindingContext.SecretKey = Password; + + Snackbar.Add("Password set successfully!", Severity.Success); + } +} diff --git a/src/aoWebWallet/Shared/UnlockWalletComponent.razor b/src/aoWebWallet/Shared/UnlockWalletComponent.razor index 16a84b5..62b05f6 100644 --- a/src/aoWebWallet/Shared/UnlockWalletComponent.razor +++ b/src/aoWebWallet/Shared/UnlockWalletComponent.razor @@ -25,6 +25,8 @@ { await BindingContext.TriggerUnlock(); + this.StateHasChanged(); + return true; } } diff --git a/src/aoWebWallet/Shared/UnlockWalletDialog.razor b/src/aoWebWallet/Shared/UnlockWalletDialog.razor index 836d1ca..9ccfb70 100644 --- a/src/aoWebWallet/Shared/UnlockWalletDialog.razor +++ b/src/aoWebWallet/Shared/UnlockWalletDialog.razor @@ -40,13 +40,16 @@ wallet.JwkSecret = EncryptionService.DecryptWallet(Password, wallet.JwkEncrypted); } } + + MudDialog.Close(DialogResult.Ok(true)); + } catch { Progress = "Could not unlock wallets."; } + } - //void Submit() => MudDialog.Close(DialogResult.Ok(true)); void Cancel() => MudDialog.Cancel(); } \ No newline at end of file diff --git a/src/aoWebWallet/ViewModels/MainViewModel.cs b/src/aoWebWallet/ViewModels/MainViewModel.cs index 1daded9..eb76cec 100644 --- a/src/aoWebWallet/ViewModels/MainViewModel.cs +++ b/src/aoWebWallet/ViewModels/MainViewModel.cs @@ -176,6 +176,9 @@ public async Task DeleteWallet(Wallet wallet) public async Task DownloadWallet(Wallet wallet) { + if (wallet.NeedsUnlock) + throw new Exception("Wallet is locked"); + string? jwk = wallet.GetJwkSecret(); if (string.IsNullOrEmpty(jwk)) return; @@ -264,24 +267,30 @@ public async Task GetActiveArConnectAddress() } } - public Task SendToken(Wallet wallet, string tokenId, string address, long amount) - { - if (wallet.Source == WalletTypes.ArConnect) - return SendTokenWithArConnect(tokenId, address, amount); + //public Task SendToken(Wallet wallet, string tokenId, string address, long amount) + //{ + // if (wallet.Source == WalletTypes.ArConnect) + // return SendTokenWithArConnect(tokenId, address, amount); - if (!string.IsNullOrEmpty(wallet.OwnerAddress)) - { - var ownerWallet = WalletList.Data!.Where(x => x.Address == wallet.OwnerAddress).FirstOrDefault(); - return SendTokenWithEval(ownerWallet?.GetJwkSecret(), wallet.Address, tokenId, address, amount); + // if (!string.IsNullOrEmpty(wallet.OwnerAddress)) + // { + // var ownerWallet = WalletList.Data!.Where(x => x.Address == wallet.OwnerAddress).FirstOrDefault(); + // if (ownerWallet?.NeedsUnlock ?? false) + // throw new Exception("Wallet is locked"); + + // return SendTokenWithEval(ownerWallet?.GetJwkSecret(), wallet.Address, tokenId, address, amount); - } + // } - if (!string.IsNullOrEmpty(wallet.GetJwkSecret())) - return SendTokenWithJwk(wallet.GetJwkSecret(), tokenId, address, amount); + // if (wallet.NeedsUnlock) + // throw new Exception("Wallet is locked"); - return Task.FromResult(default); + // if (!string.IsNullOrEmpty(wallet.GetJwkSecret())) + // return SendTokenWithJwk(wallet.GetJwkSecret(), tokenId, address, amount); - } + // return Task.FromResult(default); + + //} public Task SendTokenWithEval(string? jwk, string processId, string tokenId, string address, long amount) => LastTransactionId.DataLoader.LoadAsync(async () => diff --git a/src/aoWebWallet/ViewModels/WalletDetailsViewModel.cs b/src/aoWebWallet/ViewModels/WalletDetailsViewModel.cs index e082e1a..dee5a93 100644 --- a/src/aoWebWallet/ViewModels/WalletDetailsViewModel.cs +++ b/src/aoWebWallet/ViewModels/WalletDetailsViewModel.cs @@ -34,6 +34,8 @@ partial void OnOwnerCanSendChanged(bool value) private void SetCanSend() { + var jwk = Wallet.GetJwkSecret(); + var result = Wallet.Source switch { WalletTypes.None => false, @@ -41,8 +43,8 @@ private void SetCanSend() WalletTypes.Manual => !string.IsNullOrEmpty(Wallet.OwnerAddress) && OwnerCanSend, WalletTypes.Explorer => !string.IsNullOrEmpty(Wallet.OwnerAddress) && OwnerCanSend, WalletTypes.AoProcess => !string.IsNullOrEmpty(Wallet.OwnerAddress) && OwnerCanSend, - WalletTypes.Generated => !string.IsNullOrEmpty(Wallet.GetJwkSecret()), - WalletTypes.Imported => !string.IsNullOrEmpty(Wallet.GetJwkSecret()), + WalletTypes.Generated => !string.IsNullOrEmpty(jwk), + WalletTypes.Imported => !string.IsNullOrEmpty(jwk), _ => false }; diff --git a/src/aoWebWallet/aoWebWallet.csproj b/src/aoWebWallet/aoWebWallet.csproj index 901e83c..1cf078e 100644 --- a/src/aoWebWallet/aoWebWallet.csproj +++ b/src/aoWebWallet/aoWebWallet.csproj @@ -29,7 +29,7 @@ - +