Port sendtx to new format
This commit is contained in:
parent
65837cf952
commit
66ec2f266c
@ -2,126 +2,104 @@ package commands
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
lightclient "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/light-client/commands"
|
||||
"github.com/tendermint/light-client/proofs"
|
||||
txcmd "github.com/tendermint/light-client/commands/txs"
|
||||
|
||||
btypes "github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
type BaseTxPresenter struct {
|
||||
proofs.RawPresenter // this handles MakeKey as hex bytes
|
||||
/*** Here is the sendtx command ***/
|
||||
|
||||
var SendTxCmd = &cobra.Command{
|
||||
Use: "send",
|
||||
Short: "send tokens from one account to another",
|
||||
RunE: doSendTx,
|
||||
}
|
||||
|
||||
func (_ BaseTxPresenter) ParseData(raw []byte) (interface{}, error) {
|
||||
var tx btypes.TxS
|
||||
err := wire.ReadBinaryBytes(raw, &tx)
|
||||
return tx, err
|
||||
const (
|
||||
ToFlag = "to"
|
||||
AmountFlag = "amount"
|
||||
FeeFlag = "fee"
|
||||
GasFlag = "gas"
|
||||
SequenceFlag = "sequence"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flags := SendTxCmd.Flags()
|
||||
flags.String(ToFlag, "", "Destination address for the bits")
|
||||
flags.String(AmountFlag, "", "Coins to send in the format <amt><coin>,<amt><coin>...")
|
||||
flags.String(FeeFlag, "0mycoin", "Coins for the transaction fee of the format <amt><coin>")
|
||||
flags.Int64(GasFlag, 0, "Amount of gas for this transaction")
|
||||
flags.Int(SequenceFlag, -1, "Sequence number for this transaction")
|
||||
}
|
||||
|
||||
/******** SendTx *********/
|
||||
// runDemo is an example of how to make a tx
|
||||
func doSendTx(cmd *cobra.Command, args []string) error {
|
||||
tx := new(btypes.SendTx)
|
||||
|
||||
type SendTxMaker struct{}
|
||||
|
||||
func (m SendTxMaker) MakeReader() (lightclient.TxReader, error) {
|
||||
chainID := viper.GetString(commands.ChainFlag)
|
||||
return SendTxReader{ChainID: chainID}, nil
|
||||
}
|
||||
|
||||
type SendFlags struct {
|
||||
To string
|
||||
Amount string
|
||||
Fee string
|
||||
Gas int64
|
||||
Sequence int
|
||||
}
|
||||
|
||||
func (m SendTxMaker) Flags() (*flag.FlagSet, interface{}) {
|
||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
|
||||
fs.String("to", "", "Destination address for the bits")
|
||||
fs.String("amount", "", "Coins to send in the format <amt><coin>,<amt><coin>...")
|
||||
fs.String("fee", "0mycoin", "Coins for the transaction fee of the format <amt><coin>")
|
||||
fs.Int64("gas", 0, "Amount of gas for this transaction")
|
||||
fs.Int("sequence", -1, "Sequence number for this transaction")
|
||||
return fs, &SendFlags{}
|
||||
}
|
||||
|
||||
// SendTXReader allows us to create SendTx
|
||||
type SendTxReader struct {
|
||||
ChainID string
|
||||
}
|
||||
|
||||
func (t SendTxReader) ReadTxJSON(data []byte, pk crypto.PubKey) (interface{}, error) {
|
||||
// TODO: use pk info to help construct data
|
||||
var tx btypes.SendTx
|
||||
err := json.Unmarshal(data, &tx)
|
||||
send := SendTx{
|
||||
chainID: t.ChainID,
|
||||
Tx: &tx,
|
||||
// load data from json or flags
|
||||
found, err := txcmd.LoadJSON(tx)
|
||||
if !found {
|
||||
err = readSendTxFlags(tx)
|
||||
}
|
||||
return &send, errors.Wrap(err, "parse sendtx")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
send := &SendTx{
|
||||
chainID: viper.GetString(commands.ChainFlag),
|
||||
Tx: tx,
|
||||
}
|
||||
send.AddSigner(txcmd.GetSigner())
|
||||
|
||||
// Sign if needed and post. This it the work-horse
|
||||
bres, err := txcmd.SignAndPostTx(send)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// output result
|
||||
return txcmd.OutputTx(bres)
|
||||
}
|
||||
|
||||
func (t SendTxReader) ReadTxFlags(flags interface{}, pk crypto.PubKey) (interface{}, error) {
|
||||
data := flags.(*SendFlags)
|
||||
|
||||
// parse to and from addresses
|
||||
to, err := hex.DecodeString(StripHex(data.To))
|
||||
func readSendTxFlags(tx *btypes.SendTx) error {
|
||||
// parse to address
|
||||
to, err := hex.DecodeString(StripHex(viper.GetString(ToFlag)))
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("To address is invalid hex: %v\n", err)
|
||||
return errors.Errorf("To address is invalid hex: %v\n", err)
|
||||
}
|
||||
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := btypes.ParseCoin(data.Fee)
|
||||
tx.Fee, err = btypes.ParseCoin(viper.GetString(FeeFlag))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
amountCoins, err := btypes.ParseCoins(data.Amount)
|
||||
amountCoins, err := btypes.ParseCoins(viper.GetString(AmountFlag))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// get addr if available
|
||||
var addr []byte
|
||||
if !pk.Empty() {
|
||||
addr = pk.Address()
|
||||
}
|
||||
// set the gas
|
||||
tx.Gas = viper.GetInt64(GasFlag)
|
||||
|
||||
// craft the tx
|
||||
input := btypes.TxInput{
|
||||
Address: addr,
|
||||
// craft the inputs and outputs
|
||||
tx.Inputs = []btypes.TxInput{{
|
||||
Coins: amountCoins,
|
||||
Sequence: data.Sequence,
|
||||
}
|
||||
if data.Sequence == 1 {
|
||||
input.PubKey = pk
|
||||
}
|
||||
output := btypes.TxOutput{
|
||||
Sequence: viper.GetInt(SequenceFlag),
|
||||
}}
|
||||
tx.Outputs = []btypes.TxOutput{{
|
||||
Address: to,
|
||||
Coins: amountCoins,
|
||||
}
|
||||
tx := btypes.SendTx{
|
||||
Gas: data.Gas,
|
||||
Fee: feeCoin,
|
||||
Inputs: []btypes.TxInput{input},
|
||||
Outputs: []btypes.TxOutput{output},
|
||||
}
|
||||
}}
|
||||
|
||||
// wrap it in the proper signer thing...
|
||||
send := SendTx{
|
||||
chainID: t.ChainID,
|
||||
Tx: &tx,
|
||||
}
|
||||
return &send, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
/******** AppTx *********/
|
||||
|
||||
@ -41,3 +41,15 @@ func doAccountQuery(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return proofcmd.OutputProof(acc, proof.BlockHeight())
|
||||
}
|
||||
|
||||
/*** this decodes the basecoin tx ***/
|
||||
|
||||
type BaseTxPresenter struct {
|
||||
proofs.RawPresenter // this handles MakeKey as hex bytes
|
||||
}
|
||||
|
||||
func (_ BaseTxPresenter) ParseData(raw []byte) (interface{}, error) {
|
||||
var tx btypes.TxS
|
||||
err := wire.ReadBinaryBytes(raw, &tx)
|
||||
return tx, err
|
||||
}
|
||||
|
||||
@ -58,3 +58,55 @@ func (s *SendTx) TxBytes() ([]byte, error) {
|
||||
}{s.Tx})
|
||||
return txBytes, nil
|
||||
}
|
||||
|
||||
// AddSigner sets address and pubkey info on the tx based on the key that
|
||||
// will be used for signing
|
||||
func (s *SendTx) AddSigner(pk crypto.PubKey) {
|
||||
// get addr if available
|
||||
var addr []byte
|
||||
if !pk.Empty() {
|
||||
addr = pk.Address()
|
||||
}
|
||||
|
||||
// set the send address, and pubkey if needed
|
||||
in := s.Tx.Inputs
|
||||
in[0].Address = addr
|
||||
if in[0].Sequence == 1 {
|
||||
in[0].PubKey = pk
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should really be in the basecoin.types SendTx,
|
||||
// but that code is too ugly now, needs refactor..
|
||||
func (s *SendTx) ValidateBasic() error {
|
||||
if s.chainID == "" {
|
||||
return errors.New("No chainId specified")
|
||||
}
|
||||
for _, in := range s.Tx.Inputs {
|
||||
if len(in.Address) != 20 {
|
||||
return errors.Errorf("Invalid input address length: %d", len(in.Address))
|
||||
}
|
||||
if !in.Coins.IsValid() {
|
||||
return errors.Errorf("Invalid input coins %v", in.Coins)
|
||||
}
|
||||
if in.Coins.IsZero() {
|
||||
return errors.New("Input coins cannot be zero")
|
||||
}
|
||||
if in.Sequence <= 0 {
|
||||
return errors.New("Sequence must be greater than 0")
|
||||
}
|
||||
}
|
||||
for _, out := range s.Tx.Outputs {
|
||||
if len(out.Address) != 20 {
|
||||
return errors.Errorf("Invalid output address length: %d", len(out.Address))
|
||||
}
|
||||
if !out.Coins.IsValid() {
|
||||
return errors.Errorf("Invalid output coins %v", out.Coins)
|
||||
}
|
||||
if out.Coins.IsZero() {
|
||||
return errors.New("Output coins cannot be zero")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -15,19 +15,6 @@ import (
|
||||
btypes "github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
type CounterPresenter struct{}
|
||||
|
||||
func (_ CounterPresenter) MakeKey(str string) ([]byte, error) {
|
||||
key := counter.New().StateKey()
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (_ CounterPresenter) ParseData(raw []byte) (interface{}, error) {
|
||||
var cp counter.CounterPluginState
|
||||
err := wire.ReadBinaryBytes(raw, &cp)
|
||||
return cp, err
|
||||
}
|
||||
|
||||
/**** build out the tx ****/
|
||||
|
||||
var (
|
||||
|
||||
@ -36,3 +36,18 @@ func doCounterQuery(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return proofcmd.OutputProof(cp, proof.BlockHeight())
|
||||
}
|
||||
|
||||
/*** doesn't seem to be needed anymore??? ***/
|
||||
|
||||
// type CounterPresenter struct{}
|
||||
|
||||
// func (_ CounterPresenter) MakeKey(str string) ([]byte, error) {
|
||||
// key := counter.New().StateKey()
|
||||
// return key, nil
|
||||
// }
|
||||
|
||||
// func (_ CounterPresenter) ParseData(raw []byte) (interface{}, error) {
|
||||
// var cp counter.CounterPluginState
|
||||
// err := wire.ReadBinaryBytes(raw, &cp)
|
||||
// return cp, err
|
||||
// }
|
||||
|
||||
@ -14,7 +14,6 @@ import (
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
bcmd "github.com/tendermint/basecoin/cmd/basecli/commands"
|
||||
bcount "github.com/tendermint/basecoin/cmd/basecli/counter"
|
||||
)
|
||||
|
||||
// BaseCli represents the base command when called without any subcommands
|
||||
@ -38,18 +37,18 @@ func main() {
|
||||
pr.AddCommand(proofs.TxCmd)
|
||||
pr.AddCommand(proofs.KeyCmd)
|
||||
pr.AddCommand(bcmd.AccountQueryCmd)
|
||||
pr.AddCommand(bcount.CounterQueryCmd)
|
||||
// pr.AddCommand(bcount.CounterQueryCmd)
|
||||
|
||||
// here is how you would add the custom txs... but don't really add demo in your app
|
||||
proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{})
|
||||
tr := txs.RootCmd
|
||||
// tr.AddCommand(txs.DemoCmd)
|
||||
tr.AddCommand(bcmd.SendTxCmd)
|
||||
// tr.AddCommand(bcmd.AppTxCmd)
|
||||
|
||||
// TODO
|
||||
proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{})
|
||||
//proofs.StatePresenters.Register("counter", bcount.CounterPresenter{})
|
||||
|
||||
txs.Register("send", bcmd.SendTxMaker{})
|
||||
txs.Register("counter", bcount.CounterTxMaker{})
|
||||
// txs.Register("send", bcmd.SendTxMaker{})
|
||||
// txs.Register("counter", bcount.CounterTxMaker{})
|
||||
|
||||
// set up the various commands to use
|
||||
BaseCli.AddCommand(
|
||||
|
||||
2
glide.lock
generated
2
glide.lock
generated
@ -172,7 +172,7 @@ imports:
|
||||
- types
|
||||
- version
|
||||
- name: github.com/tendermint/tmlibs
|
||||
version: 0ecb38c6da95a1e8f60117b2bd4a6f76c7a0f944
|
||||
version: 59a77e7bef092eef0e1f9b44c983dc9e35eed0d6
|
||||
subpackages:
|
||||
- autofile
|
||||
- cli
|
||||
|
||||
Loading…
Reference in New Issue
Block a user