diff --git a/go.mod b/go.mod index b1991bb22..33bec350d 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( cosmossdk.io/x/circuit v0.1.1 cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 + cosmossdk.io/x/tx v0.13.7 cosmossdk.io/x/upgrade v0.1.4 github.com/cheqd/cheqd-node v1.4.6-pseudo-version-3.1.5.0.20250521081311-8e2db0a29d7d github.com/cometbft/cometbft v0.38.12 @@ -43,7 +44,6 @@ require ( cloud.google.com/go/storage v1.41.0 // indirect cosmossdk.io/errors v1.0.2 // indirect cosmossdk.io/store v1.1.1 // indirect - cosmossdk.io/x/tx v0.13.7 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/4meepo/tagalign v1.3.4 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect diff --git a/modules/mint/source/remote/gogoproto_client.go b/modules/mint/source/remote/gogoproto_client.go new file mode 100644 index 000000000..dbc856941 --- /dev/null +++ b/modules/mint/source/remote/gogoproto_client.go @@ -0,0 +1,87 @@ +package remote + +import ( + "context" + "fmt" + + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + gogoproto "github.com/cosmos/gogoproto/proto" + "google.golang.org/grpc" + "google.golang.org/grpc/encoding" +) + +func init() { + // Register gogoproto codec for gRPC + encoding.RegisterCodec(gogoprotoCodec{}) +} + +// gogoprotoCodec implements grpc/encoding.Codec using gogoproto +type gogoprotoCodec struct{} + +func (gogoprotoCodec) Name() string { + return "gogoproto" +} + +func (gogoprotoCodec) Marshal(v interface{}) ([]byte, error) { + if msg, ok := v.(gogoproto.Marshaler); ok { + return msg.Marshal() + } + return nil, fmt.Errorf("value does not implement gogoproto.Marshaler") +} + +func (gogoprotoCodec) Unmarshal(data []byte, v interface{}) error { + if msg, ok := v.(gogoproto.Unmarshaler); ok { + return msg.Unmarshal(data) + } + return fmt.Errorf("value does not implement gogoproto.Unmarshaler") +} + +// grpcConnWrapper wraps a standard grpc.ClientConn to implement grpc1.ClientConn interface +// This allows us to use gogoproto-generated clients with standard gRPC connections +type grpcConnWrapper struct { + *grpc.ClientConn +} + +// NewStream implements grpc1.ClientConn interface +func (w *grpcConnWrapper) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { + return w.ClientConn.NewStream(ctx, desc, method, opts...) +} + +// Invoke implements grpc1.ClientConn interface +// Use gogoproto codec via CallOption +func (w *grpcConnWrapper) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error { + opts = append(opts, grpc.ForceCodec(gogoprotoCodec{})) + return w.ClientConn.Invoke(ctx, method, args, reply, opts...) +} + +func (w *grpcConnWrapper) Close() error { + return w.ClientConn.Close() +} + +// GogoprotoQueryClient uses gogoproto-generated types for mint queries +type GogoprotoQueryClient struct { + cc *grpc.ClientConn + pb minttypes.QueryClient +} + +// NewGogoprotoQueryClient creates a new gogoproto-based query client +func NewGogoprotoQueryClient(cc *grpc.ClientConn) *GogoprotoQueryClient { + // Wrap the standard grpc.ClientConn to implement grpc1.ClientConn interface + wrapped := &grpcConnWrapper{ClientConn: cc} + + // Create the gogoproto-generated client which uses gogoproto for marshaling/unmarshaling + pbClient := minttypes.NewQueryClient(wrapped) + + return &GogoprotoQueryClient{ + cc: cc, + pb: pbClient, + } +} + +func (c *GogoprotoQueryClient) Inflation(ctx context.Context, req *minttypes.QueryInflationRequest, opts ...grpc.CallOption) (*minttypes.QueryInflationResponse, error) { + return c.pb.Inflation(ctx, req, opts...) +} + +func (c *GogoprotoQueryClient) Params(ctx context.Context, req *minttypes.QueryParamsRequest, opts ...grpc.CallOption) (*minttypes.QueryParamsResponse, error) { + return c.pb.Params(ctx, req, opts...) +} diff --git a/modules/mint/source/remote/source.go b/modules/mint/source/remote/source.go index e3397f78a..91d2dfc8c 100644 --- a/modules/mint/source/remote/source.go +++ b/modules/mint/source/remote/source.go @@ -1,23 +1,31 @@ package remote import ( + "context" + "cosmossdk.io/math" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/forbole/juno/v6/node/remote" - mintsource "github.com/forbole/callisto/v4/modules/mint/source" + "github.com/forbole/juno/v6/node/remote" + "google.golang.org/grpc" ) var _ mintsource.Source = &Source{} -// Source implements mintsource.Source using a remote node +// Source implements mintsource.Source using a remote node with gogoproto-compatible types type Source struct { *remote.Source - querier minttypes.QueryClient + querier QueryClient +} + +// QueryClient interface for mint queries using gogoproto-generated types +type QueryClient interface { + Inflation(ctx context.Context, req *minttypes.QueryInflationRequest, opts ...grpc.CallOption) (*minttypes.QueryInflationResponse, error) + Params(ctx context.Context, req *minttypes.QueryParamsRequest, opts ...grpc.CallOption) (*minttypes.QueryParamsResponse, error) } // NewSource returns a new Source instance -func NewSource(source *remote.Source, querier minttypes.QueryClient) *Source { +func NewSource(source *remote.Source, querier QueryClient) *Source { return &Source{ Source: source, querier: querier, @@ -26,7 +34,8 @@ func NewSource(source *remote.Source, querier minttypes.QueryClient) *Source { // GetInflation implements mintsource.Source func (s Source) GetInflation(height int64) (math.LegacyDec, error) { - res, err := s.querier.Inflation(remote.GetHeightRequestContext(s.Ctx, height), &minttypes.QueryInflationRequest{}) + req := &minttypes.QueryInflationRequest{} + res, err := s.querier.Inflation(remote.GetHeightRequestContext(s.Ctx, height), req) if err != nil { return math.LegacyDec{}, err } @@ -36,10 +45,12 @@ func (s Source) GetInflation(height int64) (math.LegacyDec, error) { // Params implements mintsource.Source func (s Source) Params(height int64) (minttypes.Params, error) { - res, err := s.querier.Params(remote.GetHeightRequestContext(s.Ctx, height), &minttypes.QueryParamsRequest{}) + req := &minttypes.QueryParamsRequest{} + res, err := s.querier.Params(remote.GetHeightRequestContext(s.Ctx, height), req) if err != nil { - return minttypes.Params{}, nil + return minttypes.Params{}, err } + // res.Params is already of type minttypes.Params (proto-generated types are canonical) return res.Params, nil } diff --git a/modules/types/sources.go b/modules/types/sources.go index eb1b4ee1e..71abeea94 100644 --- a/modules/types/sources.go +++ b/modules/types/sources.go @@ -17,7 +17,6 @@ import ( govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -120,12 +119,15 @@ func buildRemoteSources(cfg *remote.Details) (*Sources, error) { return nil, fmt.Errorf("error while creating remote source: %s", err) } + // Create gogoproto client for mint queries to handle math.LegacyDec properly + mintGogoClient := remotemintsource.NewGogoprotoQueryClient(source.GrpcConn) + return &Sources{ AuthSource: remoteauthsource.NewSource(source, authtypes.NewQueryClient(source.GrpcConn)), BankSource: remotebanksource.NewSource(source, banktypes.NewQueryClient(source.GrpcConn)), DistrSource: remotedistrsource.NewSource(source, distrtypes.NewQueryClient(source.GrpcConn)), GovSource: remotegovsource.NewSource(source, govtypesv1.NewQueryClient(source.GrpcConn)), - MintSource: remotemintsource.NewSource(source, minttypes.NewQueryClient(source.GrpcConn)), + MintSource: remotemintsource.NewSource(source, mintGogoClient), SlashingSource: remoteslashingsource.NewSource(source, slashingtypes.NewQueryClient(source.GrpcConn)), StakingSource: remotestakingsource.NewSource(source, stakingtypes.NewQueryClient(source.GrpcConn)), }, nil diff --git a/utils/codec.go b/utils/codec.go index 314d1fb8e..11a61a489 100644 --- a/utils/codec.go +++ b/utils/codec.go @@ -18,7 +18,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" "github.com/cosmos/cosmos-sdk/x/bank" consensus "github.com/cosmos/cosmos-sdk/x/consensus" @@ -69,6 +71,16 @@ func GetCodec() codec.Codec { ) getBasicManagers().RegisterInterfaces(interfaceRegistry) std.RegisterInterfaces(interfaceRegistry) + + // Explicitly register vesting account types + interfaceRegistry.RegisterImplementations( + (*authtypes.AccountI)(nil), + &vestingtypes.ContinuousVestingAccount{}, + &vestingtypes.DelayedVestingAccount{}, + &vestingtypes.PeriodicVestingAccount{}, + &vestingtypes.PermanentLockedAccount{}, + ) + cdc = codec.NewProtoCodec(interfaceRegistry) }) return cdc