cosmos-sdk/core/appmodule/v2/handlers.go
ipangpang d8c84589fc
style: remove redundant import alias (#23130)
Co-authored-by: hao.wang <hao.wang@haowangdeMacBook-Pro.local>
Co-authored-by: Marko <marko@baricevic.me>
Co-authored-by: Alex | Skip <alex@skip.money>
2025-01-03 15:04:11 +00:00

187 lines
6.5 KiB
Go

package appmodulev2
import (
"context"
"fmt"
"cosmossdk.io/core/transaction"
)
type (
// PreMsgHandler is a handler that is executed before Handler. If it errors the execution reverts.
PreMsgHandler = func(ctx context.Context, msg transaction.Msg) error
// HandlerFunc handles the state transition of the provided message.
HandlerFunc = func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error)
// PostMsgHandler runs after Handler, only if Handler does not error. If PostMsgHandler errors
// then the execution is reverted.
PostMsgHandler = func(ctx context.Context, msg, msgResp transaction.Msg) error
)
// PreMsgRouter is a router that allows you to register PreMsgHandlers for specific message types.
type PreMsgRouter interface {
// RegisterPreMsgHandler will register a specific message handler hooking into the message with
// the provided name.
RegisterPreMsgHandler(msgName string, handler PreMsgHandler)
// RegisterGlobalPreMsgHandler will register a global message handler hooking into any message
// being executed.
RegisterGlobalPreMsgHandler(handler PreMsgHandler)
}
// HasPreMsgHandlers is an interface that modules must implement if they want to register PreMsgHandlers.
type HasPreMsgHandlers interface {
RegisterPreMsgHandlers(router PreMsgRouter)
}
// RegisterMsgPreHandler is a helper function that modules can use to not lose type safety when registering PreMsgHandler to the
// PreMsgRouter. Example usage:
// ```go
//
// func (h Handlers) BeforeSend(ctx context.Context, req *types.MsgSend) error {
// ... before send logic ...
// }
//
// func (m Module) RegisterPreMsgHandlers(router appmodule.PreMsgRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// appmodule.RegisterMsgPreHandler(router, gogoproto.MessageName(types.MsgSend{}), handlers.BeforeSend)
// }
//
// ```
func RegisterMsgPreHandler[Req transaction.Msg](
router PreMsgRouter,
msgName string,
handler func(ctx context.Context, msg Req) error,
) {
untypedHandler := func(ctx context.Context, m transaction.Msg) error {
typed, ok := m.(Req)
if !ok {
return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req))
}
return handler(ctx, typed)
}
router.RegisterPreMsgHandler(msgName, untypedHandler)
}
// PostMsgRouter is a router that allows you to register PostMsgHandlers for specific message types.
type PostMsgRouter interface {
// RegisterPostMsgHandler will register a specific message handler hooking after the execution of message with
// the provided name.
RegisterPostMsgHandler(msgName string, handler PostMsgHandler)
// RegisterGlobalPostMsgHandler will register a global message handler hooking after the execution of any message.
RegisterGlobalPostMsgHandler(handler PostMsgHandler)
}
// HasPostMsgHandlers is an interface that modules must implement if they want to register PostMsgHandlers.
type HasPostMsgHandlers interface {
RegisterPostMsgHandlers(router PostMsgRouter)
}
// RegisterPostMsgHandler is a helper function that modules can use to not lose type safety when registering handlers to the
// PostMsgRouter. Example usage:
// ```go
//
// func (h Handlers) AfterSend(ctx context.Context, req *types.MsgSend, resp *types.MsgSendResponse) error {
// ... query logic ...
// }
//
// func (m Module) RegisterPostMsgHandlers(router appmodule.PostMsgRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// appmodule.RegisterPostMsgHandler(router, gogoproto.MessageName(types.MsgSend{}), handlers.AfterSend)
// }
//
// ```
func RegisterPostMsgHandler[Req, Resp transaction.Msg](
router PostMsgRouter,
msgName string,
handler func(ctx context.Context, msg Req, msgResp Resp) error,
) {
untypedHandler := func(ctx context.Context, m, mResp transaction.Msg) error {
typed, ok := m.(Req)
if !ok {
return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req))
}
typedResp, ok := mResp.(Resp)
if !ok {
return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Resp))
}
return handler(ctx, typed, typedResp)
}
router.RegisterPostMsgHandler(msgName, untypedHandler)
}
// Handler defines a handler descriptor.
type Handler struct {
// Func defines the actual handler, the function that runs a request and returns a response.
// Can be query handler or msg handler.
Func HandlerFunc
// MakeMsg instantiates the type of the request, can be used in decoding contexts.
MakeMsg func() transaction.Msg
// MakeMsgResp instantiates a new response, can be used in decoding contexts.
MakeMsgResp func() transaction.Msg
}
// MsgRouter is a router that allows you to register Handlers for specific message types.
type MsgRouter = interface {
RegisterHandler(handler Handler)
}
// HasMsgHandlers is an interface that modules must implement if they want to register Handlers.
type HasMsgHandlers interface {
RegisterMsgHandlers(router MsgRouter)
}
// QueryRouter is a router that allows you to register QueryHandlers for specific query types.
type QueryRouter = MsgRouter
// HasQueryHandlers is an interface that modules must implement if they want to register QueryHandlers.
type HasQueryHandlers interface {
RegisterQueryHandlers(router QueryRouter)
}
// RegisterMsgHandler is a helper function that modules can use to not lose type safety when registering handlers to the MsgRouter and Query Router.
// Example usage:
// ```go
//
// func (h Handlers) Mint(ctx context.Context, req *types.MsgMint) (*types.MsgMintResponse, error) {
// ... msg logic ...
// }
//
// func (h Handlers) QueryBalance(ctx context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) {
// ... query logic ...
// }
//
// func (m Module) RegisterMsgHandlers(router appmodule.MsgRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// err := appmodule.RegisterHandler(router, handlers.MsgMint)
// }
//
// func (m Module) RegisterQueryHandlers(router appmodule.QueryRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// err := appmodule.RegisterHandler(router, handlers.QueryBalance)
// }
//
// ```
func RegisterMsgHandler[Req, Resp any, PReq transaction.GenericMsg[Req], PResp transaction.GenericMsg[Resp]](
router MsgRouter,
handler func(ctx context.Context, msg PReq) (msgResp PResp, err error),
) {
untypedHandler := func(ctx context.Context, m transaction.Msg) (transaction.Msg, error) {
typed, ok := m.(PReq)
if !ok {
return nil, fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req))
}
return handler(ctx, typed)
}
router.RegisterHandler(Handler{
Func: untypedHandler,
MakeMsg: func() transaction.Msg {
return PReq(new(Req))
},
MakeMsgResp: func() transaction.Msg {
return PResp(new(Resp))
},
})
}