new cli
This commit is contained in:
parent
0b583ec97b
commit
665b39e330
|
@ -1,55 +1,160 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"os"
|
||||||
|
|
||||||
"github.com/tendermint/abci/server"
|
"github.com/urfave/cli"
|
||||||
"github.com/tendermint/basecoin/app"
|
)
|
||||||
cmn "github.com/tendermint/go-common"
|
|
||||||
eyes "github.com/tendermint/merkleeyes/client"
|
// start flags
|
||||||
|
var (
|
||||||
|
addrFlag = cli.StringFlag{
|
||||||
|
Name: "address",
|
||||||
|
Value: "tcp://0.0.0.0:46658",
|
||||||
|
Usage: "Listen address",
|
||||||
|
}
|
||||||
|
|
||||||
|
eyesFlag = cli.StringFlag{
|
||||||
|
Name: "eyes",
|
||||||
|
Value: "local",
|
||||||
|
Usage: "MerkleEyes address, or 'local' for embedded",
|
||||||
|
}
|
||||||
|
|
||||||
|
eyesDBFlag = cli.StringFlag{
|
||||||
|
Name: "eyes-db",
|
||||||
|
Value: "merkleeyes.db",
|
||||||
|
Usage: "MerkleEyes db name for embedded",
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move to config file
|
||||||
|
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
||||||
|
|
||||||
|
genesisFlag = cli.StringFlag{
|
||||||
|
Name: "genesis",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Path to genesis file, if it exists",
|
||||||
|
}
|
||||||
|
|
||||||
|
inProcTMFlag = cli.BoolFlag{
|
||||||
|
Name: "in-proc",
|
||||||
|
Usage: "Run Tendermint in-process with the App",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// tx flags
|
||||||
|
|
||||||
|
var (
|
||||||
|
toFlag = cli.StringFlag{
|
||||||
|
Name: "to",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Destination address for the transaction",
|
||||||
|
}
|
||||||
|
|
||||||
|
amountFlag = cli.IntFlag{
|
||||||
|
Name: "amount",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "Amount of coins to send in the transaction",
|
||||||
|
}
|
||||||
|
|
||||||
|
fromFlag = cli.StringFlag{
|
||||||
|
Name: "from",
|
||||||
|
Value: "priv_validator.json",
|
||||||
|
Usage: "Path to a private key to sign the transaction",
|
||||||
|
}
|
||||||
|
|
||||||
|
seqFlag = cli.IntFlag{
|
||||||
|
Name: "sequence",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "Sequence number for the account",
|
||||||
|
}
|
||||||
|
|
||||||
|
coinFlag = cli.StringFlag{
|
||||||
|
Name: "coin",
|
||||||
|
Value: "blank",
|
||||||
|
Usage: "Specify a coin denomination",
|
||||||
|
}
|
||||||
|
|
||||||
|
gasFlag = cli.IntFlag{
|
||||||
|
Name: "gas",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "The amount of gas for the transaction",
|
||||||
|
}
|
||||||
|
|
||||||
|
feeFlag = cli.IntFlag{
|
||||||
|
Name: "fee",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "The transaction fee",
|
||||||
|
}
|
||||||
|
|
||||||
|
dataFlag = cli.StringFlag{
|
||||||
|
Name: "data",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Data to send with the transaction",
|
||||||
|
}
|
||||||
|
|
||||||
|
nameFlag = cli.StringFlag{
|
||||||
|
Name: "name",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Plugin to send the transaction to",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
addrPtr := flag.String("address", "tcp://0.0.0.0:46658", "Listen address")
|
app := cli.NewApp()
|
||||||
eyesPtr := flag.String("eyes", "local", "MerkleEyes address, or 'local' for embedded")
|
app.Name = "basecoin"
|
||||||
eyesDBNamePtr := flag.String("eyes-db-name", "local.db", "MerkleEyes db name, for embedded")
|
app.Usage = "basecoin [command] [args...]"
|
||||||
eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
app.Version = "0.1.0"
|
||||||
genFilePath := flag.String("genesis", "", "Genesis file, if any")
|
app.Commands = []cli.Command{
|
||||||
flag.Parse()
|
{
|
||||||
|
Name: "start",
|
||||||
|
Usage: "Start basecoin",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return cmdStart(c)
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
addrFlag,
|
||||||
|
eyesFlag,
|
||||||
|
eyesDBFlag,
|
||||||
|
genesisFlag,
|
||||||
|
inProcTMFlag,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// Connect to MerkleEyes
|
{
|
||||||
var eyesCli *eyes.Client
|
Name: "sendtx",
|
||||||
if *eyesPtr == "local" {
|
Usage: "Broadcast a basecoin SendTx",
|
||||||
eyesCli = eyes.NewLocalClient(*eyesDBNamePtr, *eyesCacheSizePtr)
|
ArgsUsage: "",
|
||||||
} else {
|
Action: func(c *cli.Context) error {
|
||||||
var err error
|
return cmdSendTx(c)
|
||||||
eyesCli, err = eyes.NewClient(*eyesPtr)
|
},
|
||||||
if err != nil {
|
Flags: []cli.Flag{
|
||||||
cmn.Exit("connect to MerkleEyes: " + err.Error())
|
toFlag,
|
||||||
}
|
fromFlag,
|
||||||
|
amountFlag,
|
||||||
|
coinFlag,
|
||||||
|
gasFlag,
|
||||||
|
feeFlag,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
Name: "apptx",
|
||||||
|
Usage: "Broadcast a basecoin AppTx",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return cmdAppTx(c)
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
nameFlag,
|
||||||
|
fromFlag,
|
||||||
|
amountFlag,
|
||||||
|
coinFlag,
|
||||||
|
gasFlag,
|
||||||
|
feeFlag,
|
||||||
|
dataFlag,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
app.Run(os.Args)
|
||||||
// Create Basecoin app
|
|
||||||
app := app.NewBasecoin(eyesCli)
|
|
||||||
|
|
||||||
// If genesis file was specified, set key-value options
|
|
||||||
if *genFilePath != "" {
|
|
||||||
err := app.LoadGenesis(*genFilePath)
|
|
||||||
if err != nil {
|
|
||||||
cmn.Exit(cmn.Fmt("%+v", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the listener
|
|
||||||
svr, err := server.NewServer(*addrPtr, "socket", app)
|
|
||||||
if err != nil {
|
|
||||||
cmn.Exit("create listener: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait forever
|
|
||||||
cmn.TrapSignal(func() {
|
|
||||||
// Cleanup
|
|
||||||
svr.Stop()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
|
"github.com/tendermint/abci/server"
|
||||||
|
"github.com/tendermint/basecoin/app"
|
||||||
|
cmn "github.com/tendermint/go-common"
|
||||||
|
eyes "github.com/tendermint/merkleeyes/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
const EyesCacheSize = 10000
|
||||||
|
|
||||||
|
func cmdStart(c *cli.Context) error {
|
||||||
|
|
||||||
|
// Connect to MerkleEyes
|
||||||
|
var eyesCli *eyes.Client
|
||||||
|
if c.String("eyes") == "local" {
|
||||||
|
eyesCli = eyes.NewLocalClient(c.String("eyes-db"), EyesCacheSize)
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
eyesCli, err = eyes.NewClient(c.String("eyes"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("connect to MerkleEyes: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Basecoin app
|
||||||
|
app := app.NewBasecoin(eyesCli)
|
||||||
|
|
||||||
|
// If genesis file was specified, set key-value options
|
||||||
|
if c.String("genesis") != "" {
|
||||||
|
err := app.LoadGenesis(c.String("genesis"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(cmn.Fmt("%+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the listener
|
||||||
|
svr, err := server.NewServer(c.String("address"), "socket", app)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("create listener: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
cmn.TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
svr.Stop()
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
|
"github.com/tendermint/basecoin/types"
|
||||||
|
cmn "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/go-wire"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cmdSendTx(c *cli.Context) error {
|
||||||
|
toHex := c.String("to")
|
||||||
|
fromFile := c.String("from")
|
||||||
|
amount := int64(c.Int("amount"))
|
||||||
|
coin := c.String("coin")
|
||||||
|
gas, fee := c.Int("gas"), int64(c.Int("fee"))
|
||||||
|
chainID := c.String("chain_id")
|
||||||
|
|
||||||
|
to, err := hex.DecodeString(toHex)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("To address is invalid hex: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
privVal := tmtypes.LoadPrivValidator(fromFile)
|
||||||
|
|
||||||
|
sequence := getSeq(c)
|
||||||
|
|
||||||
|
input := types.NewTxInput(privVal.PubKey, types.Coins{types.Coin{coin, amount}}, sequence)
|
||||||
|
output := newOutput(to, coin, amount)
|
||||||
|
|
||||||
|
tx := types.SendTx{
|
||||||
|
Gas: int64(gas),
|
||||||
|
Fee: types.Coin{coin, fee},
|
||||||
|
Inputs: []types.TxInput{input},
|
||||||
|
Outputs: []types.TxOutput{output},
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Inputs[0].Signature = privVal.Sign(tx.SignBytes(chainID))
|
||||||
|
fmt.Println(string(wire.JSONBytes(tx)))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdAppTx(c *cli.Context) error {
|
||||||
|
name := c.String("name")
|
||||||
|
fromFile := c.String("from")
|
||||||
|
amount := int64(c.Int("amount"))
|
||||||
|
coin := c.String("coin")
|
||||||
|
gas, fee := c.Int("gas"), int64(c.Int("fee"))
|
||||||
|
chainID := c.String("chain_id")
|
||||||
|
dataString := c.String("data")
|
||||||
|
|
||||||
|
data := []byte(dataString)
|
||||||
|
if cmn.IsHex(dataString) {
|
||||||
|
data, _ = hex.DecodeString(dataString)
|
||||||
|
}
|
||||||
|
|
||||||
|
privVal := tmtypes.LoadPrivValidator(fromFile)
|
||||||
|
|
||||||
|
sequence := getSeq(c)
|
||||||
|
|
||||||
|
input := types.NewTxInput(privVal.PubKey, types.Coins{types.Coin{coin, amount}}, sequence)
|
||||||
|
|
||||||
|
tx := types.AppTx{
|
||||||
|
Gas: int64(gas),
|
||||||
|
Fee: types.Coin{coin, fee},
|
||||||
|
Name: name,
|
||||||
|
Input: input,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Input.Signature = privVal.Sign(tx.SignBytes(chainID))
|
||||||
|
fmt.Println(string(wire.JSONBytes(tx)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSeq(c *cli.Context) int {
|
||||||
|
if c.IsSet("sequence") {
|
||||||
|
return c.Int("sequence")
|
||||||
|
}
|
||||||
|
// TODO: get from query
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOutput(to []byte, coin string, amount int64) types.TxOutput {
|
||||||
|
return types.TxOutput{
|
||||||
|
Address: to,
|
||||||
|
Coins: types.Coins{
|
||||||
|
types.Coin{
|
||||||
|
Denom: coin,
|
||||||
|
Amount: amount,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue