sonr/internal/accounts/protoaccount.go

79 lines
2.5 KiB
Go
Raw Permalink Normal View History

package accounts
import (
"context"
"fmt"
"google.golang.org/protobuf/proto"
"github.com/onsonr/sonr/internal/transaction"
)
// RegisterInitHandler registers an initialisation handler for a smart account that uses protobuf.
func RegisterInitHandler[
Req any, ProtoReq ProtoMsgG[Req], Resp any, ProtoResp ProtoMsgG[Resp],
](router *InitBuilder, handler func(ctx context.Context, req ProtoReq) (ProtoResp, error),
) {
reqName := MessageName(ProtoReq(new(Req)))
router.handler = func(ctx context.Context, initRequest transaction.Msg) (initResponse transaction.Msg, err error) {
concrete, ok := initRequest.(ProtoReq)
if !ok {
return nil, fmt.Errorf("%w: wanted %s, got %T", errInvalidMessage, reqName, initRequest)
}
return handler(ctx, concrete)
}
router.schema = HandlerSchema{
RequestSchema: *NewProtoMessageSchema[Req, ProtoReq](),
ResponseSchema: *NewProtoMessageSchema[Resp, ProtoResp](),
}
}
// RegisterExecuteHandler registers an execution handler for a smart account that uses protobuf.
func RegisterExecuteHandler[
Req any, ProtoReq ProtoMsgG[Req], Resp any, ProtoResp ProtoMsgG[Resp],
](router *ExecuteBuilder, handler func(ctx context.Context, req ProtoReq) (ProtoResp, error),
) {
reqName := MessageName(ProtoReq(new(Req)))
// check if not registered already
if _, ok := router.handlers[reqName]; ok {
router.err = fmt.Errorf("handler already registered for message %s", reqName)
return
}
router.handlers[reqName] = func(ctx context.Context, executeRequest transaction.Msg) (executeResponse transaction.Msg, err error) {
concrete, ok := executeRequest.(ProtoReq)
if !ok {
return nil, fmt.Errorf("%w: wanted %s, got %T", errInvalidMessage, reqName, executeRequest)
}
return handler(ctx, concrete)
}
router.handlersSchema[reqName] = HandlerSchema{
RequestSchema: *NewProtoMessageSchema[Req, ProtoReq](),
ResponseSchema: *NewProtoMessageSchema[Resp, ProtoResp](),
}
}
// RegisterQueryHandler registers a query handler for a smart account that uses protobuf.
func RegisterQueryHandler[
Req any, ProtoReq ProtoMsgG[Req], Resp any, ProtoResp ProtoMsgG[Resp],
](router *QueryBuilder, handler func(ctx context.Context, req ProtoReq) (ProtoResp, error),
) {
RegisterExecuteHandler(router.er, handler)
}
func NewProtoMessageSchema[T any, PT ProtoMsgG[T]]() *MessageSchema {
msg := PT(new(T))
if _, ok := (interface{}(msg)).(proto.Message); ok {
panic("protov2 messages are not supported")
}
return &MessageSchema{
Name: MessageName(msg),
New: func() transaction.Msg {
return PT(new(T))
},
}
}