Imported basecli wholesale
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
flag "github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
btypes "github.com/tendermint/basecoin/types"
|
||||
keycmd "github.com/tendermint/go-crypto/cmd"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
lightclient "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/light-client/commands"
|
||||
"github.com/tendermint/light-client/proofs"
|
||||
)
|
||||
|
||||
type AccountPresenter struct{}
|
||||
|
||||
func (_ AccountPresenter) MakeKey(str string) ([]byte, error) {
|
||||
res, err := hex.DecodeString(str)
|
||||
if err == nil {
|
||||
res = append([]byte("base/a/"), res...)
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (_ AccountPresenter) ParseData(raw []byte) (interface{}, error) {
|
||||
var acc *btypes.Account
|
||||
err := wire.ReadBinaryBytes(raw, &acc)
|
||||
return acc, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// SendTXReader allows us to create SendTx
|
||||
type SendTxReader struct {
|
||||
ChainID string
|
||||
}
|
||||
|
||||
func (t SendTxReader) ReadTxJSON(data []byte) (interface{}, error) {
|
||||
var tx btypes.SendTx
|
||||
err := json.Unmarshal(data, &tx)
|
||||
send := SendTx{
|
||||
chainID: t.ChainID,
|
||||
Tx: &tx,
|
||||
}
|
||||
return &send, errors.Wrap(err, "parse 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("foobar", 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", "", "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{}
|
||||
}
|
||||
|
||||
func (t SendTxReader) ReadTxFlags(flags interface{}) (interface{}, error) {
|
||||
data := flags.(*SendFlags)
|
||||
|
||||
// parse to and from addresses
|
||||
to, err := hex.DecodeString(StripHex(data.To))
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("To address is invalid hex: %v\n", err)
|
||||
}
|
||||
|
||||
// TODO: figure out a cleaner way to do this... until then
|
||||
// just close your eyes and continue...
|
||||
manager := keycmd.GetKeyManager()
|
||||
name := viper.GetString("name")
|
||||
info, err := manager.Get(name)
|
||||
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := btypes.ParseCoin(data.Fee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amountCoins, err := btypes.ParseCoins(data.Amount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// craft the tx
|
||||
input := btypes.TxInput{
|
||||
Address: info.Address,
|
||||
Coins: amountCoins,
|
||||
Sequence: data.Sequence,
|
||||
}
|
||||
if data.Sequence == 1 {
|
||||
input.PubKey = info.PubKey
|
||||
}
|
||||
output := 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
|
||||
}
|
||||
|
||||
/** copied from basecoin cli - put in common somewhere? **/
|
||||
|
||||
// Returns true for non-empty hex-string prefixed with "0x"
|
||||
func isHex(s string) bool {
|
||||
if len(s) > 2 && s[:2] == "0x" {
|
||||
_, err := hex.DecodeString(s[2:])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func StripHex(s string) string {
|
||||
if isHex(s) {
|
||||
return s[2:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
keycmd "github.com/tendermint/go-crypto/cmd"
|
||||
"github.com/tendermint/light-client/commands"
|
||||
"github.com/tendermint/light-client/commands/proofs"
|
||||
"github.com/tendermint/light-client/commands/seeds"
|
||||
"github.com/tendermint/light-client/commands/txs"
|
||||
)
|
||||
|
||||
// BaseCli represents the base command when called without any subcommands
|
||||
var BaseCli = &cobra.Command{
|
||||
Use: "basecli",
|
||||
Short: "Light client for tendermint",
|
||||
Long: `Basecli is an version of tmcli including custom logic to
|
||||
present a nice (not raw hex) interface to the basecoin blockchain structure.
|
||||
|
||||
This is a useful tool, but also serves to demonstrate how one can configure
|
||||
tmcli to work for any custom abci app.
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
commands.AddBasicFlags(BaseCli)
|
||||
|
||||
// set up the various commands to use
|
||||
BaseCli.AddCommand(keycmd.RootCmd)
|
||||
BaseCli.AddCommand(commands.InitCmd)
|
||||
BaseCli.AddCommand(seeds.RootCmd)
|
||||
proofs.StatePresenters.Register("account", AccountPresenter{})
|
||||
proofs.TxPresenters.Register("base", BaseTxPresenter{})
|
||||
BaseCli.AddCommand(proofs.RootCmd)
|
||||
txs.Register("send", SendTxMaker{})
|
||||
BaseCli.AddCommand(txs.RootCmd)
|
||||
}
|
||||
|
||||
func main() {
|
||||
keycmd.PrepareMainCmd(BaseCli, "BC", os.ExpandEnv("$HOME/.basecli"))
|
||||
BaseCli.Execute()
|
||||
// err := BaseCli.Execute()
|
||||
// if err != nil {
|
||||
// fmt.Printf("%+v\n", err)
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
bc "github.com/tendermint/basecoin/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
keys "github.com/tendermint/go-crypto/keys"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
type SendTx struct {
|
||||
chainID string
|
||||
signers []crypto.PubKey
|
||||
Tx *bc.SendTx
|
||||
}
|
||||
|
||||
var _ keys.Signable = &SendTx{}
|
||||
|
||||
// SignBytes returned the unsigned bytes, needing a signature
|
||||
func (s *SendTx) SignBytes() []byte {
|
||||
return s.Tx.SignBytes(s.chainID)
|
||||
}
|
||||
|
||||
// Sign will add a signature and pubkey.
|
||||
//
|
||||
// Depending on the Signable, one may be able to call this multiple times for multisig
|
||||
// Returns error if called with invalid data or too many times
|
||||
func (s *SendTx) Sign(pubkey crypto.PubKey, sig crypto.Signature) error {
|
||||
addr := pubkey.Address()
|
||||
set := s.Tx.SetSignature(addr, sig)
|
||||
if !set {
|
||||
return errors.Errorf("Cannot add signature for address %X", addr)
|
||||
}
|
||||
s.signers = append(s.signers, pubkey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Signers will return the public key(s) that signed if the signature
|
||||
// is valid, or an error if there is any issue with the signature,
|
||||
// including if there are no signatures
|
||||
func (s *SendTx) Signers() ([]crypto.PubKey, error) {
|
||||
if len(s.signers) == 0 {
|
||||
return nil, errors.New("No signatures on SendTx")
|
||||
}
|
||||
return s.signers, nil
|
||||
}
|
||||
|
||||
// TxBytes returns the transaction data as well as all signatures
|
||||
// It should return an error if Sign was never called
|
||||
func (s *SendTx) TxBytes() ([]byte, error) {
|
||||
// TODO: verify it is signed
|
||||
|
||||
// Code and comment from: basecoin/cmd/commands/tx.go
|
||||
// Don't you hate having to do this?
|
||||
// How many times have I lost an hour over this trick?!
|
||||
txBytes := wire.BinaryBytes(struct {
|
||||
bc.Tx `json:"unwrap"`
|
||||
}{s.Tx})
|
||||
return txBytes, nil
|
||||
}
|
||||
Reference in New Issue
Block a user