public bool LoadWallet()
        {
            SeedWords = Guard.Correct(SeedWords);
            Password  = Guard.Correct(Password);            // Do not let whitespaces to the beginning and to the end.

            string walletFilePath = Path.Combine(Global.WalletManager.WalletDirectories.WalletsDir, $"{Global.Network}.json");
            bool   isLoadSuccessful;

            try
            {
                KeyPath.TryParse(ACCOUNT_KEY_PATH, out KeyPath keyPath);

                var mnemonic = new Mnemonic(SeedWords);
                var km       = KeyManager.Recover(mnemonic, Password, filePath: null, keyPath, MIN_GAP_LIMIT);
                km.SetNetwork(Global.Network);
                km.SetFilePath(walletFilePath);
                Global.WalletManager.AddWallet(km);
                Hsm.SetAsync($"{Global.Network}-seedWords", SeedWords.ToString());                 // PROMPT
                Global.UiConfig.HasSeed = true;
                Global.UiConfig.ToFile();
                isLoadSuccessful = true;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                isLoadSuccessful = false;
            }
            return(isLoadSuccessful);
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var str = value as string;

            if (string.IsNullOrWhiteSpace(str))
            {
                return(ValidationResult.Success);
            }
            if (KeyPath.TryParse(str, out _))
            {
                return(ValidationResult.Success);
            }
            else
            {
                return(new ValidationResult("Invalid keypath"));
            }
        }
 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 {
     if (reader.TokenType == JsonToken.Null)
     {
         return(null);
     }
     if (typeof(KeyPath).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()))
     {
         if (KeyPath.TryParse(reader.Value.ToString(), out var k))
         {
             return(k);
         }
         throw new JsonObjectException("Invalid key path", reader);
     }
     else
     {
         if (RootedKeyPath.TryParse(reader.Value.ToString(), out var k))
         {
             return(k);
         }
         throw new JsonObjectException("Invalid rooted key path", reader);
     }
 }
        public async Task LoadWallet()
        {
            SeedWords = Guard.Correct(SeedWords);
            Password  = Guard.Correct(Password); // Do not let whitespaces to the beginning and to the end.

            string walletFilePath = Path.Combine(_walletManager.WalletDirectories.WalletsDir, $"{_config.Network}.json");

            Mnemonic mnemonic = null;
            await Task.Run(() =>
            {
                KeyPath.TryParse(ACCOUNT_KEY_PATH, out KeyPath keyPath);

                mnemonic = new Mnemonic(SeedWords);
                var km   = KeyManager.Recover(mnemonic, Password, filePath: null, keyPath, MIN_GAP_LIMIT);
                km.SetNetwork(_config.Network);
                km.SetFilePath(walletFilePath);
                _walletManager.AddWallet(km);
            });

            await _storage.SetSeedWords(Password, mnemonic.ToString());

            _uiConfig.HasSeed = true;
            _uiConfig.ToFile();
        }
        public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet")
        {
            MnemonicWords = "";

            RecoverCommand = ReactiveCommand.Create(() =>
            {
                WalletName    = Guard.Correct(WalletName);
                MnemonicWords = Guard.Correct(MnemonicWords);
                Password      = Guard.Correct(Password);            // Don't let whitespaces to the beginning and to the end.

                string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json");

                if (string.IsNullOrWhiteSpace(WalletName))
                {
                    ValidationMessage = $"The name {WalletName} is not valid.";
                }
                else if (File.Exists(walletFilePath))
                {
                    ValidationMessage = $"The name {WalletName} is already taken.";
                }
                else if (string.IsNullOrWhiteSpace(MnemonicWords))
                {
                    ValidationMessage = "Recovery Words were not supplied.";
                }
                else if (string.IsNullOrWhiteSpace(AccountKeyPath))
                {
                    ValidationMessage = "The account key path is not valid.";
                }
                else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit)
                {
                    ValidationMessage = $"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}.";
                }
                else if (MinGapLimit > 1_000_000)
                {
                    ValidationMessage = $"Min Gap Limit cannot be larger than {1_000_000}.";
                }
                else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath))
                {
                    ValidationMessage = "The account key path is not a valid derivation path.";
                }
                else
                {
                    try
                    {
                        var mnemonic = new Mnemonic(MnemonicWords);
                        KeyManager.Recover(mnemonic, Password, walletFilePath, keyPath, MinGapLimit);

                        owner.SelectLoadWallet();
                    }
                    catch (Exception ex)
                    {
                        ValidationMessage = ex.ToTypeMessageString();
                        Logger.LogError <LoadWalletViewModel>(ex);
                    }
                }
            });

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(x => UpdateSuggestions(x));
            this.WhenAnyValue(x => x.Password).Subscribe(x =>
            {
                try
                {
                    if (x.NotNullAndNotEmpty())
                    {
                        char lastChar = x.Last();
                        if (lastChar == '\r' || lastChar == '\n')                         // If the last character is cr or lf then act like it'd be a sign to do the job.
                        {
                            Password = x.TrimEnd('\r', '\n');
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogTrace(ex);
                }
            });

            this.WhenAnyValue(x => x.CaretIndex).Subscribe(_ =>
            {
                if (CaretIndex != MnemonicWords.Length)
                {
                    CaretIndex = MnemonicWords.Length;
                }
            });

            _suggestions = new ObservableCollection <SuggestionViewModel>();
        }
Example #6
0
        public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet")
        {
            Global = Locator.Current.GetService <Global>();

            MnemonicWords = "";

            RecoverCommand = ReactiveCommand.Create(() =>
            {
                WalletName    = Guard.Correct(WalletName);
                MnemonicWords = Guard.Correct(MnemonicWords);
                Password      = Guard.Correct(Password);            // Do not let whitespaces to the beginning and to the end.

                string walletFilePath = Global.WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;

                if (string.IsNullOrWhiteSpace(WalletName))
                {
                    NotificationHelpers.Error("Invalid wallet name.");
                }
                else if (File.Exists(walletFilePath))
                {
                    NotificationHelpers.Error("Wallet name is already taken.");
                }
                else if (string.IsNullOrWhiteSpace(MnemonicWords))
                {
                    NotificationHelpers.Error("Recovery Words were not supplied.");
                }
                else if (string.IsNullOrWhiteSpace(AccountKeyPath))
                {
                    NotificationHelpers.Error("The account key path is not valid.");
                }
                else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit)
                {
                    NotificationHelpers.Error($"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}.");
                }
                else if (MinGapLimit > 1_000_000)
                {
                    NotificationHelpers.Error($"Min Gap Limit cannot be larger than {1_000_000}.");
                }
                else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath))
                {
                    NotificationHelpers.Error("The account key path is not a valid derivation path.");
                }
                else
                {
                    try
                    {
                        var mnemonic = new Mnemonic(MnemonicWords);
                        var km       = KeyManager.Recover(mnemonic, Password, filePath: null, keyPath, MinGapLimit);
                        km.SetNetwork(Global.Network);
                        km.SetFilePath(walletFilePath);
                        km.ToFile();

                        NotificationHelpers.Success("Wallet was recovered.");

                        owner.SelectLoadWallet();
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex);
                        NotificationHelpers.Error(ex.ToUserFriendlyString());
                    }
                }
            });

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions);

            _suggestions = new ObservableCollection <SuggestionViewModel>();

            RecoverCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        public async Task InitSeedWords(string password)
        {
            string     wordString = null;
            KeyManager keyManager = null;

            try
            {
                // ensure correct pw
                PasswordHelper.Guard(password);
                string walletFilePath = Path.Combine(_walletManager.WalletDirectories.WalletsDir, $"{_config.Network}.json");
                await Task.Run(() =>
                {
                    keyManager = KeyManager.FromFile(walletFilePath);
                    keyManager.GetMasterExtKey(password ?? "");
                });

                await Task.Run(async() =>
                {
                    // this next line doesn't really run async :/
                    wordString = await _storage.GetSeedWords(password);
                    if (wordString is null)
                    {
                        throw new KeyNotFoundException();
                    }
                });
            }
            catch (SecurityException e)
            {
                // toss bad password to UI
                throw e;
            }
            // KeyNotFoundException || ArgumentException
            catch
            {
                // try migrate from the legacy system
                var seedWords = await _hsm.GetAsync(LegacyWordsLoc);

                if (string.IsNullOrEmpty(seedWords))
                {
                    // check if corrupted and show message
                    throw new InvalidOperationException("Try again if you cancelled the biometric authentication. Otherwise, there are no seed words saved. Please back up using \"Export Wallet File\"");
                }

                // check if words match the wallet file
                KeyManager legacyKM = null;
                await Task.Run(() =>
                {
                    KeyPath.TryParse(ACCOUNT_KEY_PATH, out KeyPath keyPath);

                    var mnemonic = new Mnemonic(seedWords);
                    legacyKM     = KeyManager.Recover(mnemonic, password, filePath: null, keyPath, MIN_GAP_LIMIT);
                });

                if (legacyKM.EncryptedSecret != keyManager.EncryptedSecret)
                {
                    throw new InvalidOperationException("Corrupt seed words. Please back up using \"Export Wallet File\" instead.");
                }

                await _storage.SetSeedWords(password, seedWords);

                wordString = seedWords;
            }
            finally
            {
                SeedWords = wordString?.Split(' ').ToList();
            }
        }
        public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet")
        {
            Global        = owner.Global;
            MnemonicWords = "";

            RecoverCommand = ReactiveCommand.Create(() =>
            {
                WalletName    = Guard.Correct(WalletName);
                MnemonicWords = Guard.Correct(MnemonicWords);
                Password      = Guard.Correct(Password);                    // Do not let whitespaces to the beginning and to the end.

                string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json");

                if (string.IsNullOrWhiteSpace(WalletName))
                {
                    ValidationMessage = $"The name {WalletName} is not valid.";
                }
                else if (File.Exists(walletFilePath))
                {
                    ValidationMessage = $"The name {WalletName} is already taken.";
                }
                else if (string.IsNullOrWhiteSpace(MnemonicWords))
                {
                    ValidationMessage = "Recovery Words were not supplied.";
                }
                else if (string.IsNullOrWhiteSpace(AccountKeyPath))
                {
                    ValidationMessage = "The account key path is not valid.";
                }
                else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit)
                {
                    ValidationMessage = $"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}.";
                }
                else if (MinGapLimit > 1_000_000)
                {
                    ValidationMessage = $"Min Gap Limit cannot be larger than {1_000_000}.";
                }
                else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath))
                {
                    ValidationMessage = "The account key path is not a valid derivation path.";
                }
                else
                {
                    try
                    {
                        var mnemonic = new Mnemonic(MnemonicWords);
                        KeyManager.Recover(mnemonic, Password, walletFilePath, keyPath, MinGapLimit);

                        owner.SelectLoadWallet();
                    }
                    catch (Exception ex)
                    {
                        ValidationMessage = ex.ToTypeMessageString();
                        Logger.LogError(ex);
                    }
                }
            });

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions);

            _suggestions = new ObservableCollection <SuggestionViewModel>();
        }