From 7fdb5c9f3a2ebe4544f6f4f4299cbbc6ecf9b6cd Mon Sep 17 00:00:00 2001 From: affan Date: Wed, 11 Sep 2024 05:00:18 -0400 Subject: [PATCH] Add client code for affiliates --- proto/dydxprotocol/affiliates/genesis.proto | 8 +- protocol/x/affiliates/client/cli/query.go | 72 ++++++++++++++++++ .../x/affiliates/client/cli/query_test.go | 74 ++++++++++++++++++ protocol/x/affiliates/client/cli/tx.go | 24 ++++++ protocol/x/affiliates/genesis.go | 10 ++- protocol/x/affiliates/keeper/grpc_query.go | 6 +- protocol/x/affiliates/types/genesis.go | 4 +- protocol/x/affiliates/types/genesis.pb.go | 76 +++++++++++++++++-- 8 files changed, 258 insertions(+), 16 deletions(-) create mode 100644 protocol/x/affiliates/client/cli/query_test.go diff --git a/proto/dydxprotocol/affiliates/genesis.proto b/proto/dydxprotocol/affiliates/genesis.proto index 62315d2c44..2b55d4a853 100644 --- a/proto/dydxprotocol/affiliates/genesis.proto +++ b/proto/dydxprotocol/affiliates/genesis.proto @@ -1,7 +1,13 @@ syntax = "proto3"; package dydxprotocol.affiliates; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "dydxprotocol/affiliates/affiliates.proto"; option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types"; // GenesisState defines generis state of `x/affiliates` -message GenesisState {} \ No newline at end of file +message GenesisState { + // The list of affiliate tiers + AffiliateTiers affiliate_tiers = 1 [ (gogoproto.nullable) = false ]; +} \ No newline at end of file diff --git a/protocol/x/affiliates/client/cli/query.go b/protocol/x/affiliates/client/cli/query.go index f5145a6c05..872ba5443b 100644 --- a/protocol/x/affiliates/client/cli/query.go +++ b/protocol/x/affiliates/client/cli/query.go @@ -1,6 +1,7 @@ package cli import ( + "context" "fmt" "github.com/spf13/cobra" @@ -20,5 +21,76 @@ func GetQueryCmd(queryRoute string) *cobra.Command { RunE: client.ValidateCmd, } + cmd.AddCommand( + GetCmdQueryAffiliateTiers(), + GetCmdQueryAffiliateInfo(), + GetCmdQueryReferredBy(), + ) + return cmd +} + +func GetCmdQueryAffiliateTiers() *cobra.Command { + cmd := &cobra.Command{ + Use: "affiliate-tiers", + Short: "Query affiliate tiers", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.AllAffiliateTiers(context.Background(), &types.AllAffiliateTiersRequest{}) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + return cmd +} + +func GetCmdQueryAffiliateInfo() *cobra.Command { + cmd := &cobra.Command{ + Use: "affiliate-info [affiliate-address]", + Short: "Query affiliate info", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.AffiliateInfo(context.Background(), &types.AffiliateInfoRequest{ + Address: args[0], + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + return cmd +} + +func GetCmdQueryReferredBy() *cobra.Command { + cmd := &cobra.Command{ + Use: "referred-by [address]", + Short: "Query the referee that referred the given addresss", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.ReferredBy(context.Background(), &types.ReferredByRequest{ + Address: args[0], + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } return cmd } diff --git a/protocol/x/affiliates/client/cli/query_test.go b/protocol/x/affiliates/client/cli/query_test.go new file mode 100644 index 0000000000..036e64a404 --- /dev/null +++ b/protocol/x/affiliates/client/cli/query_test.go @@ -0,0 +1,74 @@ +package cli_test + +import ( + "strconv" + "testing" + + "github.com/cosmos/cosmos-sdk/client" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/stretchr/testify/require" + + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + "github.com/dydxprotocol/v4-chain/protocol/testutil/network" + "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/client/cli" + "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func setupNetwork(t *testing.T) (*network.Network, client.Context) { + t.Helper() + cfg := network.DefaultConfig(nil) + + // Init state. + state := types.GenesisState{} + require.NoError(t, cfg.Codec.UnmarshalJSON(cfg.GenesisState[types.ModuleName], &state)) + + // Modify default genesis state + state = *types.DefaultGenesis() + + // Add test affiliate tiers + state.AffiliateTiers = types.DefaultAffiliateTiers + + buf, err := cfg.Codec.MarshalJSON(&state) + require.NoError(t, err) + cfg.GenesisState[types.ModuleName] = buf + net := network.New(t, cfg) + ctx := net.Validators[0].ClientCtx + + return net, ctx +} + +func TestQueryAffiliateTiers(t *testing.T) { + net, ctx := setupNetwork(t) + + out, err := clitestutil.ExecTestCLICmd(ctx, cli.GetCmdQueryAffiliateTiers(), []string{}) + require.NoError(t, err) + + var resp types.AllAffiliateTiersResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) + require.Equal(t, types.DefaultAffiliateTiers, resp.Tiers) +} + +func TestQueryAffiliateInfo(t *testing.T) { + net, ctx := setupNetwork(t) + + testAddress := constants.AliceAccAddress.String() + out, err := clitestutil.ExecTestCLICmd(ctx, cli.GetCmdQueryAffiliateInfo(), []string{testAddress}) + require.NoError(t, err) + + var resp types.AffiliateInfoResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +} + +func TestQueryReferredBy(t *testing.T) { + net, ctx := setupNetwork(t) + + testAddress := constants.AliceAccAddress.String() + out, err := clitestutil.ExecTestCLICmd(ctx, cli.GetCmdQueryReferredBy(), []string{testAddress}) + require.NoError(t, err) + + var resp types.ReferredByResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +} diff --git a/protocol/x/affiliates/client/cli/tx.go b/protocol/x/affiliates/client/cli/tx.go index fab8d4a046..1deb7a0897 100644 --- a/protocol/x/affiliates/client/cli/tx.go +++ b/protocol/x/affiliates/client/cli/tx.go @@ -6,6 +6,8 @@ import ( "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" ) @@ -18,5 +20,27 @@ func GetTxCmd() *cobra.Command { SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } + cmd.AddCommand(CmdRegisterAffiliate()) + return cmd +} + +func CmdRegisterAffiliate() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-affiliate [affiliate] [referee]", + Short: "Register an affiliate", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + msg := types.MsgRegisterAffiliate{ + Affiliate: args[0], + Referee: args[1], + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + flags.AddTxFlagsToCmd(cmd) return cmd } diff --git a/protocol/x/affiliates/genesis.go b/protocol/x/affiliates/genesis.go index 4767af4794..7dea514d8e 100644 --- a/protocol/x/affiliates/genesis.go +++ b/protocol/x/affiliates/genesis.go @@ -8,9 +8,17 @@ import ( // InitGenesis initializes the module's state from a provided genesis state. func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + k.UpdateAffiliateTiers(ctx, genState.AffiliateTiers) } // ExportGenesis returns the module's exported genesis. func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { - return &types.GenesisState{} + affiliateTiers, err := k.GetAllAffiliateTiers(ctx) + if err != nil { + panic(err) + } + + return &types.GenesisState{ + AffiliateTiers: affiliateTiers, + } } diff --git a/protocol/x/affiliates/keeper/grpc_query.go b/protocol/x/affiliates/keeper/grpc_query.go index fff1a96295..a4a992b271 100644 --- a/protocol/x/affiliates/keeper/grpc_query.go +++ b/protocol/x/affiliates/keeper/grpc_query.go @@ -49,11 +49,7 @@ func (k Keeper) ReferredBy(ctx context.Context, affiliateAddr, exists := k.GetReferredBy(sdkCtx, req.GetAddress()) if !exists { - return &types.ReferredByResponse{}, errorsmod.Wrapf( - types.ErrAffiliateNotFound, - "affiliate not found for address: %s", - req.GetAddress(), - ) + return &types.ReferredByResponse{}, nil } return &types.ReferredByResponse{ diff --git a/protocol/x/affiliates/types/genesis.go b/protocol/x/affiliates/types/genesis.go index 09583a5f2e..d00d8cb822 100644 --- a/protocol/x/affiliates/types/genesis.go +++ b/protocol/x/affiliates/types/genesis.go @@ -2,7 +2,9 @@ package types // DefaultGenesis returns the default stats genesis state. func DefaultGenesis() *GenesisState { - return &GenesisState{} + return &GenesisState{ + AffiliateTiers: AffiliateTiers{}, + } } // Validate performs basic genesis state validation returning an error upon any diff --git a/protocol/x/affiliates/types/genesis.pb.go b/protocol/x/affiliates/types/genesis.pb.go index 98728d902f..4f9d224436 100644 --- a/protocol/x/affiliates/types/genesis.pb.go +++ b/protocol/x/affiliates/types/genesis.pb.go @@ -5,6 +5,8 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -24,6 +26,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines generis state of `x/affiliates` type GenesisState struct { + // The list of affiliate tiers + AffiliateTiers AffiliateTiers `protobuf:"bytes,1,opt,name=affiliate_tiers,json=affiliateTiers,proto3" json:"affiliate_tiers"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -59,6 +63,13 @@ func (m *GenesisState) XXX_DiscardUnknown() { var xxx_messageInfo_GenesisState proto.InternalMessageInfo +func (m *GenesisState) GetAffiliateTiers() AffiliateTiers { + if m != nil { + return m.AffiliateTiers + } + return AffiliateTiers{} +} + func init() { proto.RegisterType((*GenesisState)(nil), "dydxprotocol.affiliates.GenesisState") } @@ -68,17 +79,21 @@ func init() { } var fileDescriptor_7d3ffc50e877971b = []byte{ - // 146 bytes of a gzipped FileDescriptorProto + // 221 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xa9, 0x4c, 0xa9, 0x28, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0xce, 0xcf, 0xd1, 0x4f, 0x4c, 0x4b, 0xcb, 0xcc, 0xc9, 0x4c, 0x2c, 0x49, 0x2d, 0xd6, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x03, 0xcb, 0x09, 0x89, - 0x23, 0x2b, 0xd3, 0x43, 0x28, 0x53, 0xe2, 0xe3, 0xe2, 0x71, 0x87, 0xa8, 0x0c, 0x2e, 0x49, 0x2c, - 0x49, 0x75, 0x0a, 0x3b, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, - 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x9b, 0xf4, - 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x14, 0x4b, 0xcb, 0x4c, 0x74, 0x93, - 0x33, 0x12, 0x33, 0xf3, 0xf4, 0xe1, 0x22, 0x15, 0xc8, 0x0e, 0x29, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, - 0x62, 0x03, 0x4b, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x52, 0x0f, 0x30, 0xb0, 0x00, - 0x00, 0x00, + 0x23, 0x2b, 0xd3, 0x43, 0x28, 0x93, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x4b, 0xe8, 0x83, 0x58, + 0x10, 0xe5, 0x52, 0x92, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xf1, 0x10, 0x09, 0x08, 0x07, 0x2a, + 0xa5, 0x81, 0xcb, 0x42, 0x04, 0x13, 0xa2, 0x52, 0x29, 0x8d, 0x8b, 0xc7, 0x1d, 0xe2, 0x88, 0xe0, + 0x92, 0xc4, 0x92, 0x54, 0xa1, 0x30, 0x2e, 0x7e, 0xb8, 0x9a, 0xf8, 0x92, 0xcc, 0xd4, 0xa2, 0x62, + 0x09, 0x46, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x75, 0x3d, 0x1c, 0xae, 0xd3, 0x73, 0x84, 0x31, 0x43, + 0x40, 0xca, 0x9d, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, 0xe2, 0x4b, 0x44, 0x15, 0x0d, 0x3b, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x9b, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, + 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x14, 0x67, 0x97, 0x99, 0xe8, 0x26, 0x67, 0x24, 0x66, 0xe6, 0xe9, + 0xc3, 0x45, 0x2a, 0x90, 0xbd, 0x52, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x96, 0x34, 0x06, + 0x04, 0x00, 0x00, 0xff, 0xff, 0x03, 0xce, 0x7f, 0xe1, 0x63, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -101,6 +116,16 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.AffiliateTiers.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -121,6 +146,8 @@ func (m *GenesisState) Size() (n int) { } var l int _ = l + l = m.AffiliateTiers.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -159,6 +186,39 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AffiliateTiers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.AffiliateTiers.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:])