github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/feesplit/keeper/querier.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/query"
    14  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    15  	"github.com/fibonacci-chain/fbc/x/feesplit/types"
    16  )
    17  
    18  // NewQuerier is the module level router for state queries
    19  func NewQuerier(keeper Keeper) sdk.Querier {
    20  	return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
    21  		if len(path) < 1 {
    22  			return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
    23  				"Insufficient parameters, at least 1 parameter is required")
    24  		}
    25  
    26  		switch path[0] {
    27  		case types.QueryParameters:
    28  			return queryParams(ctx, keeper)
    29  		case types.QueryFeeSplits:
    30  			return queryFeeSplits(ctx, req, keeper)
    31  		case types.QueryFeeSplit:
    32  			return queryFeeSplit(ctx, req, keeper)
    33  		case types.QueryDeployerFeeSplits:
    34  			return queryDeployerFeeSplits(ctx, req, keeper)
    35  		case types.QueryDeployerFeeSplitsDetail:
    36  			return queryDeployerFeeSplitsDetail(ctx, req, keeper)
    37  		case types.QueryWithdrawerFeeSplits:
    38  			return queryWithdrawerFeeSplits(ctx, req, keeper)
    39  		default:
    40  			return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query endpoint")
    41  		}
    42  	}
    43  }
    44  
    45  // queryFeeSplits returns all FeeSplits that have been registered for fee distribution
    46  func queryFeeSplits(
    47  	ctx sdk.Context,
    48  	req abci.RequestQuery,
    49  	k Keeper,
    50  ) ([]byte, sdk.Error) {
    51  	var params types.QueryWithdrawerFeeSplitsRequest
    52  	err := k.cdc.UnmarshalJSON(req.Data, &params)
    53  	if err != nil {
    54  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
    55  	}
    56  
    57  	var feeSplits []types.FeeSplitWithShare
    58  	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixFeeSplit)
    59  
    60  	pageRes, err := query.Paginate(store, params.Pagination, func(_, value []byte) error {
    61  		var fee types.FeeSplit
    62  		if err := k.cdc.UnmarshalBinaryBare(value, &fee); err != nil {
    63  			return err
    64  		}
    65  		share, found := k.GetContractShare(ctx, fee.ContractAddress)
    66  		if !found {
    67  			share = k.GetParams(ctx).DeveloperShares
    68  		}
    69  		feeSplits = append(feeSplits, types.FeeSplitWithShare{
    70  			ContractAddress:   fee.ContractAddress.String(),
    71  			DeployerAddress:   fee.DeployerAddress.String(),
    72  			WithdrawerAddress: fee.WithdrawerAddress.String(),
    73  			Share:             share,
    74  		})
    75  		return nil
    76  	})
    77  	if err != nil {
    78  		return nil, sdkerrors.Wrap(sdkerrors.ErrInternal, err.Error())
    79  	}
    80  
    81  	resp := &types.QueryFeeSplitsResponse{
    82  		FeeSplits:  feeSplits,
    83  		Pagination: pageRes,
    84  	}
    85  	res, err := codec.MarshalJSONIndent(types.ModuleCdc, resp)
    86  	if err != nil {
    87  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
    88  	}
    89  	return res, nil
    90  }
    91  
    92  // queryFeeSplit returns the FeeSplit that has been registered for fee distribution for a given
    93  // contract
    94  func queryFeeSplit(
    95  	ctx sdk.Context,
    96  	req abci.RequestQuery,
    97  	k Keeper,
    98  ) ([]byte, sdk.Error) {
    99  	var params types.QueryFeeSplitRequest
   100  	err := k.cdc.UnmarshalJSON(req.Data, &params)
   101  	if err != nil {
   102  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
   103  	}
   104  
   105  	if strings.TrimSpace(params.ContractAddress) == "" {
   106  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "contract address is empty")
   107  	}
   108  
   109  	// check if the contract is a non-zero hex address
   110  	if err := types.ValidateNonZeroAddress(params.ContractAddress); err != nil {
   111  		return nil, sdkerrors.Wrap(
   112  			sdkerrors.ErrInvalidRequest,
   113  			fmt.Sprintf("invalid format for contract %s, should be non-zero hex ('0x...')", params.ContractAddress),
   114  		)
   115  	}
   116  
   117  	feeSplit, found := k.GetFeeSplit(ctx, common.HexToAddress(params.ContractAddress))
   118  	if !found {
   119  		return nil, sdkerrors.Wrap(
   120  			sdkerrors.ErrInvalidRequest,
   121  			fmt.Sprintf("not found fees registered contract '%s'", params.ContractAddress),
   122  		)
   123  	}
   124  	share, found := k.GetContractShare(ctx, feeSplit.ContractAddress)
   125  	if !found {
   126  		share = k.GetParams(ctx).DeveloperShares
   127  	}
   128  
   129  	resp := &types.QueryFeeSplitResponse{FeeSplit: types.FeeSplitWithShare{
   130  		ContractAddress:   feeSplit.ContractAddress.String(),
   131  		DeployerAddress:   feeSplit.DeployerAddress.String(),
   132  		WithdrawerAddress: feeSplit.WithdrawerAddress.String(),
   133  		Share:             share,
   134  	}}
   135  	res, err := codec.MarshalJSONIndent(types.ModuleCdc, resp)
   136  	if err != nil {
   137  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   138  	}
   139  	return res, nil
   140  }
   141  
   142  // queryParams returns the fees module params
   143  func queryParams(
   144  	ctx sdk.Context,
   145  	k Keeper,
   146  ) ([]byte, sdk.Error) {
   147  	params := k.GetParams(ctx)
   148  	res, err := codec.MarshalJSONIndent(k.cdc, types.QueryParamsResponse{Params: params})
   149  	if err != nil {
   150  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   151  	}
   152  
   153  	return res, nil
   154  }
   155  
   156  // queryDeployerFeeSplits returns all contracts that have been registered for fee
   157  // distribution by a given deployer
   158  func queryDeployerFeeSplits(
   159  	ctx sdk.Context,
   160  	req abci.RequestQuery,
   161  	k Keeper,
   162  ) ([]byte, sdk.Error) {
   163  	var params types.QueryDeployerFeeSplitsRequest
   164  	err := k.cdc.UnmarshalJSON(req.Data, &params)
   165  	if err != nil {
   166  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
   167  	}
   168  
   169  	if strings.TrimSpace(params.DeployerAddress) == "" {
   170  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "deployer address is empty")
   171  	}
   172  
   173  	deployer, err := sdk.AccAddressFromBech32(params.DeployerAddress)
   174  	if err != nil {
   175  		return nil, sdkerrors.Wrap(
   176  			sdkerrors.ErrInvalidRequest,
   177  			fmt.Sprintf("invalid format for deployer %s, should be bech32", params.DeployerAddress),
   178  		)
   179  	}
   180  
   181  	var contracts []string
   182  	store := prefix.NewStore(
   183  		ctx.KVStore(k.storeKey),
   184  		types.GetKeyPrefixDeployer(deployer),
   185  	)
   186  
   187  	pageRes, err := query.Paginate(store, params.Pagination, func(key, _ []byte) error {
   188  		contracts = append(contracts, common.BytesToAddress(key).Hex())
   189  		return nil
   190  	})
   191  	if err != nil {
   192  		return nil, sdkerrors.Wrap(sdkerrors.ErrInternal, err.Error())
   193  	}
   194  
   195  	resp := &types.QueryDeployerFeeSplitsResponse{
   196  		ContractAddresses: contracts,
   197  		Pagination:        pageRes,
   198  	}
   199  	res, err := codec.MarshalJSONIndent(types.ModuleCdc, resp)
   200  	if err != nil {
   201  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   202  	}
   203  	return res, nil
   204  }
   205  
   206  // queryDeployerFeeSplitsDetail returns all contracts with feesplit info that have been registered for fee
   207  // distribution by a given deployer
   208  func queryDeployerFeeSplitsDetail(
   209  	ctx sdk.Context,
   210  	req abci.RequestQuery,
   211  	k Keeper,
   212  ) ([]byte, sdk.Error) {
   213  	var params types.QueryDeployerFeeSplitsRequest
   214  	err := k.cdc.UnmarshalJSON(req.Data, &params)
   215  	if err != nil {
   216  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
   217  	}
   218  
   219  	if strings.TrimSpace(params.DeployerAddress) == "" {
   220  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "deployer address is empty")
   221  	}
   222  
   223  	deployer, err := sdk.AccAddressFromBech32(params.DeployerAddress)
   224  	if err != nil {
   225  		return nil, sdkerrors.Wrap(
   226  			sdkerrors.ErrInvalidRequest,
   227  			fmt.Sprintf("invalid format for deployer %s, should be bech32", params.DeployerAddress),
   228  		)
   229  	}
   230  
   231  	var contracts []common.Address
   232  	store := prefix.NewStore(
   233  		ctx.KVStore(k.storeKey),
   234  		types.GetKeyPrefixDeployer(deployer),
   235  	)
   236  
   237  	pageRes, err := query.Paginate(store, params.Pagination, func(key, _ []byte) error {
   238  		contracts = append(contracts, common.BytesToAddress(key))
   239  		return nil
   240  	})
   241  	if err != nil {
   242  		return nil, sdkerrors.Wrap(sdkerrors.ErrInternal, err.Error())
   243  	}
   244  
   245  	var feeSplits []types.FeeSplitWithShare
   246  	for _, contract := range contracts {
   247  		feeSplit, found := k.GetFeeSplit(ctx, contract)
   248  		if !found {
   249  			continue
   250  		}
   251  		share, found := k.GetContractShare(ctx, feeSplit.ContractAddress)
   252  		if !found {
   253  			share = k.GetParams(ctx).DeveloperShares
   254  		}
   255  
   256  		feeSplits = append(feeSplits, types.FeeSplitWithShare{
   257  			ContractAddress:   feeSplit.ContractAddress.String(),
   258  			DeployerAddress:   feeSplit.DeployerAddress.String(),
   259  			WithdrawerAddress: feeSplit.WithdrawerAddress.String(),
   260  			Share:             share,
   261  		})
   262  	}
   263  
   264  	if len(feeSplits) == 0 {
   265  		return nil, sdkerrors.Wrap(
   266  			sdkerrors.ErrInvalidRequest,
   267  			fmt.Sprintf("not found fees registered contract for deployer '%s'", params.DeployerAddress),
   268  		)
   269  	}
   270  	resp := &types.QueryDeployerFeeSplitsResponseV2{
   271  		FeeSplits:  feeSplits,
   272  		Pagination: pageRes,
   273  	}
   274  	res, err := codec.MarshalJSONIndent(types.ModuleCdc, resp)
   275  	if err != nil {
   276  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   277  	}
   278  	return res, nil
   279  }
   280  
   281  // queryWithdrawerFeeSplits returns all fees for a given withdraw address
   282  func queryWithdrawerFeeSplits(
   283  	ctx sdk.Context,
   284  	req abci.RequestQuery,
   285  	k Keeper,
   286  ) ([]byte, sdk.Error) {
   287  	var params types.QueryWithdrawerFeeSplitsRequest
   288  	err := k.cdc.UnmarshalJSON(req.Data, &params)
   289  	if err != nil {
   290  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
   291  	}
   292  
   293  	if strings.TrimSpace(params.WithdrawerAddress) == "" {
   294  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "withdraw address is empty")
   295  	}
   296  
   297  	withdrawer, err := sdk.AccAddressFromBech32(params.WithdrawerAddress)
   298  	if err != nil {
   299  		return nil, sdkerrors.Wrap(
   300  			sdkerrors.ErrInvalidRequest,
   301  			fmt.Sprintf("invalid format for withdraw addr %s, should be bech32", params.WithdrawerAddress),
   302  		)
   303  	}
   304  
   305  	var contracts []string
   306  	store := prefix.NewStore(
   307  		ctx.KVStore(k.storeKey),
   308  		types.GetKeyPrefixWithdrawer(withdrawer),
   309  	)
   310  
   311  	pageRes, err := query.Paginate(store, params.Pagination, func(key, _ []byte) error {
   312  		contracts = append(contracts, common.BytesToAddress(key).Hex())
   313  
   314  		return nil
   315  	})
   316  	if err != nil {
   317  		return nil, sdkerrors.Wrap(sdkerrors.ErrInternal, err.Error())
   318  	}
   319  
   320  	resp := &types.QueryWithdrawerFeeSplitsResponse{
   321  		ContractAddresses: contracts,
   322  		Pagination:        pageRes,
   323  	}
   324  	res, err := codec.MarshalJSONIndent(types.ModuleCdc, resp)
   325  	if err != nil {
   326  		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   327  	}
   328  	return res, nil
   329  }