Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(x/tx): add enum as string encoder option #19618

Merged
merged 8 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/v2/autocli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func (b *Builder) BuildQueryMethodCommand(ctx context.Context, descriptor protor
outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output())
encoderOptions := aminojson.EncoderOptions{
Indent: " ",
EnumAsString: true,
DoNotSortFields: true,
TypeResolver: b.TypeResolver,
FileResolver: b.FileResolver,
Expand Down
8 changes: 6 additions & 2 deletions x/tx/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

### Bug Fixes
### Features

* [#19265](https://github.com/cosmos/cosmos-sdk/pull/19265) Reject denoms that contain a comma.
* * [#](https://github.com/cosmos/cosmos-sdk/pull/) Add enum as string option to encoder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of the feature to add an enum as a string option to the encoder is accurately documented under the "Features" section. This entry clearly communicates the enhancement made to the SDK, aligning with the PR's objectives. Ensure that the placeholder link [#](https://github.com/cosmos/cosmos-sdk/pull/) is replaced with the actual PR link for proper referencing.

- * * [#](https://github.com/cosmos/cosmos-sdk/pull/) Add enum as string option to encoder.
+ * * [#19618](https://github.com/cosmos/cosmos-sdk/pull/19618) Add enum as string option to encoder.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
* * [#](https://github.com/cosmos/cosmos-sdk/pull/) Add enum as string option to encoder.
* * [#19618](https://github.com/cosmos/cosmos-sdk/pull/19618) Add enum as string option to encoder.


### Improvements

* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` from `core/coins` to this package under `signing/textual`.

### Bug Fixes

* [#19265](https://github.com/cosmos/cosmos-sdk/pull/19265) Reject denoms that contain a comma.

## v0.13.0

### Improvements
Expand Down
4 changes: 2 additions & 2 deletions x/tx/signing/aminojson/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func nullSliceAsEmptyEncoder(enc *Encoder, v protoreflect.Value, w io.Writer) er
_, err := io.WriteString(w, "[]")
return err
}
return enc.marshalList(list, w)
return enc.marshalList(list, nil /* TODO */, w)
default:
return fmt.Errorf("unsupported type %T", list)
}
Expand Down Expand Up @@ -161,7 +161,7 @@ func thresholdStringEncoder(enc *Encoder, msg protoreflect.Message, w io.Writer)
pubkeysField := fields.ByName("public_keys")
pubkeys := msg.Get(pubkeysField).List()

err = enc.marshalList(pubkeys, w)
err = enc.marshalList(pubkeys, pubkeysField, w)
if err != nil {
return err
}
Expand Down
29 changes: 22 additions & 7 deletions x/tx/signing/aminojson/json_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type EncoderOptions struct {
Indent string
// DoNotSortFields when set turns off sorting of field names.
DoNotSortFields bool
// EnumAsString when set will encode enums as strings instead of integers.
EnumAsString bool
// TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages.
TypeResolver signing.TypeResolver
// FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails.
Expand All @@ -45,6 +47,7 @@ type Encoder struct {
typeResolver protoregistry.MessageTypeResolver
doNotSortFields bool
indent string
enumsAsString bool
}

// NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding
Expand Down Expand Up @@ -78,6 +81,7 @@ func NewEncoder(options EncoderOptions) Encoder {
typeResolver: options.TypeResolver,
doNotSortFields: options.DoNotSortFields,
indent: options.Indent,
enumsAsString: options.EnumAsString,
}
return enc
}
Expand Down Expand Up @@ -189,7 +193,7 @@ func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAn
}
}

err := enc.marshal(protoreflect.ValueOfMessage(msg), writer)
err := enc.marshal(protoreflect.ValueOfMessage(msg), nil /* todo */, writer)
if err != nil {
return err
}
Expand All @@ -204,7 +208,7 @@ func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAn
return nil
}

func (enc Encoder) marshal(value protoreflect.Value, writer io.Writer) error {
func (enc Encoder) marshal(value protoreflect.Value, fd protoreflect.FieldDescriptor, writer io.Writer) error {
switch val := value.Interface().(type) {
case protoreflect.Message:
err := enc.marshalMessage(val, writer)
Expand All @@ -218,9 +222,20 @@ func (enc Encoder) marshal(value protoreflect.Value, writer io.Writer) error {
_, err := io.WriteString(writer, "null")
return err
}
return enc.marshalList(val, writer)
return enc.marshalList(val, fd, writer)

case string, bool, int32, uint32, []byte:
return jsonMarshal(writer, val)

case protoreflect.EnumNumber:
if enc.enumsAsString && fd != nil {
desc := fd.Enum().Values().ByNumber(val)
if desc != nil {
_, err := io.WriteString(writer, fmt.Sprintf(`"%s"`, desc.Name()))
return err
}
}

case string, bool, int32, uint32, []byte, protoreflect.EnumNumber:
return jsonMarshal(writer, val)

case uint64, int64:
Expand Down Expand Up @@ -342,7 +357,7 @@ func (enc Encoder) marshalMessage(msg protoreflect.Message, writer io.Writer) er
return err
}
} else {
err = enc.marshal(v, writer)
err = enc.marshal(v, f, writer)
if err != nil {
return err
}
Expand Down Expand Up @@ -371,7 +386,7 @@ func jsonMarshal(w io.Writer, v interface{}) error {
return err
}

func (enc Encoder) marshalList(list protoreflect.List, writer io.Writer) error {
func (enc Encoder) marshalList(list protoreflect.List, fd protoreflect.FieldDescriptor, writer io.Writer) error {
n := list.Len()

_, err := io.WriteString(writer, "[")
Expand All @@ -389,7 +404,7 @@ func (enc Encoder) marshalList(list protoreflect.List, writer io.Writer) error {
}
first = false

err = enc.marshal(list.Get(i), writer)
err = enc.marshal(list.Get(i), fd, writer)
if err != nil {
return err
}
Expand Down
59 changes: 59 additions & 0 deletions x/tx/signing/aminojson/json_marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,62 @@ func TestIndent(t *testing.T) {
}
}`, string(bz))
}

func TestEnumAsString(t *testing.T) {
encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", EnumAsString: true})

msg := &testpb.ABitOfEverything{
Message: &testpb.NestedMessage{
Foo: "test",
Bar: 0, // this is the default value and should be omitted from output
},
Enum: testpb.AnEnum_ONE,
Repeated: []int32{3, -7, 2, 6, 4},
Str: `abcxyz"foo"def`,
Bool: true,
Bytes: []byte{0, 1, 2, 3},
I32: -15,
F32: 1001,
U32: 1200,
Si32: -376,
Sf32: -1000,
I64: 14578294827584932,
F64: 9572348124213523654,
U64: 4759492485,
Si64: -59268425823934,
Sf64: -659101379604211154,
}

bz, err := encoder.Marshal(msg)
require.NoError(t, err)
fmt.Println(string(bz))
require.Equal(t, `{
"type": "ABitOfEverything",
"value": {
"bool": true,
"bytes": "AAECAw==",
"enum": "ONE",
"f32": 1001,
"f64": "9572348124213523654",
"i32": -15,
"i64": "14578294827584932",
"message": {
"foo": "test"
},
"repeated": [
3,
-7,
2,
6,
4
],
"sf32": -1000,
"sf64": "-659101379604211154",
"si32": -376,
"si64": "-59268425823934",
"str": "abcxyz\"foo\"def",
"u32": 1200,
"u64": "4759492485"
}
}`, string(bz))
}
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
Loading