private static string GetAddress() { while (true) { YellowMsg.Write($"Public {Globals.ticker} address: "); string input = Console.ReadLine(); /* Try and parse into public keys to see if it's valid, don't * need the keys so ignore the result. */ switch (Addresses.KeysFromAddress(input)) { case ILeft <Error> error: { RedMsg.WriteLine(error.Value.errorMessage + "\n"); continue; } default: { return(input); } } } }
public static (bool exit, WalletBackend wallet) SelectionScreen() { while (true) { LaunchAction action = GetAction(); if (action == LaunchAction.Exit) { return(true, null); } /* Get the walletbackend, or an error. On error, return * to selection screen. */ switch (LaunchWallet.HandleAction(action)) { case ILeft <Error> error: { RedMsg.WriteLine( error.Value.errorMessage ); YellowMsg.WriteLine("Returning to selection screen.\n"); continue; } case IRight <WalletBackend> wallet: { return(false, wallet.Value); } } } }
private static PrivateKey GetPrivateKey(string msg) { while (true) { YellowMsg.Write(msg); string input = Console.ReadLine(); if (input.Length != 64) { RedMsg.WriteLine("Invalid private key, should be 64 " + "characters long! Try again.\n"); continue; } if (!input.IsHex()) { RedMsg.WriteLine("Invalid private key, is not a valid " + "hexadecimal string!"); continue; } var p = new PrivateKey(Encoding.HexStringToByteArray(input)); if (!KeyOps.IsValidKey(p)) { RedMsg.WriteLine("Invalid private key, is not a valid " + "ED25519 key!"); } return(p); } }
private static PrivateKeys GetPrivateKeysFromSeed() { while (true) { YellowMsg.Write("Mnemonic seed (25 words): "); string input = Console.ReadLine(); switch (Mnemonics.MnemonicToPrivateKey(input)) { case ILeft <Error> error: { RedMsg.WriteLine(error.Value.errorMessage); Console.WriteLine("Try again.\n"); continue; } case IRight <PrivateKey> key: { var privateSpendKey = key.Value; var privateViewKey = KeyOps.GenerateDeterministicKeys(privateSpendKey) .privateKey; return(new PrivateKeys(privateSpendKey, privateViewKey)); } } } }
/* Attempts to open a wallet, and either returns the wallet, or * an Error */ private static IEither <Error, WalletBackend> OpenWallet() { string walletFilename = GetExistingWalletName(); while (true) { string walletPassword = GetWalletPassword(); var maybeWalletBackend = WalletBackend.Load( walletFilename, walletPassword ); if (maybeWalletBackend.IsLeft()) { Error err = maybeWalletBackend.Left(); /* If the password is incorrect, try again. Else, return * the error. */ if (err.errorName == "INCORRECT_PASSWORD") { RedMsg.WriteLine(err.errorMessage + "\n"); continue; } } return(maybeWalletBackend); } }
private static void ChangePassword(WalletBackend wallet) { Utilities.ConfirmPassword(wallet); string newPassword; while (true) { YellowMsg.Write("Enter your new password: "******"Confirm your new password: "******"Passwords do not match! Try again.\n"); continue; } break; } wallet.password = newPassword; wallet.Save(); GreenMsg.WriteLine("\nPassword successfully updated!"); }
public static void ConfirmPassword(WalletBackend wallet) { while (true) { YellowMsg.Write("Confirm your current password: "******"Incorrect password! Try again.\n"); continue; } return; } }
/* Get the filename to use for a new wallet */ private static string GetNewWalletName() { while (true) { YellowMsg.Write( "What filename would you like to give your new wallet?: " ); string filename = Console.ReadLine(); string appended = filename + ".wallet"; if (string.IsNullOrWhiteSpace(filename)) { RedMsg.WriteLine( "Wallet name cannot be empty! Try again.\n" ); continue; } if (GeneralUtilities.FilenameInUse(filename) || GeneralUtilities.FilenameInUse(appended)) { RedMsg.Write("A file with the name "); YellowMsg.Write(filename); RedMsg.Write(" or "); YellowMsg.Write(appended); RedMsg.WriteLine(" already exists! Try again.\n"); } /* If the file already ends with .wallet, return it. */ else if (filename.EndsWith(".wallet")) { return(filename); } /* Else, append .wallet to the filename */ else { return(appended); } } }
/* Get the filename of an already existing wallet */ private static string GetExistingWalletName() { while (true) { YellowMsg.Write( "What wallet filename would you like to open?: " ); string filename = Console.ReadLine(); string appended = filename + ".wallet"; if (string.IsNullOrWhiteSpace(filename)) { RedMsg.WriteLine("Wallet name cannot be empty! Try again."); continue; } if (File.Exists(filename)) { return(filename); } /* Automatically add the .wallet extension for users */ else if (File.Exists(appended)) { return(appended); } else { RedMsg.Write("A file with the name "); YellowMsg.Write(filename); RedMsg.Write(" or "); YellowMsg.Write(appended); RedMsg.WriteLine(" doesn't exist!"); Console.WriteLine( "Ensure you entered your wallet name correctly.\n" ); } } }
/* Get the password for a new wallet file (Confirm the password) */ private static string GetNewWalletPassword() { while (true) { YellowMsg.Write("Give your new wallet a password: "******"Confirm your new password: "******"Passwords do not match! Try again.\n"); } else { return(firstPassword); } } }
private static void ExportKeys(WalletBackend wallet) { Utilities.ConfirmPassword(wallet); RedMsg.WriteLine("The below data is PRIVATE and should not be " + "given to anyone!"); RedMsg.WriteLine("If someone else gains access to these, they " + "can steal all your funds!"); Console.WriteLine(); if (wallet.isViewWallet) { GreenMsg.WriteLine("Private view key:"); GreenMsg.WriteLine(wallet.keys.privateViewKey.ToString()); return; } GreenMsg.WriteLine("Private spend key:"); GreenMsg.WriteLine(wallet.keys.privateSpendKey.ToString()); Console.WriteLine(); GreenMsg.WriteLine("Private view key:"); GreenMsg.WriteLine(wallet.keys.privateViewKey.ToString()); if (KeyOps.AreKeysDeterministic(wallet.keys.privateSpendKey, wallet.keys.privateViewKey)) { string mnemonic = Mnemonics.PrivateKeyToMnemonic( wallet.keys.privateSpendKey ); GreenMsg.WriteLine("\nMnemonic seed:"); GreenMsg.WriteLine(mnemonic); } }
/* printableCommands = the commands to print on bad input. * availableCommands = the commands that the inputted string is * checked against. * * For example, we print basic commands, but can input both basic * and advanced commands */ private static string ParseCommand( IEnumerable <Command> printableCommands, IEnumerable <Command> availableCommands, string prompt) { string selection = null; while (true) { /* Write the prompt message */ YellowMsg.Write(prompt); selection = Console.ReadLine().ToLower(); /* \n == no-op */ if (selection == "") { continue; } /* Check if they entered a command or an number */ if (int.TryParse(selection, out int selectionNum)) { /* We print 1, 2, 3, 4 etc to be user friendly but we want * to access it with 0 indexing */ selectionNum--; if (selectionNum < 0 || selectionNum >= availableCommands.Count()) { RedMsg.Write("Bad input, expected a command " + "name, or number from "); YellowMsg.Write("1 "); RedMsg.Write("to "); YellowMsg.WriteLine(availableCommands.Count().ToString()); PrintCommands(printableCommands); continue; } /* Set the selection to the command name chosen via * the previously printed numbers */ selection = availableCommands.ElementAt(selectionNum) .commandName; } else { /* Does the inputted command exist? */ if (!availableCommands.Any(c => c.commandName == selection)) { Console.Write("Unknown command: "); RedMsg.Write($"{selection}\n"); PrintCommands(printableCommands); continue; } } return(selection); } }
public static bool HandleCommand(string command, WalletBackend wallet) { switch (command) { case "advanced": { Advanced(wallet); break; } case "address": { GreenMsg.WriteLine(wallet.addresses[0]); break; } case "balance": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "backup": { ExportKeys(wallet); break; } case "exit": { return(Exit(wallet)); } case "help": { Help(wallet); break; } case "transfer": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "ab_add": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "ab_delete": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "ab_list": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "ab_send": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "change_password": { ChangePassword(wallet); break; } case "make_integrated_address": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "incoming_transfers": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "list_transfers": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "optimize": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "outgoing_transfers": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "reset": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "save": { Save(wallet); break; } case "save_csv": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "send_all": { RedMsg.WriteLine("Command not implemented yet..."); break; } case "status": { RedMsg.WriteLine("Command not implemented yet..."); break; } /* This should never happen */ default: { throw new NotImplementedException( "Command was defined but not hooked up!" ); } } /* Don't exit */ return(false); }