-
Notifications
You must be signed in to change notification settings - Fork 0
/
accounts.go
85 lines (67 loc) · 2.21 KB
/
accounts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package commands
import (
"encoding/hex"
"fmt"
"regexp"
"strings"
"github.com/spf13/cobra"
"github.com/lantah/go/exp/crypto/derivation"
"github.com/lantah/go/keypair"
"github.com/lantah/go/support/errors"
"github.com/tyler-smith/go-bip39"
)
var wordsRegexp = regexp.MustCompile(`^[a-z]+$`)
var count, startID uint32
var allowedNumbers = map[uint32]bool{12: true, 15: true, 18: true, 21: true, 24: true}
var AccountsCmd = &cobra.Command{
Use: "accounts",
Short: "Display accounts for a given mnemonic code",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
printf("How many words? ")
wordsCount := readUint()
if _, exist := allowedNumbers[wordsCount]; !exist {
return errors.New("Invalid value, allowed values: 12, 15, 18, 21, 24")
}
words := make([]string, wordsCount)
for i := uint32(0); i < wordsCount; i++ {
printf("Enter word #%-4d", i+1)
words[i] = readString()
if !wordsRegexp.MatchString(words[i]) {
println("Invalid word, try again.")
i--
}
}
printf("Enter password (leave empty if none): ")
password := readString()
mnemonic := strings.Join(words, " ")
println("Mnemonic:", mnemonic)
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, password)
if err != nil {
return errors.New("Invalid words or checksum")
}
println("BIP39 Seed:", hex.EncodeToString(seed))
masterKey, err := derivation.DeriveForPath(derivation.StellarAccountPrefix, seed)
if err != nil {
return errors.Wrap(err, "Error deriving master key")
}
println("m/44'/148' key:", hex.EncodeToString(masterKey.Key))
println("")
for i := uint32(startID); i < startID+count; i++ {
key, err := masterKey.Derive(derivation.FirstHardenedIndex + i)
if err != nil {
return errors.Wrap(err, "Error deriving child key")
}
kp, err := keypair.FromRawSeed(key.RawSeed())
if err != nil {
return errors.Wrap(err, "Error creating key pair")
}
println(fmt.Sprintf(derivation.StellarAccountPathFormat, i), kp.Address(), kp.Seed())
}
return nil
},
}
func init() {
AccountsCmd.Flags().Uint32VarP(&count, "count", "c", 10, "number of accounts to display")
AccountsCmd.Flags().Uint32VarP(&startID, "start", "s", 0, "ID of the first wallet to display")
}