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/Qb-2041: Add query: TotalRewardByEpoch #308

Merged
merged 3 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
15 changes: 15 additions & 0 deletions proto/stratos/pot/v1/pot.proto
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,18 @@ message VolumeReportRecord {
(gogoproto.moretags) = "yaml:\"tx_hash\""
];
}

message TotalReward {
repeated cosmos.base.v1beta1.Coin mining_reward = 1 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "mining_reward",
(gogoproto.moretags) = "yaml:\"mining_reward\"",
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
repeated cosmos.base.v1beta1.Coin traffic_reward = 2 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "traffic_reward",
(gogoproto.moretags) = "yaml:\"traffic_reward\"",
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
15 changes: 15 additions & 0 deletions proto/stratos/pot/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ service Query {
rpc CirculationSupply(QueryCirculationSupplyRequest) returns (QueryCirculationSupplyResponse) {
option (google.api.http).get = "/stratos/pot/v1/circulation-supply";
}

rpc TotalRewardByEpoch(QueryTotalRewardByEpochRequest) returns (QueryTotalRewardByEpochResponse) {
option (google.api.http).get = "/stratos/pot/v1/total-reward/{epoch}";
}
}

// QueryVolumeReportRequest is request type for the Query/VolumeReport RPC method
Expand Down Expand Up @@ -142,4 +146,15 @@ message QueryCirculationSupplyResponse{
];
}

message QueryTotalRewardByEpochRequest {
int64 epoch = 1;
}

message QueryTotalRewardByEpochResponse {
TotalReward total_reward = 1 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "total_reward",
(gogoproto.moretags) = "yaml:\"total_reward\""
];
}

40 changes: 40 additions & 0 deletions x/pot/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func GetQueryCmd() *cobra.Command {
GetCmdQueryParams(),
GetCmdQueryTotalMinedTokens(),
GetCmdQueryCirculationSupply(),
GetCmdQueryTotalRewardByEpoch(),
)

return potQueryCmd
Expand Down Expand Up @@ -177,3 +178,42 @@ func checkFlagEpoch(epochStr string) (sdk.Int, error) {
epoch := sdk.NewInt(epochInt64)
return epoch, nil
}

func GetCmdQueryTotalRewardByEpoch() *cobra.Command {
cmd := &cobra.Command{
Use: "total-reward [flags]",
Short: "Query total reward by epoch",
Long: strings.TrimSpace(
fmt.Sprintf(`Query total reward by epoch.`),
),

RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

epochStr := viper.GetString(FlagEpoch)
epoch, err := checkFlagEpoch(epochStr)
if err != nil {
return err
}

result, err := queryClient.TotalRewardByEpoch(cmd.Context(), &types.QueryTotalRewardByEpochRequest{
Epoch: epoch.Int64(),
})
if err != nil {
return err
}

return clientCtx.PrintProto(result)
},
}
cmd.Flags().AddFlagSet(flagSetEpoch())
_ = cmd.MarkFlagRequired(FlagEpoch)

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
32 changes: 32 additions & 0 deletions x/pot/client/rest/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func registerQueryRoutes(clientCtx client.Context, r *mux.Router) {
r.HandleFunc("/pot/params", potParamsHandlerFn(clientCtx, types.QueryPotParams)).Methods("GET")
r.HandleFunc("/pot/total-mined-token", getTotalMinedTokenHandlerFn(clientCtx, types.QueryTotalMinedToken)).Methods("GET")
r.HandleFunc("/pot/circulation-supply", getCirculationSupplyHandlerFn(clientCtx, types.QueryCirculationSupply)).Methods("GET")
r.HandleFunc("/pot/total-reward/{epoch}", getTotalRewardByEpochHandlerFn(clientCtx, types.QueryTotalRewardByEpoch)).Methods("GET")
}

// GET request handler to query params of POT module
Expand Down Expand Up @@ -227,3 +228,34 @@ func getCirculationSupplyHandlerFn(clientCtx client.Context, queryPath string) h
rest.PostProcessResponse(w, cliCtx, res)
}
}

func getTotalRewardByEpochHandlerFn(clientCtx client.Context, queryPath string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r)
if !ok {
return
}
epochStr := mux.Vars(r)["epoch"]
epoch, ok := sdk.NewIntFromString(epochStr)
if !ok {
return
}

params := types.NewQueryTotalRewardByEpochParams(epoch)
bz, err := cliCtx.LegacyAmino.MarshalJSON(params)
if err != nil {
rest.PostProcessResponse(w, cliCtx, err.Error())
return
}

route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, queryPath)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
rest.PostProcessResponse(w, cliCtx, err.Error())
return
}

cliCtx = cliCtx.WithHeight(height)
rest.PostProcessResponse(w, cliCtx, res)
}
}
21 changes: 19 additions & 2 deletions x/pot/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

"github.com/stratosnet/stratos-chain/x/pot/types"
registerkeeper "github.com/stratosnet/stratos-chain/x/register/keeper"
registertypes "github.com/stratosnet/stratos-chain/x/register/types"
)

// Querier is used as Keeper will have duplicate methods if used directly, and gRPC names take precedence over keeper
Expand Down Expand Up @@ -132,7 +131,7 @@ func FilteredPaginate(cdc codec.Codec,
}

if limit == 0 {
limit = registertypes.QueryDefaultLimit
limit = types.QueryDefaultLimit

// count total results when the limit is zero/not supplied
countTotal = pageRequest.CountTotal
Expand Down Expand Up @@ -381,3 +380,21 @@ func (q Querier) CirculationSupply(c context.Context, _ *types.QueryCirculationS

return &types.QueryCirculationSupplyResponse{CirculationSupply: circulationSupply}, nil
}

func (q Querier) TotalRewardByEpoch(c context.Context, req *types.QueryTotalRewardByEpochRequest) (
*types.QueryTotalRewardByEpochResponse, error) {
if req == nil {
return &types.QueryTotalRewardByEpochResponse{}, status.Error(codes.InvalidArgument, "empty request")
}

epochInt64 := req.GetEpoch()
if sdk.NewInt(epochInt64).LTE(sdk.ZeroInt()) {
return &types.QueryTotalRewardByEpochResponse{}, status.Error(codes.InvalidArgument, "epoch should be positive value")
}
epoch := sdk.NewInt(epochInt64)

ctx := sdk.UnwrapSDKContext(c)

totalReward := q.GetTotalReward(ctx, epoch)
return &types.QueryTotalRewardByEpochResponse{TotalReward: totalReward}, nil
}
66 changes: 64 additions & 2 deletions x/pot/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package keeper

import (
"context"
"encoding/hex"
"errors"
"fmt"
"math"

"github.com/tendermint/tendermint/libs/log"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tendermint/tendermint/libs/log"

stratos "github.com/stratosnet/stratos-chain/types"
"github.com/stratosnet/stratos-chain/x/pot/types"
Expand Down Expand Up @@ -181,3 +185,61 @@ func (k Keeper) GetCirculationSupply(ctx sdk.Context) (circulationSupply sdk.Coi

return
}

func (k Keeper) GetTotalReward(ctx sdk.Context, epoch sdk.Int) (totalReward types.TotalReward) {
volumeReport := k.GetVolumeReport(ctx, epoch)

if volumeReport == (types.VolumeReportRecord{}) {
return types.TotalReward{}
}
hash, err := hex.DecodeString(volumeReport.TxHash)
if err != nil {
return types.TotalReward{}
}

clientCtx := client.Context{}.WithViper("")
clientCtx, err = config.ReadFromClientConfig(clientCtx)
if err != nil {
return types.TotalReward{}
}

node, err := clientCtx.GetNode()
if err != nil {
return types.TotalReward{}
}

resTx, err := node.Tx(context.Background(), hash, true)
if err != nil {
return types.TotalReward{}
}

senderAddr := k.accountKeeper.GetModuleAddress(registertypes.TotalUnissuedPrepay)
if senderAddr == nil {

panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", registertypes.TotalUnissuedPrepay))
}

trafficReward := sdk.NewCoin(k.BondDenom(ctx), sdk.ZeroInt())
txEvents := resTx.TxResult.GetEvents()
for _, event := range txEvents {
if event.Type == "coin_received" {
attributes := event.GetAttributes()
for _, attr := range attributes {
if string(attr.GetKey()) == "amount" {
received, err := sdk.ParseCoinNormalized(string(attr.GetValue()))
if err != nil {
continue
}
trafficReward = trafficReward.Add(received)
}
}
}
}
miningReward := sdk.NewCoin(types.DefaultRewardDenom, sdk.NewInt(80).MulRaw(stratos.StosToWei))
trafficReward = trafficReward.Sub(miningReward)
totalReward = types.TotalReward{
MiningReward: sdk.NewCoins(miningReward),
TrafficReward: sdk.NewCoins(trafficReward),
}
return
}
17 changes: 17 additions & 0 deletions x/pot/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func NewQuerier(k Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier {
return getTotalMinedToken(ctx, req, k, legacyQuerierCdc)
case types.QueryCirculationSupply:
return getCirculationSupply(ctx, req, k, legacyQuerierCdc)
case types.QueryTotalRewardByEpoch:
return getTotalRewardByEpoch(ctx, req, k, legacyQuerierCdc)
default:
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown pot query endpoint")
}
Expand Down Expand Up @@ -177,3 +179,18 @@ func getCirculationSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper, lega
}
return bz, nil
}

func getTotalRewardByEpoch(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) {
var params types.QueryTotalRewardByEpochParams
err := legacyQuerierCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return []byte{}, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
totalReward := k.GetTotalReward(ctx, params.Epoch)

bz, err := codec.MarshalJSONIndent(legacyQuerierCdc, totalReward)
if err != nil {
return []byte{}, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
Loading