From 6dec9353bed9457b2758bdf1a21e050dbbb63e0d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 2 Mar 2018 17:21:49 +0000 Subject: [PATCH] working new cool module in basecoin --- examples/basecoin/x/coolmodule/handler.go | 64 ++++++++++++++++ examples/basecoin/x/coolmodule/types.go | 92 +++++++++++++++++++++++ types/account.go | 1 + types/tx_msg.go | 4 +- x/bank/tx.go | 14 ++-- x/bank/wire.go | 1 + 6 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 examples/basecoin/x/coolmodule/handler.go create mode 100644 examples/basecoin/x/coolmodule/types.go diff --git a/examples/basecoin/x/coolmodule/handler.go b/examples/basecoin/x/coolmodule/handler.go new file mode 100644 index 0000000000..615d91bb8d --- /dev/null +++ b/examples/basecoin/x/coolmodule/handler.go @@ -0,0 +1,64 @@ +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 new file mode 100644 index 0000000000..62be2d49a4 --- /dev/null +++ b/examples/basecoin/x/coolmodule/types.go @@ -0,0 +1,92 @@ +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/types/account.go b/types/account.go index 4368ef0aa3..266b62d40f 100644 --- a/types/account.go +++ b/types/account.go @@ -5,6 +5,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +// Address in go-crypto style type Address = cmn.HexBytes // Account is a standard account using a sequence number for replay protection diff --git a/types/tx_msg.go b/types/tx_msg.go index c919f6fc5a..c6c96c364c 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -23,6 +23,8 @@ type Msg interface { GetSigners() []Address } +//__________________________________________________________ + // Transactions objects must fulfill the Tx type Tx interface { @@ -64,7 +66,7 @@ func (tx StdTx) GetMsg() Msg { return tx.Msg } func (tx StdTx) GetFeePayer() Address { return tx.Signatures[0].PubKey.Address() } // XXX but PubKey is optional! func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures } -//------------------------------------- +//__________________________________________________________ // Application function variable used to unmarshal transaction bytes type TxDecoder func(txBytes []byte) (Tx, Error) diff --git a/x/bank/tx.go b/x/bank/tx.go index 48dcba85a0..0f2d15c132 100644 --- a/x/bank/tx.go +++ b/x/bank/tx.go @@ -15,6 +15,8 @@ type SendMsg struct { Outputs []Output `json:"outputs"` } +var _ SendMsg = (nil)(sdk.Msg) + // NewSendMsg - construct arbitrary multi-in, multi-out send msg. func NewSendMsg(in []Input, out []Output) SendMsg { return SendMsg{Inputs: in, Outputs: out} @@ -87,7 +89,7 @@ func (msg SendMsg) GetSigners() []sdk.Address { // IssueMsg - high level transaction of the coin module type IssueMsg struct { Banker sdk.Address `json:"banker"` - Outputs []Output `json:"outputs"` + Outputs []Output `json:"outputs"` } // NewIssueMsg - construct arbitrary multi-in, multi-out send msg. @@ -96,7 +98,7 @@ func NewIssueMsg(banker sdk.Address, out []Output) IssueMsg { } // Implements Msg. -func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/send" +func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/issue" // Implements Msg. func (msg IssueMsg) ValidateBasic() sdk.Error { @@ -138,10 +140,11 @@ func (msg IssueMsg) GetSigners() []sdk.Address { //---------------------------------------- // Input +// Transaction Output type Input struct { Address sdk.Address `json:"address"` - Coins sdk.Coins `json:"coins"` - Sequence int64 `json:"sequence"` + Coins sdk.Coins `json:"coins"` + Sequence int64 `json:"sequence"` signature crypto.Signature } @@ -186,9 +189,10 @@ func NewInputWithSequence(addr sdk.Address, coins sdk.Coins, seq int64) Input { //---------------------------------------- // Output +// Transaction Output type Output struct { Address sdk.Address `json:"address"` - Coins sdk.Coins `json:"coins"` + Coins sdk.Coins `json:"coins"` } // ValidateBasic - validate transaction output diff --git a/x/bank/wire.go b/x/bank/wire.go index a69398ea3d..e229e0450b 100644 --- a/x/bank/wire.go +++ b/x/bank/wire.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/wire" ) +// Register concrete types on wire codec func RegisterWire(cdc *wire.Codec) { // TODO: bring this back ... /*