cosmos-sdk/x/bank/internal/types/msgs.go

186 lines
4.9 KiB
Go

package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// RouterKey is they name of the bank module
const RouterKey = ModuleName
// MsgSend - high level transaction of the coin module
type MsgSend struct {
FromAddress sdk.AccAddress `json:"from_address" yaml:"from_address"`
ToAddress sdk.AccAddress `json:"to_address" yaml:"to_address"`
Amount sdk.Coins `json:"amount" yaml:"amount"`
}
var _ sdk.Msg = MsgSend{}
// NewMsgSend - construct arbitrary multi-in, multi-out send msg.
func NewMsgSend(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins) MsgSend {
return MsgSend{FromAddress: fromAddr, ToAddress: toAddr, Amount: amount}
}
// Route Implements Msg.
func (msg MsgSend) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgSend) Type() string { return "send" }
// ValidateBasic Implements Msg.
func (msg MsgSend) ValidateBasic() sdk.Error {
if msg.FromAddress.Empty() {
return sdk.ErrInvalidAddress("missing sender address")
}
if msg.ToAddress.Empty() {
return sdk.ErrInvalidAddress("missing recipient address")
}
if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins("send amount is invalid: " + msg.Amount.String())
}
if !msg.Amount.IsAllPositive() {
return sdk.ErrInsufficientCoins("send amount must be positive")
}
return nil
}
// GetSignBytes Implements Msg.
func (msg MsgSend) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}
// GetSigners Implements Msg.
func (msg MsgSend) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.FromAddress}
}
// MsgMultiSend - high level transaction of the coin module
type MsgMultiSend struct {
Inputs []Input `json:"inputs" yaml:"inputs"`
Outputs []Output `json:"outputs" yaml:"outputs"`
}
var _ sdk.Msg = MsgMultiSend{}
// NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg.
func NewMsgMultiSend(in []Input, out []Output) MsgMultiSend {
return MsgMultiSend{Inputs: in, Outputs: out}
}
// Route Implements Msg
func (msg MsgMultiSend) Route() string { return RouterKey }
// Type Implements Msg
func (msg MsgMultiSend) Type() string { return "multisend" }
// ValidateBasic Implements Msg.
func (msg MsgMultiSend) ValidateBasic() sdk.Error {
// this just makes sure all the inputs and outputs are properly formatted,
// not that they actually have the money inside
if len(msg.Inputs) == 0 {
return ErrNoInputs(DefaultCodespace).TraceSDK("")
}
if len(msg.Outputs) == 0 {
return ErrNoOutputs(DefaultCodespace).TraceSDK("")
}
return ValidateInputsOutputs(msg.Inputs, msg.Outputs)
}
// GetSignBytes Implements Msg.
func (msg MsgMultiSend) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}
// GetSigners Implements Msg.
func (msg MsgMultiSend) GetSigners() []sdk.AccAddress {
addrs := make([]sdk.AccAddress, len(msg.Inputs))
for i, in := range msg.Inputs {
addrs[i] = in.Address
}
return addrs
}
// Input models transaction input
type Input struct {
Address sdk.AccAddress `json:"address" yaml:"address"`
Coins sdk.Coins `json:"coins" yaml:"coins"`
}
// ValidateBasic - validate transaction input
func (in Input) ValidateBasic() sdk.Error {
if len(in.Address) == 0 {
return sdk.ErrInvalidAddress(in.Address.String())
}
if !in.Coins.IsValid() {
return sdk.ErrInvalidCoins(in.Coins.String())
}
if !in.Coins.IsAllPositive() {
return sdk.ErrInvalidCoins(in.Coins.String())
}
return nil
}
// NewInput - create a transaction input, used with MsgMultiSend
func NewInput(addr sdk.AccAddress, coins sdk.Coins) Input {
return Input{
Address: addr,
Coins: coins,
}
}
// Output models transaction outputs
type Output struct {
Address sdk.AccAddress `json:"address" yaml:"address"`
Coins sdk.Coins `json:"coins" yaml:"coins"`
}
// ValidateBasic - validate transaction output
func (out Output) ValidateBasic() sdk.Error {
if len(out.Address) == 0 {
return sdk.ErrInvalidAddress(out.Address.String())
}
if !out.Coins.IsValid() {
return sdk.ErrInvalidCoins(out.Coins.String())
}
if !out.Coins.IsAllPositive() {
return sdk.ErrInvalidCoins(out.Coins.String())
}
return nil
}
// NewOutput - create a transaction output, used with MsgMultiSend
func NewOutput(addr sdk.AccAddress, coins sdk.Coins) Output {
return Output{
Address: addr,
Coins: coins,
}
}
// ValidateInputsOutputs validates that each respective input and output is
// valid and that the sum of inputs is equal to the sum of outputs.
func ValidateInputsOutputs(inputs []Input, outputs []Output) sdk.Error {
var totalIn, totalOut sdk.Coins
for _, in := range inputs {
if err := in.ValidateBasic(); err != nil {
return err.TraceSDK("")
}
totalIn = totalIn.Add(in.Coins)
}
for _, out := range outputs {
if err := out.ValidateBasic(); err != nil {
return err.TraceSDK("")
}
totalOut = totalOut.Add(out.Coins)
}
// make sure inputs and outputs match
if !totalIn.IsEqual(totalOut) {
return ErrInputOutputMismatch(DefaultCodespace)
}
return nil
}