github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/crypto/keys/client/send.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  
     8  	"github.com/gnolang/gno/tm2/pkg/amino"
     9  	"github.com/gnolang/gno/tm2/pkg/commands"
    10  	"github.com/gnolang/gno/tm2/pkg/crypto"
    11  	"github.com/gnolang/gno/tm2/pkg/crypto/keys"
    12  	"github.com/gnolang/gno/tm2/pkg/errors"
    13  	"github.com/gnolang/gno/tm2/pkg/sdk/bank"
    14  	"github.com/gnolang/gno/tm2/pkg/std"
    15  )
    16  
    17  type MakeSendCfg struct {
    18  	RootCfg *MakeTxCfg
    19  
    20  	Send string
    21  	To   string
    22  }
    23  
    24  func NewMakeSendCmd(rootCfg *MakeTxCfg, io commands.IO) *commands.Command {
    25  	cfg := &MakeSendCfg{
    26  		RootCfg: rootCfg,
    27  	}
    28  
    29  	return commands.NewCommand(
    30  		commands.Metadata{
    31  			Name:       "send",
    32  			ShortUsage: "send [flags] <key-name or address>",
    33  			ShortHelp:  "sends native currency",
    34  		},
    35  		cfg,
    36  		func(_ context.Context, args []string) error {
    37  			return execMakeSend(cfg, args, io)
    38  		},
    39  	)
    40  }
    41  
    42  func (c *MakeSendCfg) RegisterFlags(fs *flag.FlagSet) {
    43  	fs.StringVar(
    44  		&c.Send,
    45  		"send",
    46  		"",
    47  		"send amount",
    48  	)
    49  
    50  	fs.StringVar(
    51  		&c.To,
    52  		"to",
    53  		"",
    54  		"destination address",
    55  	)
    56  }
    57  
    58  func execMakeSend(cfg *MakeSendCfg, args []string, io commands.IO) error {
    59  	if len(args) != 1 {
    60  		return flag.ErrHelp
    61  	}
    62  
    63  	if cfg.RootCfg.GasWanted == 0 {
    64  		return errors.New("gas-wanted not specified")
    65  	}
    66  	if cfg.RootCfg.GasFee == "" {
    67  		return errors.New("gas-fee not specified")
    68  	}
    69  	if cfg.Send == "" {
    70  		return errors.New("send (amount) must be specified")
    71  	}
    72  	if cfg.To == "" {
    73  		return errors.New("to (destination address) must be specified")
    74  	}
    75  
    76  	// read account pubkey.
    77  	nameOrBech32 := args[0]
    78  	kb, err := keys.NewKeyBaseFromDir(cfg.RootCfg.RootCfg.Home)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	info, err := kb.GetByNameOrAddress(nameOrBech32)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	fromAddr := info.GetAddress()
    87  	// info.GetPubKey()
    88  
    89  	// Parse to address.
    90  	toAddr, err := crypto.AddressFromBech32(cfg.To)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	// Parse send amount.
    96  	send, err := std.ParseCoins(cfg.Send)
    97  	if err != nil {
    98  		return errors.Wrap(err, "parsing send coins")
    99  	}
   100  
   101  	// parse gas wanted & fee.
   102  	gaswanted := cfg.RootCfg.GasWanted
   103  	gasfee, err := std.ParseCoin(cfg.RootCfg.GasFee)
   104  	if err != nil {
   105  		return errors.Wrap(err, "parsing gas fee coin")
   106  	}
   107  
   108  	// construct msg & tx and marshal.
   109  	msg := bank.MsgSend{
   110  		FromAddress: fromAddr,
   111  		ToAddress:   toAddr,
   112  		Amount:      send,
   113  	}
   114  	tx := std.Tx{
   115  		Msgs:       []std.Msg{msg},
   116  		Fee:        std.NewFee(gaswanted, gasfee),
   117  		Signatures: nil,
   118  		Memo:       cfg.RootCfg.Memo,
   119  	}
   120  
   121  	if cfg.RootCfg.Broadcast {
   122  		err := ExecSignAndBroadcast(cfg.RootCfg, args, tx, io)
   123  		if err != nil {
   124  			return err
   125  		}
   126  	} else {
   127  		fmt.Println(string(amino.MustMarshalJSON(tx)))
   128  	}
   129  	return nil
   130  }