diff --git a/app/context.go b/app/context.go index eb8f29a947..4e882be76e 100644 --- a/app/context.go +++ b/app/context.go @@ -16,6 +16,7 @@ import ( "strings" ) +//TODO 以后需要重构,现在有点乱 type Context struct { context.CLIContext txCtx txcxt.TxContext @@ -38,6 +39,7 @@ func (c Context) GetTxCxt() txcxt.TxContext { func (c Context) WithCodeC(cdc *wire.Codec) Context { c.Cdc = cdc + c.CLIContext = c.CLIContext.WithCodec(cdc) return c } func (c Context) WithCLIContext(ctx context.CLIContext) Context { diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 60fee24137..c1f23f84a4 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -658,7 +658,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk if app.feePreprocessHandler != nil { err := app.feePreprocessHandler(ctx, tx) if err != nil { - sdk.ErrInvalidCoins(err.Error()).Result() + return sdk.ErrInvalidCoins(err.Error()).Result() } } diff --git a/client/cli/auth/query.go b/client/cli/auth/query.go new file mode 100644 index 0000000000..99ccaa8b36 --- /dev/null +++ b/client/cli/auth/query.go @@ -0,0 +1,81 @@ +package auth + +import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/irisnet/irishub/app" + "github.com/spf13/cobra" + "github.com/tendermint/tendermint/crypto" + "github.com/irisnet/irishub/types" +) + +// GetAccountCmd returns a query account that will display the state of the +// account at a given address. +func GetAccountCmd(storeName string, cdc *wire.Codec, decoder auth.AccountDecoder) *cobra.Command { + return &cobra.Command{ + Use: "account [address]", + Short: "Query account balance", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + // find the key to look up the account + addr := args[0] + + key, err := sdk.AccAddressFromBech32(addr) + if err != nil { + return err + } + + ctx := app.NewContext() + cliCtx := ctx.WithCodec(cdc). + WithAccountDecoder(decoder) + if err := cliCtx.EnsureAccountExistsFromAddr(key); err != nil { + return err + } + + acc, err := cliCtx.GetAccount(key) + if err != nil { + return err + } + + coins := acc.GetCoins() + var coins_str []string + for _, coin := range coins { + coinName ,_ := types.GetCoinName(coin.String()) + ct, err := ctx.GetCoinType(coinName) + if err != nil { + return err + } + mainCoin, err := ct.Convert(coin.String(), ct.Name) + if err != nil { + return err + } + coins_str = append(coins_str, mainCoin) + } + acct := account{ + Address: acc.GetAddress(), + Coins: coins_str, + PubKey: acc.GetPubKey(), + AccountNumber: acc.GetAccountNumber(), + Sequence: acc.GetSequence(), + } + + output, err := wire.MarshalJSONIndent(cdc, acct) + if err != nil { + return err + } + + fmt.Println(string(output)) + return nil + }, + } +} + +type account struct { + Address sdk.AccAddress `json:"address"` + Coins []string `json:"coins"` + PubKey crypto.PubKey `json:"public_key"` + AccountNumber int64 `json:"account_number"` + Sequence int64 `json:"sequence"` +} diff --git a/client/cli/coin/tx.go b/client/cli/coin/tx.go new file mode 100644 index 0000000000..187c7f10f1 --- /dev/null +++ b/client/cli/coin/tx.go @@ -0,0 +1,32 @@ +package coin + +import ( + "github.com/cosmos/cosmos-sdk/wire" + "github.com/spf13/cobra" + "fmt" + "github.com/irisnet/irishub/app" +) + +func GetCmdQueryCoinType(cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "types [coin_name]", + Short: "query coin_type", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := app.NewContext().WithCodeC(cdc) + res , err := ctx.GetCoinType(args[0]) + if err != nil { + return err + } + output, err := wire.MarshalJSONIndent(cdc, res) + if err != nil { + return err + } + + fmt.Println(string(output)) + return nil + }, + } + + return cmd +} \ No newline at end of file diff --git a/client/cli/gov/tx.go b/client/cli/gov/tx.go index 3787139733..b869399a47 100644 --- a/client/cli/gov/tx.go +++ b/client/cli/gov/tx.go @@ -406,3 +406,39 @@ func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { return cmd } + +func GetCmdQueryConfig(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "query-params", + Short: "query parameter proposal's config", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := app.NewContext().WithCodeC(cdc) + res , err := ctx.QuerySubspace([]byte(gov.Prefix),storeName) + + var kvs []KvPair + for _,kv := range res { + var v string + cdc.UnmarshalBinary(kv.Value, &v) + kv := KvPair{ + K: string(kv.Key), + V: v, + } + kvs = append(kvs, kv) + } + output, err := wire.MarshalJSONIndent(cdc, kvs) + if err != nil { + return err + } + + fmt.Println(string(output)) + return nil + }, + } + + return cmd +} + +type KvPair struct { + K string `json:"key"` + V string `json:"value"` +} diff --git a/cmd/iriscli/main.go b/cmd/iriscli/main.go index 2a8be29294..fd3c465ef1 100644 --- a/cmd/iriscli/main.go +++ b/cmd/iriscli/main.go @@ -19,6 +19,8 @@ import ( govcmd "github.com/irisnet/irishub/client/cli/gov" upgradecmd "github.com/irisnet/irishub/client/cli/upgrade" "github.com/irisnet/irishub/version" + "github.com/irisnet/irishub/client/cli/coin" + "github.com/irisnet/irishub/client/cli/auth" ) // rootCmd is the entry point for this binary @@ -111,7 +113,10 @@ func main() { govCmd.AddCommand( client.GetCommands( govcmd.GetCmdQueryProposal("gov", cdc), + govcmd.GetCmdQueryProposals("gov", cdc), govcmd.GetCmdQueryVote("gov", cdc), + govcmd.GetCmdQueryVotes("gov", cdc), + govcmd.GetCmdQueryConfig("iparams", cdc), )...) govCmd.AddCommand( client.PostCommands( @@ -144,7 +149,7 @@ func main() { //Add auth and bank commands rootCmd.AddCommand( client.GetCommands( - authcmd.GetAccountCmd("acc", cdc, authcmd.GetAccountDecoder(cdc)), + auth.GetAccountCmd("acc", cdc, authcmd.GetAccountDecoder(cdc)), )...) rootCmd.AddCommand( client.PostCommands( @@ -161,12 +166,16 @@ func main() { version.GetCmdVersion("upgrade", cdc), )...) - paramsCmd := &cobra.Command{ - Use: "params", - Short: "Governance and voting subcommands", + coinCmd := &cobra.Command{ + Use: "coin", + Short: "Coin and CoinType", } + coinCmd.AddCommand( + client.GetCommands( + coin.GetCmdQueryCoinType(cdc), + )...) - rootCmd.AddCommand(paramsCmd) + rootCmd.AddCommand(coinCmd) // prepare and add flags executor := cli.PrepareMainCmd(rootCmd, "GA", app.DefaultCLIHome) diff --git a/docs/modules/coin/coin_type.md b/docs/modules/coin/coin_type.md new file mode 100644 index 0000000000..40ff01187e --- /dev/null +++ b/docs/modules/coin/coin_type.md @@ -0,0 +1,37 @@ +# Coin_Type的定义 +coin_type 定义了iris-hub系统中代币的可用单位,只要是系统中已注册的coin_type类型,都可以使用该单位来进行交易。iris-hub中系统默认的代币为iris,iris存在以下几种可用单位:iris-milli,iris-micro,iris-nano,iris-pico,iris-femto,iris-atto。他们之间存在以下换算关系 +``` +1 iris = 10^3 iris-milli +1 iris = 10^6 iris-micro +1 iris = 10^9 iris-nano +1 iris = 10^12 iris-pico +1 iris = 10^15 iris-femto +1 iris = 10^18 iris-atto +``` +coin_type的数据模型如下: +```golang +type CoinType struct { + Name string `json:"name"` + MinUnit Unit `json:"min_unit"` + Units Units `json:"units"` + Origin Origin `json:"origin"` + Desc string `json:"desc"` +} +``` +* Name : 代币名称,也是coin的主单位,例如iris +* MinUnit: coin_type的最小单位,系统中存在的代币都是以最小单位的形式存在,例如iris代币,在iris-hub中存储的单位是iris-atto。当用户发送交易到iris-hub中,使用的必须是该代币的最小单位。但是如果你使用的是iris-hub提供的命令行工具,你可以使用任何系统识别的单位,系统将自动转化为该代币对应的最小单位形式。比如如果你使用send命令转移1iris,命令行将在后端处理为10^18 iris-atto,使用交易hash查询到的交易详情,你也只会看到10^18 iris-atto。Unit结构定义如下: +```golang +type Unit struct { + Denom string `json:"denom"` + Decimal int `json:"decimal"` +} +``` +其中Denom定义为该单位的名称,Decimal定义为该单位支持的最大精度,例如iris-atto支持的最大精度为18 +* Units:定义了coin_type下可用的一组单位 +* Origin:定义了该coin_type的来源,取值:Native(系统内部,iris),External(系统外部,例如eth等),UserIssued(用户自定义) +* Desc:对该代币coin_type的描述 + +如果想查询某种代币的coin_type配置,可以使用如下命令 +```golang +iriscli coin types [coin_name] +``` \ No newline at end of file diff --git a/modules/gov/endblocker_test.go b/modules/gov/endblocker_test.go index 9dd241aabd..e028848d74 100644 --- a/modules/gov/endblocker_test.go +++ b/modules/gov/endblocker_test.go @@ -19,7 +19,7 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.Nil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)}) + newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)},Params{}) res := govHandler(ctx, newProposalMsg) require.True(t, res.IsOK()) @@ -50,7 +50,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.Nil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)}) + newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)},Params{}) res := govHandler(ctx, newProposalMsg) require.True(t, res.IsOK()) @@ -64,7 +64,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)}) + newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)},Params{}) res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) @@ -94,7 +94,7 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) require.False(t, shouldPopActiveProposalQueue(ctx, keeper)) - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)}) + newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)},Params{}) res := govHandler(ctx, newProposalMsg) require.True(t, res.IsOK()) @@ -139,7 +139,7 @@ func TestTickPassedVotingPeriod(t *testing.T) { require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) require.False(t, shouldPopActiveProposalQueue(ctx, keeper)) - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)}) + newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)},Params{}) res := govHandler(ctx, newProposalMsg) require.True(t, res.IsOK()) @@ -185,7 +185,7 @@ func TestSlashing(t *testing.T) { val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(initTotalPower) val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[2]).GetPower().Quo(initTotalPower) - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 15)}) + newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 15)},Params{}) res := govHandler(ctx, newProposalMsg) require.True(t, res.IsOK())