Merge branch 'queryReg' into develop
This commit is contained in:
commit
2728af1f3b
|
@ -41,7 +41,7 @@ This will create the `basecoin` binary in `$GOPATH/bin`.
|
|||
|
||||
The basecoin CLI can be used to start a stand-alone basecoin instance (`basecoin start`),
|
||||
or to start basecoin with Tendermint in the same process (`basecoin start --in-proc`).
|
||||
It can also be used to send transactions, eg. `basecoin tx send --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 100`
|
||||
It can also be used to send transactions, eg. `basecoin tx send --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 100btc,10gold`
|
||||
See `basecoin --help` and `basecoin [cmd] --help` for more details`.
|
||||
|
||||
## Learn more
|
||||
|
|
|
@ -48,10 +48,10 @@ var (
|
|||
Usage: "Destination address for the transaction",
|
||||
}
|
||||
|
||||
AmountFlag = cli.IntFlag{
|
||||
AmountFlag = cli.StringFlag{
|
||||
Name: "amount",
|
||||
Value: 0,
|
||||
Usage: "Amount of coins to send in the transaction",
|
||||
Value: "",
|
||||
Usage: "Coins to send in transaction of the format <amt><coin>,<amt2><coin2>,... (eg: 1btc,2gold,5silver)",
|
||||
}
|
||||
|
||||
FromFlag = cli.StringFlag{
|
||||
|
@ -66,22 +66,16 @@ var (
|
|||
Usage: "Sequence number for the account",
|
||||
}
|
||||
|
||||
CoinFlag = cli.StringFlag{
|
||||
Name: "coin",
|
||||
Value: "mycoin",
|
||||
Usage: "Specify a coin denomination",
|
||||
}
|
||||
|
||||
GasFlag = cli.IntFlag{
|
||||
Name: "gas",
|
||||
Value: 0,
|
||||
Usage: "The amount of gas for the transaction",
|
||||
}
|
||||
|
||||
FeeFlag = cli.IntFlag{
|
||||
FeeFlag = cli.StringFlag{
|
||||
Name: "fee",
|
||||
Value: 0,
|
||||
Usage: "The transaction fee",
|
||||
Value: "",
|
||||
Usage: "Coins for the transaction fee of the format <amt><coin>",
|
||||
}
|
||||
|
||||
DataFlag = cli.StringFlag{
|
||||
|
|
|
@ -66,6 +66,11 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// Register a subcommand of QueryCmd for plugin specific query functionality
|
||||
func RegisterQuerySubcommand(cmd cli.Command) {
|
||||
QueryCmd.Subcommands = append(QueryCmd.Subcommands, cmd)
|
||||
}
|
||||
|
||||
func cmdQuery(c *cli.Context) error {
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.New("query command requires an argument ([key])")
|
||||
|
|
|
@ -23,7 +23,6 @@ var TxFlags = []cli.Flag{
|
|||
FromFlag,
|
||||
|
||||
AmountFlag,
|
||||
CoinFlag,
|
||||
GasFlag,
|
||||
FeeFlag,
|
||||
SeqFlag,
|
||||
|
@ -71,9 +70,9 @@ func RegisterTxSubcommand(cmd cli.Command) {
|
|||
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"))
|
||||
amount := c.String("amount")
|
||||
gas := int64(c.Int("gas"))
|
||||
fee := c.String("fee")
|
||||
chainID := c.String("chain_id")
|
||||
|
||||
// convert destination address to bytes
|
||||
|
@ -91,12 +90,22 @@ func cmdSendTx(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := ParseCoin(fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amountCoins, err := ParseCoins(amount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// craft the tx
|
||||
input := types.NewTxInput(privKey.PubKey, types.Coins{types.Coin{coin, amount}}, sequence)
|
||||
output := newOutput(to, coin, amount)
|
||||
input := types.NewTxInput(privKey.PubKey, amountCoins, sequence)
|
||||
output := newOutput(to, amountCoins)
|
||||
tx := &types.SendTx{
|
||||
Gas: int64(gas),
|
||||
Fee: types.Coin{coin, fee},
|
||||
Gas: gas,
|
||||
Fee: feeCoin,
|
||||
Inputs: []types.TxInput{input},
|
||||
Outputs: []types.TxOutput{output},
|
||||
}
|
||||
|
@ -128,9 +137,9 @@ func cmdAppTx(c *cli.Context) error {
|
|||
|
||||
func AppTx(c *cli.Context, name string, data []byte) error {
|
||||
fromFile := c.String("from")
|
||||
amount := int64(c.Int("amount"))
|
||||
coin := c.String("coin")
|
||||
gas, fee := c.Int("gas"), int64(c.Int("fee"))
|
||||
amount := c.String("amount")
|
||||
fee := c.String("fee")
|
||||
gas := int64(c.Int("gas"))
|
||||
chainID := c.String("chain_id")
|
||||
|
||||
privKey := tmtypes.LoadPrivValidator(fromFile)
|
||||
|
@ -140,10 +149,20 @@ func AppTx(c *cli.Context, name string, data []byte) error {
|
|||
return err
|
||||
}
|
||||
|
||||
input := types.NewTxInput(privKey.PubKey, types.Coins{types.Coin{coin, amount}}, sequence)
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := ParseCoin(fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amountCoins, err := ParseCoins(amount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
input := types.NewTxInput(privKey.PubKey, amountCoins, sequence)
|
||||
tx := &types.AppTx{
|
||||
Gas: int64(gas),
|
||||
Fee: types.Coin{coin, fee},
|
||||
Gas: gas,
|
||||
Fee: feeCoin,
|
||||
Name: name,
|
||||
Input: input,
|
||||
Data: data,
|
||||
|
@ -205,15 +224,10 @@ func getSeq(c *cli.Context, address []byte) (int, error) {
|
|||
return acc.Sequence + 1, nil
|
||||
}
|
||||
|
||||
func newOutput(to []byte, coin string, amount int64) types.TxOutput {
|
||||
func newOutput(to []byte, amount types.Coins) types.TxOutput {
|
||||
return types.TxOutput{
|
||||
Address: to,
|
||||
Coins: types.Coins{
|
||||
types.Coin{
|
||||
Denom: coin,
|
||||
Amount: amount,
|
||||
},
|
||||
},
|
||||
Coins: amount,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@ package commands
|
|||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
|
@ -35,6 +39,44 @@ func StripHex(s string) string {
|
|||
return s
|
||||
}
|
||||
|
||||
//regex codes for extracting coins from CLI input
|
||||
var reDenom = regexp.MustCompile("([^\\d\\W]+)")
|
||||
var reAmt = regexp.MustCompile("(\\d+)")
|
||||
|
||||
func ParseCoin(str string) (types.Coin, error) {
|
||||
|
||||
var coin types.Coin
|
||||
|
||||
if len(str) > 0 {
|
||||
amt, err := strconv.Atoi(reAmt.FindString(str))
|
||||
if err != nil {
|
||||
return coin, err
|
||||
}
|
||||
denom := reDenom.FindString(str)
|
||||
coin = types.Coin{denom, int64(amt)}
|
||||
}
|
||||
|
||||
return coin, nil
|
||||
}
|
||||
|
||||
func ParseCoins(str string) (types.Coins, error) {
|
||||
|
||||
split := strings.Split(str, ",")
|
||||
var coins []types.Coin
|
||||
|
||||
for _, el := range split {
|
||||
if len(el) > 0 {
|
||||
coin, err := ParseCoin(el)
|
||||
if err != nil {
|
||||
return coins, err
|
||||
}
|
||||
coins = append(coins, coin)
|
||||
}
|
||||
}
|
||||
|
||||
return coins, nil
|
||||
}
|
||||
|
||||
func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) {
|
||||
clientURI := client.NewClientURI(tmAddr)
|
||||
tmResult := new(ctypes.TMResult)
|
||||
|
@ -58,7 +100,7 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) {
|
|||
// fetch the account by querying the app
|
||||
func getAcc(tmAddr string, address []byte) (*types.Account, error) {
|
||||
|
||||
key := append([]byte("base/a/"), address...)
|
||||
key := state.AccountKey(address)
|
||||
response, err := Query(tmAddr, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
//Test the parse coin and parse coins functionality
|
||||
func TestParse(t *testing.T) {
|
||||
|
||||
makeCoin := func(str string) types.Coin {
|
||||
coin, err := ParseCoin(str)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return coin
|
||||
}
|
||||
|
||||
makeCoins := func(str string) types.Coins {
|
||||
coin, err := ParseCoins(str)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return coin
|
||||
}
|
||||
|
||||
//testing ParseCoin Function
|
||||
assert.True(t, types.Coin{} == makeCoin(""), "parseCoin makes bad empty coin")
|
||||
assert.True(t, types.Coin{"fooCoin", 1} == makeCoin("1fooCoin"), "parseCoin makes bad coins")
|
||||
assert.True(t, types.Coin{"barCoin", 10} == makeCoin("10 barCoin"), "parseCoin makes bad coins")
|
||||
|
||||
//testing ParseCoins Function
|
||||
assert.True(t, types.Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), "parseCoins doesn't parse a single coin")
|
||||
assert.True(t, types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")),
|
||||
"parseCoins doesn't properly parse two coins")
|
||||
assert.True(t, types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")),
|
||||
"parseCoins doesn't properly parse two coins which use spaces")
|
||||
}
|
|
@ -95,14 +95,14 @@ The first account is flush with cash, while the second account doesn't exist.
|
|||
Let's send funds from the first account to the second:
|
||||
|
||||
```
|
||||
basecoin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 10
|
||||
basecoin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 10mycoin
|
||||
```
|
||||
|
||||
By default, the CLI looks for a `priv_validator.json` to sign the transaction with,
|
||||
so this will only work if you are in the `$GOPATH/src/github.com/tendermint/basecoin/data`.
|
||||
To specify a different key, we can use the `--from` flag.
|
||||
|
||||
Now if we check the second account, it should have `10` coins!
|
||||
Now if we check the second account, it should have `10` 'mycoin' coins!
|
||||
|
||||
```
|
||||
basecoin account 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090
|
||||
|
@ -111,7 +111,7 @@ basecoin account 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090
|
|||
We can send some of these coins back like so:
|
||||
|
||||
```
|
||||
basecoin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --from key2.json --amount 5
|
||||
basecoin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --from key2.json --amount 5mycoin
|
||||
```
|
||||
|
||||
Note how we use the `--from` flag to select a different account to send from.
|
||||
|
@ -119,7 +119,7 @@ Note how we use the `--from` flag to select a different account to send from.
|
|||
If we try to send too much, we'll get an error:
|
||||
|
||||
```
|
||||
basecoin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --from key2.json --amount 100
|
||||
basecoin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --from key2.json --amount 100mycoin
|
||||
```
|
||||
|
||||
See `basecoin tx send --help` for additional details.
|
||||
|
|
|
@ -132,10 +132,9 @@ OPTIONS:
|
|||
--node value Tendermint RPC address (default: "tcp://localhost:46657")
|
||||
--chain_id value ID of the chain for replay protection (default: "test_chain_id")
|
||||
--from value Path to a private key to sign the transaction (default: "key.json")
|
||||
--amount value Amount of coins to send in the transaction (default: 0)
|
||||
--coin value Specify a coin denomination (default: "mycoin")
|
||||
--amount value Coins to send in transaction of the format <amt><coin>,<amt2><coin2>,... (eg: 1btc,2gold,5silver)
|
||||
--gas value The amount of gas for the transaction (default: 0)
|
||||
--fee value The transaction fee (default: 0)
|
||||
--fee value Coins for the transaction fee of the format <amt><coin>
|
||||
--sequence value Sequence number for the account (default: 0)
|
||||
--valid Set this to make the transaction valid
|
||||
```
|
||||
|
@ -366,25 +365,25 @@ example-plugin start --in-proc
|
|||
In another window, we can try sending some transactions:
|
||||
|
||||
```
|
||||
example-plugin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --amount 100 --coin gold --chain_id example-chain
|
||||
example-plugin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --amount 100gold --chain_id example-chain
|
||||
```
|
||||
|
||||
Note the `--coin` and `--chain_id` flags. In the [previous tutorial](basecoin-basics.md),
|
||||
we didn't need them because we were using the default coin type ("mycoin") and chain ID ("test_chain_id").
|
||||
Now that we're using custom values, we need to specify them explicitly on the command line.
|
||||
Note the `--chain_id` flag. In the [previous tutorial](basecoin-basics.md),
|
||||
we didn't include it because we were using the default chain ID ("test_chain_id").
|
||||
Now that we're using a custom chain, we need to specify the chain explicitly on the command line.
|
||||
|
||||
Ok, so that's how we can send a `SendTx` transaction using our `example-plugin` CLI,
|
||||
but we were already able to do that with the `basecoin` CLI.
|
||||
With our new CLI, however, we can also send an `ExamplePluginTx`:
|
||||
|
||||
```
|
||||
example-plugin tx example --amount 1 --coin gold --chain_id example-chain
|
||||
example-plugin tx example --amount 1gold --chain_id example-chain
|
||||
```
|
||||
|
||||
The transaction is invalid! That's because we didn't specify the `--valid` flag:
|
||||
|
||||
```
|
||||
example-plugin tx example --valid --amount 1 --coin gold --chain_id example-chain
|
||||
example-plugin tx example --valid --amount 1gold --chain_id example-chain
|
||||
```
|
||||
|
||||
Tada! We successfuly created, signed, broadcast, and processed our custom transaction type.
|
||||
|
@ -404,7 +403,7 @@ which contains only an integer.
|
|||
If we send another transaction, and then query again, we'll see the value increment:
|
||||
|
||||
```
|
||||
example-plugin tx example --valid --amount 1 --coin gold --chain_id example-chain
|
||||
example-plugin tx example --valid --amount 1gold --chain_id example-chain
|
||||
example-plugin query ExamplePlugin.State
|
||||
```
|
||||
|
||||
|
|
|
@ -231,13 +231,13 @@ export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/key.jso
|
|||
Let's start by registering `test_chain_1` on `test_chain_2`:
|
||||
|
||||
```
|
||||
basecoin tx ibc --amount 10 $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
|
||||
```
|
||||
|
||||
Now we can create the outgoing packet on `test_chain_1`:
|
||||
|
||||
```
|
||||
basecoin tx ibc --amount 10 $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload 0xDEADBEEF --sequence 1
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload 0xDEADBEEF --sequence 1
|
||||
```
|
||||
|
||||
Note our payload is just `DEADBEEF`.
|
||||
|
@ -265,7 +265,7 @@ The former is used as input for later commands; the latter is human-readable, so
|
|||
Let's send this updated information about `test_chain_1` to `test_chain_2`:
|
||||
|
||||
```
|
||||
basecoin tx ibc --amount 10 $CHAIN_FLAGS2 update --header 0x<header>--commit 0x<commit>
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 update --header 0x<header>--commit 0x<commit>
|
||||
```
|
||||
|
||||
where `<header>` and `<commit>` are the hex-encoded header and commit returned by the previous `block` command.
|
||||
|
@ -275,7 +275,7 @@ along with proof the packet was committed on `test_chain_1`. Since `test_chain_2
|
|||
of `test_chain_1`, it will be able to verify the proof!
|
||||
|
||||
```
|
||||
basecoin tx ibc --amount 10 $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height + 1> --packet 0x<packet> --proof 0x<proof>
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height + 1> --packet 0x<packet> --proof 0x<proof>
|
||||
```
|
||||
|
||||
Here, `<height + 1>` is one greater than the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
|
||||
|
|
|
@ -39,7 +39,7 @@ func TestCounterPlugin(t *testing.T) {
|
|||
tx := &types.AppTx{
|
||||
Gas: gas,
|
||||
Fee: fee,
|
||||
Name: "counter",
|
||||
Name: counterPlugin.Name(),
|
||||
Input: types.NewTxInput(test1Acc.PubKey, inputCoins, inputSequence),
|
||||
Data: wire.BinaryBytes(CounterTx{Valid: true, Fee: appFee}),
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ func (coinsA Coins) IsGTE(coinsB Coins) bool {
|
|||
if len(diff) == 0 {
|
||||
return true
|
||||
}
|
||||
return diff.IsPositive()
|
||||
return diff.IsNonnegative()
|
||||
}
|
||||
|
||||
func (coins Coins) IsZero() bool {
|
||||
|
|
Loading…
Reference in New Issue