diff --git a/docs/architecture/adr-050-sign-mode-textual-annex1.md b/docs/architecture/adr-050-sign-mode-textual-annex1.md index 87496657c2..ff3acc8c59 100644 --- a/docs/architecture/adr-050-sign-mode-textual-annex1.md +++ b/docs/architecture/adr-050-sign-mode-textual-annex1.md @@ -320,6 +320,10 @@ TestData object > Signer: cosmos1abc ``` +### bool + +Boolean values are rendered as `True` or `False`. + ### [ABANDONED] Custom `msg_title` instead of Msg `type_url` _This paragraph is in the Annex for informational purposes only, and will be removed in a next update of the ADR._ diff --git a/x/tx/signing/textual/bool.go b/x/tx/signing/textual/bool.go new file mode 100644 index 0000000000..2347ef1dd4 --- /dev/null +++ b/x/tx/signing/textual/bool.go @@ -0,0 +1,37 @@ +package textual + +import ( + "context" + "fmt" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type boolValueRenderer struct{} + +// NewBoolValueRenderer returns a ValueRenderer for protocol buffer bool values. +// It renders the boolean as YES or NO. +func NewBoolValueRenderer() ValueRenderer { + return boolValueRenderer{} +} + +func (sr boolValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]Screen, error) { + str := "False" + if v.Bool() { + str = "True" + } + return []Screen{{Content: str}}, nil +} + +func (sr boolValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) { + if len(screens) != 1 { + return protoreflect.Value{}, fmt.Errorf("expected single screen: %v", screens) + } + + res := false + if screens[0].Content == "True" { + res = true + } + + return protoreflect.ValueOfBool(res), nil +} diff --git a/x/tx/signing/textual/bool_test.go b/x/tx/signing/textual/bool_test.go new file mode 100644 index 0000000000..07722375d6 --- /dev/null +++ b/x/tx/signing/textual/bool_test.go @@ -0,0 +1,31 @@ +package textual_test + +import ( + "context" + "testing" + + "cosmossdk.io/x/tx/signing/textual" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func TestBool(t *testing.T) { + // test true + rend := textual.NewBoolValueRenderer() + screens, err := rend.Format(context.Background(), protoreflect.ValueOfBool(true)) + require.NoError(t, err) + require.Equal(t, 1, len(screens)) + require.Equal(t, "True", screens[0].Content) + val, err := rend.Parse(context.Background(), screens) + require.NoError(t, err) + require.Equal(t, true, val.Bool()) + + // test false + screens, err = rend.Format(context.Background(), protoreflect.ValueOfBool(false)) + require.NoError(t, err) + require.Equal(t, 1, len(screens)) + require.Equal(t, "False", screens[0].Content) + val, err = rend.Parse(context.Background(), screens) + require.NoError(t, err) + require.Equal(t, false, val.Bool()) +} diff --git a/x/tx/signing/textual/handler.go b/x/tx/signing/textual/handler.go index fe208890fa..c688398c86 100644 --- a/x/tx/signing/textual/handler.go +++ b/x/tx/signing/textual/handler.go @@ -138,6 +138,8 @@ func (r *SignModeHandler) GetFieldValueRenderer(fd protoreflect.FieldDescriptor) return nil, fmt.Errorf("value renderers cannot format value of type map") } return NewMessageValueRenderer(r, md), nil + case fd.Kind() == protoreflect.BoolKind: + return NewBoolValueRenderer(), nil default: return nil, fmt.Errorf("value renderers cannot format value of type %s", fd.Kind())