func Seed(reader *bufio.Reader) (seed []byte, imported bool, err error) {
	useUserSeed, err := promptListBool(reader, "Do you have an "+
		"existing wallet seed you want to use?", "no")
	if err != nil {
		return nil, false, err
	}
	if !useUserSeed {
		seed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen)
		if err != nil {
			return nil, false, err
		}
		seedStrSplit := walletseed.EncodeMnemonicSlice(seed)
		fmt.Println("Your wallet generation seed is:")
		for i := 0; i < hdkeychain.RecommendedSeedLen+1; i++ {
			fmt.Printf("%v ", seedStrSplit[i])
			if (i+1)%6 == 0 {
				fmt.Printf("\n")
			}
		}
		fmt.Printf("\n\nHex: %x\n", seed)
		fmt.Println("IMPORTANT: Keep the seed in a safe place as you\n" +
			"will NOT be able to restore your wallet without it.")
		fmt.Println("Please keep in mind that anyone who has access\n" +
			"to the seed can also restore your wallet thereby\n" +
			"giving them access to all your funds, so it is\n" +
			"imperative that you keep it in a secure location.")
		for {
			fmt.Print(`Once you have stored the seed in a safe ` +
				`and secure location, enter "OK" to continue: `)
			confirmSeed, err := reader.ReadString('\n')
			if err != nil {
				return nil, false, err
			}
			confirmSeed = strings.TrimSpace(confirmSeed)
			confirmSeed = strings.Trim(confirmSeed, `"`)
			if strings.EqualFold("OK", confirmSeed) {
				break
			}
		}
		return seed, false, nil
	}
	for {
		fmt.Print("Enter existing wallet seed " +
			"(followed by a blank line): ")
		// Use scanner instead of buffio.Reader so we can choose choose
		// more complicated ending condition rather than just a single
		// newline.
		var seedStr string
		scanner := bufio.NewScanner(reader)
		for scanner.Scan() {
			line := scanner.Text()
			if line == "" {
				break
			}
			seedStr += " " + line
		}
		seedStrTrimmed := strings.TrimSpace(seedStr)
		seedStrTrimmed = collapseSpace(seedStrTrimmed)
		wordCount := strings.Count(seedStrTrimmed, " ") + 1
		var seed []byte
		if wordCount == 1 {
			if len(seedStrTrimmed)%2 != 0 {
				seedStrTrimmed = "0" + seedStrTrimmed
			}
			seed, err = hex.DecodeString(seedStrTrimmed)
			if err != nil {
				fmt.Printf("Input error: %v\n", err.Error())
			}
		} else {
			seed, err = walletseed.DecodeUserInput(seedStrTrimmed)
			if err != nil {
				fmt.Printf("Input error: %v\n", err.Error())
			}
		}
		if err != nil || len(seed) < hdkeychain.MinSeedBytes ||
			len(seed) > hdkeychain.MaxSeedBytes {
			fmt.Printf("Invalid seed specified.  Must be a "+
				"word seed (usually 33 words) using the PGP wordlist or "+
				"hexadecimal value that is at least %d bits and "+
				"at most %d bits\n", hdkeychain.MinSeedBytes*8,
				hdkeychain.MaxSeedBytes*8)
			continue
		}
		fmt.Printf("\nSeed input successful. \nHex: %x\n", seed)
		return seed, true, nil
	}
}
Seed prompts the user whether they want to use an existing wallet generation
seed.  When the user answers no, a seed will be generated and displayed to
the user along with prompting them for confirmation.  When the user answers
yes, a the user is prompted for it.  All prompts are repeated until the user
enters a valid response. The bool returned indicates if the wallet was
restored from a given seed or not.
package prompt
import (
	"bufio"
	"bytes"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"strings"
	"unicode"
	"decred.org/dcrwallet/v2/errors"
	"decred.org/dcrwallet/v2/walletseed"
	"github.com/decred/dcrd/hdkeychain/v3"
	"golang.org/x/crypto/ssh/terminal"
)
func ProvideSeed() ([]byte, error) {
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Print("Enter existing wallet seed: ")
		seedStr, err := reader.ReadString('\n')
		if err != nil {
			return nil, err
		}
		seedStr = strings.TrimSpace(strings.ToLower(seedStr))
		seed, err := hex.DecodeString(seedStr)
		if err != nil || len(seed) < hdkeychain.MinSeedBytes ||
			len(seed) > hdkeychain.MaxSeedBytes {
			fmt.Printf("Invalid seed specified.  Must be a "+
				"hexadecimal value that is at least %d bits and "+
				"at most %d bits\n", hdkeychain.MinSeedBytes*8,
				hdkeychain.MaxSeedBytes*8)
			continue
		}
		return seed, nil
	}
}
func ProvidePrivPassphrase() ([]byte, error) {
	prompt := "Enter the private passphrase of your wallet: "
	for {
		fmt.Print(prompt)
		pass, err := terminal.ReadPassword(int(os.Stdin.Fd()))
		if err != nil {
			return nil, err
		}
		fmt.Print("\n")
		pass = bytes.TrimSpace(pass)
		if len(pass) == 0 {
			continue
		}
		return pass, nil
	}
}
func promptList(reader *bufio.Reader, prefix string, validResponses []string, defaultEntry string) (string, error) {
	validStrings := strings.Join(validResponses, "/")
	var prompt string
	if defaultEntry != "" {
		prompt = fmt.Sprintf("%s (%s) [%s]: ", prefix, validStrings,
			defaultEntry)
	} else {
		prompt = fmt.Sprintf("%s (%s): ", prefix, validStrings)
	}
	for {
		fmt.Print(prompt)
		reply, err := reader.ReadString('\n')
		if err != nil {
			return "", err
		}
		reply = strings.TrimSpace(strings.ToLower(reply))
		if reply == "" {
			reply = defaultEntry
		}
		for _, validResponse := range validResponses {
			if reply == validResponse {
				return reply, nil
			}
		}
	}
}
func promptListBool(reader *bufio.Reader, prefix string, defaultEntry string) (bool, error) {
	valid := []string{"n", "no", "y", "yes"}
	response, err := promptList(reader, prefix, valid, defaultEntry)
	if err != nil {
		return false, err
	}
	return response == "yes" || response == "y", nil
}
func PassPrompt(reader *bufio.Reader, prefix string, confirm bool) ([]byte, error) {
	prompt := fmt.Sprintf("%s: ", prefix)
	for {
		fmt.Print(prompt)
		var pass []byte
		var err error
		fd := int(os.Stdin.Fd())
		if terminal.IsTerminal(fd) {
			pass, err = terminal.ReadPassword(fd)
		} else {
			pass, err = reader.ReadBytes('\n')
			if errors.Is(err, io.EOF) {
				err = nil
			}
		}
		if err != nil {
			return nil, err
		}
		fmt.Print("\n")
		pass = bytes.TrimSpace(pass)
		if len(pass) == 0 {
			continue
		}
		if !confirm {
			return pass, nil
		}
		fmt.Print("Confirm passphrase: ")
		confirm, err := terminal.ReadPassword(int(os.Stdin.Fd()))
		if err != nil {
			return nil, err
		}
		fmt.Print("\n")
		confirm = bytes.TrimSpace(confirm)
		if !bytes.Equal(pass, confirm) {
			fmt.Println("The entered passphrases do not match")
			continue
		}
		return pass, nil
	}
}
func PrivatePass(reader *bufio.Reader, configPass []byte) ([]byte, error) {
	if len(configPass) > 0 {
		useExisting, err := promptListBool(reader, "Use the "+
			"existing configured private passphrase for "+
			"wallet encryption?", "no")
		if err != nil {
			return nil, err
		}
		if useExisting {
			return configPass, nil
		}
	}
	return PassPrompt(reader, "Enter the private passphrase for your new wallet", true)
}
func PublicPass(reader *bufio.Reader, privPass []byte,
	defaultPubPassphrase, configPubPass []byte) ([]byte, error) {
	pubPass := defaultPubPassphrase
	usePubPass, err := promptListBool(reader, "Do you want "+
		"to add an additional layer of encryption for public "+
		"data?", "no")
	if err != nil {
		return nil, err
	}
	if !usePubPass {
		return pubPass, nil
	}
	if len(configPubPass) != 0 && !bytes.Equal(configPubPass, pubPass) {
		useExisting, err := promptListBool(reader, "Use the "+
			"existing configured public passphrase for encryption "+
			"of public data?", "no")
		if err != nil {
			return nil, err
		}
		if useExisting {
			return configPubPass, nil
		}
	}
	for {
		pubPass, err = PassPrompt(reader, "Enter the public "+
			"passphrase for your new wallet", true)
		if err != nil {
			return nil, err
		}
		if bytes.Equal(pubPass, privPass) {
			useSamePass, err := promptListBool(reader,
				"Are you sure want to use the same passphrase "+
					"for public and private data?", "no")
			if err != nil {
				return nil, err
			}
			if useSamePass {
				break
			}
			continue
		}
		break
	}
	fmt.Println("NOTE: Use the --walletpass option to configure your " +
		"public passphrase.")
	return pubPass, nil
}