From 131130b7a4f03fb8b22e46db84bdc2a1934018e7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 3 Mar 2018 17:30:08 +0000 Subject: [PATCH] basecoin upgrade without CLI --- examples/basecoin/app/app.go | 20 ++--- examples/basecoin/x/cool/handler.go | 57 ++++++++++++ examples/basecoin/x/cool/mapper.go | 30 +++++++ examples/basecoin/x/cool/types.go | 103 ++++++++++++++++++++++ examples/basecoin/x/coolmodule/handler.go | 64 -------------- examples/basecoin/x/coolmodule/types.go | 92 ------------------- x/bank/tx.go | 2 +- 7 files changed, 200 insertions(+), 168 deletions(-) create mode 100644 examples/basecoin/x/cool/handler.go create mode 100644 examples/basecoin/x/cool/mapper.go create mode 100644 examples/basecoin/x/cool/types.go delete mode 100644 examples/basecoin/x/coolmodule/handler.go delete mode 100644 examples/basecoin/x/coolmodule/types.go diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 420e0632f9..4f1cb2fb0f 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" + "github.com/cosmos/cosmos-sdk/examples/basecoin/x/cool" "github.com/cosmos/cosmos-sdk/examples/basecoin/x/sketchy" ) @@ -53,8 +54,10 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { // add handlers coinKeeper := bank.NewCoinKeeper(app.accountMapper) + coolMapper := cool.NewMapper(app.capKeyMainStore) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). + AddRoute("cool", cool.NewHandler(coinKeeper, coolMapper)). AddRoute("sketchy", sketchy.NewHandler()) // initialize BaseApp @@ -73,39 +76,34 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { } // custom tx codec +// TODO: use new go-wire func MakeCodec() *wire.Codec { - // XXX: Using old wire for now :) - const ( - msgTypeSend = 0x1 - msgTypeIssue = 0x2 - ) + const msgTypeSend = 0x1 + const msgTypeIssue = 0x2 var _ = oldwire.RegisterInterface( struct{ sdk.Msg }{}, oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend}, oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue}, ) - const ( - accTypeApp = 0x1 - ) + const accTypeApp = 0x1 var _ = oldwire.RegisterInterface( struct{ sdk.Account }{}, oldwire.ConcreteType{&types.AppAccount{}, accTypeApp}, ) - cdc := wire.NewCodec() - // TODO: use new go-wire + // cdc.RegisterInterface((*sdk.Msg)(nil), nil) // bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types. // crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types. return cdc - } // custom logic for transaction decoding func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { var tx = sdk.StdTx{} + // StdTx.Msg is an interface. The concrete types // are registered by MakeTxCodec in bank.RegisterWire. err := app.cdc.UnmarshalBinary(txBytes, &tx) diff --git a/examples/basecoin/x/cool/handler.go b/examples/basecoin/x/cool/handler.go new file mode 100644 index 0000000000..152ae2f339 --- /dev/null +++ b/examples/basecoin/x/cool/handler.go @@ -0,0 +1,57 @@ +package cool + +import ( + "fmt" + "reflect" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" +) + +// This is just an example to demonstrate a functional custom module +// with full feature set functionality. +// +// /$$$$$$$ /$$$$$$ /$$$$$$ /$$ +// /$$_____/ /$$__ $$ /$$__ $$| $$ +//| $$ | $$ \ $$| $$ \ $$| $$ +//| $$ | $$ | $$| $$ | $$| $$ +//| $$$$$$$| $$$$$$/| $$$$$$/| $$$$$$$ +// \_______/ \______/ \______/ |______/ + +// Handle all "coolmodule" type objects +func NewHandler(ck bank.CoinKeeper, cm Mapper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case SetWhatCoolMsg: + return handleSetWhatCoolMsg(ctx, cm, msg) + case WhatCoolMsg: + return handleWhatCoolMsg(ctx, ck, cm, msg) + default: + errMsg := fmt.Sprintf("Unrecognized cool Msg type: %v", reflect.TypeOf(msg).Name()) + return sdk.ErrUnknownRequest(errMsg).Result() + } + } +} + +// Handle WhatCoolMsg This is the engine of your module +func handleSetWhatCoolMsg(ctx sdk.Context, cm Mapper, msg SetWhatCoolMsg) sdk.Result { + cm.SetWhatCool(ctx, msg.WhatCool) + return sdk.Result{} +} + +// Handle WhatCoolMsg This is the engine of your module +func handleWhatCoolMsg(ctx sdk.Context, ck bank.CoinKeeper, cm Mapper, msg WhatCoolMsg) sdk.Result { + + whatsCool := cm.GetWhatCool(ctx) + + if msg.CoolerThanCool == whatsCool { + + bonusCoins := sdk.Coins{{whatsCool, 69}} + _, err := ck.AddCoins(ctx, msg.Sender, bonusCoins) + if err != nil { + return err.Result() + } + } + + return sdk.Result{} +} diff --git a/examples/basecoin/x/cool/mapper.go b/examples/basecoin/x/cool/mapper.go new file mode 100644 index 0000000000..f437f8ca43 --- /dev/null +++ b/examples/basecoin/x/cool/mapper.go @@ -0,0 +1,30 @@ +package cool + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// This Cool Mapper handlers sets/gets of custom variables for your module +type Mapper struct { + key sdk.StoreKey // The (unexposed) key used to access the store from the Context. +} + +func NewMapper(key sdk.StoreKey) Mapper { + return Mapper{key} +} + +// Key to knowing whats cool +var whatCoolKey = []byte("WhatsCoolKey") + +// Implements sdk.AccountMapper. +func (am Mapper) GetWhatCool(ctx sdk.Context) string { + store := ctx.KVStore(am.key) + bz := store.Get(whatCoolKey) + return string(bz) +} + +// Implements sdk.AccountMapper. +func (am Mapper) SetWhatCool(ctx sdk.Context, whatscool string) { + store := ctx.KVStore(am.key) + store.Set(whatCoolKey, []byte(whatscool)) +} diff --git a/examples/basecoin/x/cool/types.go b/examples/basecoin/x/cool/types.go new file mode 100644 index 0000000000..872afe7f8a --- /dev/null +++ b/examples/basecoin/x/cool/types.go @@ -0,0 +1,103 @@ +package cool + +import ( + "encoding/json" + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// A really cool msg type, these fields are can be entirely arbitrary and +// custom to your message +type SetWhatCoolMsg struct { + Sender sdk.Address + WhatCool string +} + +// New cool message +func NewSetWhatCoolMsg(sender sdk.Address, whatcool string) SetWhatCoolMsg { + return SetWhatCoolMsg{ + Sender: sender, + WhatCool: whatcool, + } +} + +// enforce the msg type at compile time +var _ sdk.Msg = SetWhatCoolMsg{} + +// nolint +func (msg SetWhatCoolMsg) Type() string { return "cool" } +func (msg SetWhatCoolMsg) Get(key interface{}) (value interface{}) { return nil } +func (msg SetWhatCoolMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } +func (msg SetWhatCoolMsg) String() string { + return fmt.Sprintf("SetWhatCoolMsg{Sender: %v, WhatCool: %v}", msg.Sender, msg.WhatCool) +} + +// Validate Basic is used to quickly disqualify obviously invalid messages quickly +func (msg SetWhatCoolMsg) ValidateBasic() sdk.Error { + if len(msg.Sender) == 0 { + return sdk.ErrUnrecognizedAddress(msg.Sender).Trace("") + } + if strings.Contains(msg.WhatCool, "hot") { + return sdk.ErrUnauthorized("").Trace("hot is not cool") + } + if strings.Contains(msg.WhatCool, "warm") { + return sdk.ErrUnauthorized("").Trace("warm is not very cool") + } + return nil +} + +// Get the bytes for the message signer to sign on +func (msg SetWhatCoolMsg) GetSignBytes() []byte { + b, err := json.Marshal(msg) + if err != nil { + panic(err) + } + return b +} + +//_______________________________________________________________________ + +// A really cool msg type, these fields are can be entirely arbitrary and +// custom to your message +type WhatCoolMsg struct { + Sender sdk.Address + CoolerThanCool string +} + +// New cool message +func NewWhatCoolMsg(sender sdk.Address, coolerthancool string) WhatCoolMsg { + return WhatCoolMsg{ + Sender: sender, + CoolerThanCool: coolerthancool, + } +} + +// enforce the msg type at compile time +var _ sdk.Msg = WhatCoolMsg{} + +// nolint +func (msg WhatCoolMsg) Type() string { return "cool" } +func (msg WhatCoolMsg) Get(key interface{}) (value interface{}) { return nil } +func (msg WhatCoolMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } +func (msg WhatCoolMsg) String() string { + return fmt.Sprintf("WhatCoolMsg{Sender: %v, CoolerThanCool: %v}", msg.Sender, msg.CoolerThanCool) +} + +// Validate Basic is used to quickly disqualify obviously invalid messages quickly +func (msg WhatCoolMsg) ValidateBasic() sdk.Error { + if len(msg.Sender) == 0 { + return sdk.ErrUnrecognizedAddress(msg.Sender).Trace("") + } + return nil +} + +// Get the bytes for the message signer to sign on +func (msg WhatCoolMsg) GetSignBytes() []byte { + b, err := json.Marshal(msg) + if err != nil { + panic(err) + } + return b +} diff --git a/examples/basecoin/x/coolmodule/handler.go b/examples/basecoin/x/coolmodule/handler.go deleted file mode 100644 index 615d91bb8d..0000000000 --- a/examples/basecoin/x/coolmodule/handler.go +++ /dev/null @@ -1,64 +0,0 @@ -package coolmodule - -import ( - "reflect" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank" -) - -// This is just an example to demonstrate a functional custom module -// with full feature set functionality. -// -// /$$$$$$$ /$$$$$$ /$$$$$$ /$$ -// /$$_____/ /$$__ $$ /$$__ $$| $$ -//| $$ | $$ \ $$| $$ \ $$| $$ -//| $$ | $$ | $$| $$ | $$| $$ -//| $$$$$$$| $$$$$$/| $$$$$$/| $$$$$$$ -// \_______/ \______/ \______/ |______/ - -// Handle all "coolmodule" type objects -func NewHandler(ck bank.CoinKeeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - switch msg := msg.(type) { - case CoolMsg: - return handleCoolMsg(ctx, ck, msg) - case CoolerThanCoolMsg: - return handleMeltMsg(ctx, ck, msg) - default: - errMsg := "Unrecognized bank Msg type: " + reflect.TypeOf(msg).Name() - return sdk.ErrUnknownRequest(errMsg).Result() - } - } -} - -// Handle CoolMsg This is the engine of your module -func handleCoolMsg(ctx sdk.Context, ck CoinKeeper, msg CoolMsg) sdk.Result { - - if msg.coolerthancool == "icecold" { - - bonusCoins := sdk.Coins{{"icecold", 69}} - _, err := ck.AddCoins(ctx, msg.Address, bonusCoins) - if err != nil { - return err.Result() - } - } - - return sdk.Result{} -} - -// Handle CoolMsg This is the engine of your module -func handleMeltMsg(ctx sdk.Context, ck CoinKeeper, msg CoolMsg) sdk.Result { - - // checks for existence should already have occured - if strings.Prefix(msg.what, "ice") { - return bank.ErrInvalidInput("only frozen coins can use the blow dryer") - } - - bonusCoins := sdk.Coins{{"icecold", 69}} - _, err := ck.SubtractCoins(ctx, msg.Address, bonusCoins) - if err != nil { - return err.Result() - } - return sdk.Result{} -} diff --git a/examples/basecoin/x/coolmodule/types.go b/examples/basecoin/x/coolmodule/types.go deleted file mode 100644 index 62be2d49a4..0000000000 --- a/examples/basecoin/x/coolmodule/types.go +++ /dev/null @@ -1,92 +0,0 @@ -package coolmodule - -import ( - "encoding/json" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// A really cool msg type, these fields are can be entirely arbitrary and -// custom to your message -type CoolMsg struct { - Sender sdk.Address - Coolerthancool string -} - -// New cool message -func NewCoolMsg(sender sdk.Address, coolerthancool string) CoolMsg { - return CoolMsg{ - Sender: sender, - Coolerthancool: coolerthancool, - } -} - -// enforce the msg type at compile time -var _ CoolMsg = sdk.Msg - -// nolint -func (msg CoolMsg) Type() string { return "cool" } -func (msg CoolMsg) Get(key interface{}) (value interface{}) { return nil } -func (msg CoolMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } -func (msg CoolMsg) String() string { return fmt.Sprintf("CoolMsg{%v}", msg) } - -// Validate Basic is used to quickly disqualify obviously invalid messages quickly -func (msg CoolMsg) ValidateBasic() sdk.Error { - if msg.Signer.Empty() { - return ErrNoOutputs().Trace("") - } - return nil -} - -// Get the bytes for the message signer to sign on -func (msg CoolMsg) GetSignBytes() []byte { - b, err := json.Marshal(msg) - if err != nil { - panic(err) - } - return b -} - -//_______________________________________________________________________ - -// A really cool msg type, these fields are can be entirely arbitrary and -// custom to your message -type BlowDryMsg struct { - Sender sdk.Address - What sdk.Coin -} - -// New cool message -func NewBlowDryMsg(sender sdk.Address, what sdk.Coin) BlowDryMsg { - return BlowDryMsg{ - Sender: sender, - What: what, - } -} - -// enforce the msg type at compile time -var _ BlowDryMsg = sdk.Msg - -// nolint -func (msg BlowDryMsg) Type() string { return "cool" } -func (msg BlowDryMsg) Get(key interface{}) (value interface{}) { return nil } -func (msg BlowDryMsg) GetSigners() []sdk.Address { return []sdk.Address{msg.Sender} } -func (msg BlowDryMsg) String() string { return fmt.Sprintf("BlowDryMsg{%v}", msg) } - -// Validate Basic is used to quickly disqualify obviously invalid messages quickly -func (msg BlowDryMsg) ValidateBasic() sdk.Error { - if msg.Signer.Empty() { - return ErrNoOutputs().Trace("") - } - return nil -} - -// Get the bytes for the message signer to sign on -func (msg BlowDryMsg) GetSignBytes() []byte { - b, err := json.Marshal(msg) - if err != nil { - panic(err) - } - return b -} diff --git a/x/bank/tx.go b/x/bank/tx.go index 0f2d15c132..eef2a087d0 100644 --- a/x/bank/tx.go +++ b/x/bank/tx.go @@ -15,7 +15,7 @@ type SendMsg struct { Outputs []Output `json:"outputs"` } -var _ SendMsg = (nil)(sdk.Msg) +var _ sdk.Msg = SendMsg{} // NewSendMsg - construct arbitrary multi-in, multi-out send msg. func NewSendMsg(in []Input, out []Output) SendMsg {