From acb967ac4f03a691ebd21afd94d3f0629b928ee9 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Wed, 20 Aug 2025 11:44:40 -0400 Subject: [PATCH] fix(x/tx/signing/aminojson): support rendering address bytes as bech32 --- x/tx/signing/aminojson/encoder.go | 14 ++++++++++++++ x/tx/signing/aminojson/json_marshal.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/x/tx/signing/aminojson/encoder.go b/x/tx/signing/aminojson/encoder.go index 4a20ae29be2f..94a44d97c1f2 100644 --- a/x/tx/signing/aminojson/encoder.go +++ b/x/tx/signing/aminojson/encoder.go @@ -72,6 +72,20 @@ func cosmosDecEncoder(_ *Encoder, v protoreflect.Value, w io.Writer) error { } } +// cosmosAddressBytesEncoder encodes `bytes` fields that represent addresses in bech32 format. +func cosmosAddressBytesEncoder(enc *Encoder, v protoreflect.Value, w io.Writer) error { + if enc.addressCodec == nil { + return fmt.Errorf("address codec not set in encoder so we can't render address bytes as bech32 strings") + } + + addrStr, err := enc.addressCodec.BytesToString(v.Bytes()) + if err != nil { + return fmt.Errorf("failed to convert bytes to address string: %w", err) + } + + return jsonMarshal(w, addrStr) +} + // nullSliceAsEmptyEncoder replicates the behavior at: // https://github.com/cosmos/cosmos-sdk/blob/be9bd7a8c1b41b115d58f4e76ee358e18a52c0af/types/coin.go#L199-L205 func nullSliceAsEmptyEncoder(enc *Encoder, v protoreflect.Value, w io.Writer) error { diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index 338ea9d88a61..999a27366cd0 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -7,6 +7,7 @@ import ( "io" "sort" + "cosmossdk.io/core/address" gogoproto "github.com/cosmos/gogoproto/proto" "github.com/pkg/errors" "google.golang.org/protobuf/proto" @@ -44,6 +45,8 @@ type EncoderOptions struct { TypeResolver signing.TypeResolver // FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails. FileResolver signing.ProtoFileResolver + // AddressCodec is used to render address bytes as JSON strings. + AddressCodec address.Codec } // Encoder is a JSON encoder that uses the Amino JSON encoding rules for protobuf messages. @@ -60,6 +63,7 @@ type Encoder struct { enumsAsString bool aminoNameAsTypeURL bool marshalMappings bool + addressCodec address.Codec } // NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding @@ -73,8 +77,9 @@ func NewEncoder(options EncoderOptions) Encoder { } enc := Encoder{ cosmosProtoScalarEncoders: map[string]FieldEncoder{ - cosmosDecType: cosmosDecEncoder, - "cosmos.Int": cosmosIntEncoder, + cosmosDecType: cosmosDecEncoder, + "cosmos.Int": cosmosIntEncoder, + "cosmos.AddressBytes": cosmosAddressBytesEncoder, }, aminoMessageEncoders: map[string]MessageEncoder{ "key_field": keyFieldEncoder, @@ -97,6 +102,7 @@ func NewEncoder(options EncoderOptions) Encoder { enumsAsString: options.EnumAsString, aminoNameAsTypeURL: options.AminoNameAsTypeURL, marshalMappings: options.MarshalMappings, + addressCodec: options.AddressCodec, } return enc }