func getChangeAddress(wltFile string, a string, c *gcli.Context) (string, error) { chgAddr := c.String("c") for { if chgAddr == "" { // get the default wallet's coin base address if a != "" { // use the from address as change address chgAddr = a break } if wltFile != "" { wlt, err := wallet.Load(wltFile) if err != nil { return "", err } if len(wlt.Entries) > 0 { chgAddr = wlt.Entries[0].Address.String() break } return "", errors.New("no change address was found") } return "", errors.New("both wallet file, from address and change address are empty") } break } // validate the address _, err := cipher.DecodeBase58Address(chgAddr) if err != nil { return "", fmt.Errorf("invalid change address: %s", chgAddr) } return chgAddr, nil }
func getAddresses(f string) ([]string, error) { wlt, err := wallet.Load(f) if err != nil { return nil, err } addrs := make([]string, len(wlt.Entries)) for i, entry := range wlt.Entries { addrs[i] = entry.Address.String() } return addrs, nil }
func gatherAddrs(c *gcli.Context) ([]string, error) { w := c.String("f") var a string if c.NArg() > 0 { a = c.Args().First() if _, err := cipher.DecodeBase58Address(a); err != nil { return []string{}, fmt.Errorf("invalid address: %v", a) } } addrs := []string{} if w == "" && a == "" { // use default wallet w = filepath.Join(cfg.WalletDir, cfg.DefaultWalletName) } if w != "" { if !strings.HasSuffix(w, walletExt) { return []string{}, fmt.Errorf("error wallet file name, must has %v extension", walletExt) } if filepath.Base(w) == w { w = filepath.Join(cfg.WalletDir, w) } else { var err error w, err = filepath.Abs(w) if err != nil { return []string{}, err } } wlt, err := wallet.Load(w) if err != nil { return []string{}, err } addresses := wlt.GetAddresses() for _, a := range addresses { addrs = append(addrs, a.String()) } } if a != "" { addrs = append(addrs, a) } return addrs, nil }
func listWalletsCMD() gcli.Command { name := "listWallets" return gcli.Command{ Name: name, Usage: "Lists all wallets stored in the default wallet directory", ArgsUsage: " ", OnUsageError: onCommandUsageError(name), Action: func(c *gcli.Context) error { var wlts struct { Wallets []walletEntry `json:"wallets"` } entries, err := ioutil.ReadDir(cfg.WalletDir) if err != nil { return err } for _, e := range entries { if e.Mode().IsRegular() { name := e.Name() if !strings.HasSuffix(name, walletExt) { continue } path := filepath.Join(cfg.WalletDir, name) w, err := wallet.Load(path) if err != nil { return err } wlts.Wallets = append(wlts.Wallets, walletEntry{ Name: name, Label: w.GetLabel(), AddressNum: len(w.Entries), }) } } d, err := json.MarshalIndent(wlts, "", " ") if err != nil { return errJSONMarshal } fmt.Println(string(d)) return nil }, } // Commands = append(Commands, cmd) }
func generateAddrs(c *gcli.Context) error { // get number of address that are need to be generated. num := c.Uint("n") if num == 0 { return errors.New("-n must > 0") } jsonFmt := c.Bool("json") w := c.String("f") if !strings.HasSuffix(w, walletExt) { return errWalletName } // only wallet file name, no path. if filepath.Base(w) == w { w = filepath.Join(cfg.WalletDir, w) } wlt, err := wallet.Load(w) if err != nil { errorWithHelp(c, err) return nil } addrs := wlt.GenerateAddresses(int(num)) dir, err := filepath.Abs(filepath.Dir(w)) if err != nil { return err } if err := wlt.Save(dir); err != nil { return errors.New("save wallet failed") } s, err := addrResult(addrs, jsonFmt) if err != nil { return err } fmt.Println(s) return nil }
func createRawTxFromAddress(addr string, chgAddr string, toAddr string, amt uint64) (string, error) { if (amt % 1e6) != 0 { return "", errors.New("skycoin coins must be multiple of 1e6") } // check if the address is in the default wallet. wlt, err := wallet.Load(filepath.Join(cfg.WalletDir, cfg.DefaultWalletName)) if err != nil { return "", err } srcAddr, err := cipher.DecodeBase58Address(addr) if err != nil { return "", errAddress } _, ok := wlt.GetEntry(srcAddr) if !ok { return "", fmt.Errorf("%v address is not in wallet", addr) } // validate change address cAddr, err := cipher.DecodeBase58Address(chgAddr) if err != nil { return "", errAddress } // validate to address _, err = cipher.DecodeBase58Address(toAddr) if err != nil { return "", errAddress } _, ok = wlt.GetEntry(cAddr) if !ok { return "", fmt.Errorf("change address %v is not in wallet", chgAddr) } return makeTx([]string{addr}, chgAddr, toAddr, amt, wlt) }
func listAddresses(c *gcli.Context) error { // get wallet name w := c.Args().First() if w == "" { w = filepath.Join(cfg.WalletDir, cfg.DefaultWalletName) } if !strings.HasSuffix(w, walletExt) { return errWalletName } if filepath.Base(w) == w { w = filepath.Join(cfg.WalletDir, w) } wlt, err := wallet.Load(w) if err != nil { return err } addrs := wlt.GetAddresses() var rlt = struct { Addresses []string `json:"addresses"` }{ make([]string, len(addrs)), } for i, a := range addrs { rlt.Addresses[i] = a.String() } d, err := json.MarshalIndent(rlt, "", " ") if err != nil { return errors.New("json marshal failed") } fmt.Println(string(d)) return nil }
func createRawTxFromWallet(wltPath string, chgAddr string, toAddr string, amt uint64) (string, error) { // validate the amt if (amt % 1e6) != 0 { return "", errors.New("skycoin coins must be multiple of 1e6") } // check if the change address is in wallet. wlt, err := wallet.Load(wltPath) if err != nil { return "", err } // check change address cAddr, err := cipher.DecodeBase58Address(chgAddr) if err != nil { return "", errAddress } // validate to address _, err = cipher.DecodeBase58Address(toAddr) if err != nil { return "", errAddress } _, ok := wlt.GetEntry(cAddr) if !ok { return "", fmt.Errorf("change address %v is not in wallet", chgAddr) } // get all address in the wallet totalAddrs := wlt.GetAddresses() addrStrArray := make([]string, len(totalAddrs)) for i, a := range totalAddrs { addrStrArray[i] = a.String() } return makeTx(addrStrArray, chgAddr, toAddr, amt, wlt) }
func addPrivateKeyCMD() gcli.Command { name := "addPrivateKey" return gcli.Command{ Name: name, Usage: "Add a private key to specific wallet", ArgsUsage: "[private key]", Description: fmt.Sprintf(`Add a private key to specific wallet, the default wallet(%s/%s) will be used if the wallet file or path is not specified`, cfg.WalletDir, cfg.DefaultWalletName), Flags: []gcli.Flag{ gcli.StringFlag{ Name: "f", Usage: "[wallet file or path] private key will be added to this wallet", }, }, OnUsageError: onCommandUsageError(name), Action: func(c *gcli.Context) error { // get private key skStr := c.Args().First() if skStr == "" { gcli.ShowSubcommandHelp(c) return nil } // get wallet file path w := c.String("f") if w == "" { w = filepath.Join(cfg.WalletDir, cfg.DefaultWalletName) } if !strings.HasSuffix(w, walletExt) { return errWalletName } // only wallet file name, no path. if filepath.Base(w) == w { w = filepath.Join(cfg.WalletDir, w) } wlt, err := wallet.Load(w) if err != nil { errorWithHelp(c, err) return nil } sk, err := cipher.SecKeyFromHex(skStr) if err != nil { return fmt.Errorf("invalid private key: %s, must be an hex string of length 64", skStr) } pk := cipher.PubKeyFromSecKey(sk) addr := cipher.AddressFromPubKey(pk) entry := wallet.WalletEntry{ Address: addr, Public: pk, Secret: sk, } if err := wlt.AddEntry(entry); err != nil { return err } dir, err := filepath.Abs(filepath.Dir(w)) if err != nil { return err } if err := wlt.Save(dir); err != nil { return errors.New("save wallet failed") } fmt.Println("success") return nil }, } // Commands = append(Commands, cmd) }