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

Issue 1525: sub-section: combine superfluid query and staking query on querying delegation by delegator #1539

Merged
merged 16 commits into from
Jun 30, 2022
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1312] Stableswap: Createpool logic
* [#1230] Stableswap CFMM equations
* [#1429] solver for multi-asset CFMM
* [#1539] Superfluid: Combine superfluid and staking query on querying delegation by delegator

### Bug Fixes
* [1700](https://github.com/osmosis-labs/osmosis/pull/1700) Upgrade sdk fork with missing snapshot manager fix.
Expand Down
35 changes: 35 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@
- [ConnectedIntermediaryAccountResponse](#osmosis.superfluid.ConnectedIntermediaryAccountResponse)
- [EstimateSuperfluidDelegatedAmountByValidatorDenomRequest](#osmosis.superfluid.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest)
- [EstimateSuperfluidDelegatedAmountByValidatorDenomResponse](#osmosis.superfluid.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse)
- [QueryDelegationRequest](#osmosis.superfluid.QueryDelegationRequest)
- [QueryDelegationResponse](#osmosis.superfluid.QueryDelegationResponse)
- [QueryParamsRequest](#osmosis.superfluid.QueryParamsRequest)
- [QueryParamsResponse](#osmosis.superfluid.QueryParamsResponse)
- [SuperfluidDelegationAmountRequest](#osmosis.superfluid.SuperfluidDelegationAmountRequest)
Expand Down Expand Up @@ -3610,6 +3612,38 @@ assets



<a name="osmosis.superfluid.QueryDelegationRequest"></a>

### QueryDelegationRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `delegator_address` | [string](#string) | | |






<a name="osmosis.superfluid.QueryDelegationResponse"></a>

### QueryDelegationResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `superfluid_delegation_records` | [SuperfluidDelegationRecord](#osmosis.superfluid.SuperfluidDelegationRecord) | repeated | |
| `delegation_response` | [cosmos.staking.v1beta1.DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | repeated | |
| `total_delegated_coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |






<a name="osmosis.superfluid.QueryParamsRequest"></a>

### QueryParamsRequest
Expand Down Expand Up @@ -3831,6 +3865,7 @@ Query defines the gRPC querier service.
| `SuperfluidUndelegationsByDelegator` | [SuperfluidUndelegationsByDelegatorRequest](#osmosis.superfluid.SuperfluidUndelegationsByDelegatorRequest) | [SuperfluidUndelegationsByDelegatorResponse](#osmosis.superfluid.SuperfluidUndelegationsByDelegatorResponse) | | GET|/osmosis/superfluid/v1beta1/superfluid_undelegations_by_delegator/{delegator_address}|
| `SuperfluidDelegationsByValidatorDenom` | [SuperfluidDelegationsByValidatorDenomRequest](#osmosis.superfluid.SuperfluidDelegationsByValidatorDenomRequest) | [SuperfluidDelegationsByValidatorDenomResponse](#osmosis.superfluid.SuperfluidDelegationsByValidatorDenomResponse) | Returns all the superfluid positions of a specific denom delegated to one validator | GET|/osmosis/superfluid/v1beta1/superfluid_delegations_by_validator_denom|
| `EstimateSuperfluidDelegatedAmountByValidatorDenom` | [EstimateSuperfluidDelegatedAmountByValidatorDenomRequest](#osmosis.superfluid.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest) | [EstimateSuperfluidDelegatedAmountByValidatorDenomResponse](#osmosis.superfluid.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse) | Returns the amount of a specific denom delegated to a specific validator This is labeled an estimate, because the way it calculates the amount can lead rounding errors from the true delegated amount | GET|/osmosis/superfluid/v1beta1/estimate_superfluid_delegation_amount_by_validator_denom|
| `Delegation` | [QueryDelegationRequest](#osmosis.superfluid.QueryDelegationRequest) | [QueryDelegationResponse](#osmosis.superfluid.QueryDelegationResponse) | | GET|/osmosis/superfluid/v1beta1/delegation/{delegator_address}|

<!-- end services -->

Expand Down
30 changes: 29 additions & 1 deletion proto/osmosis/superfluid/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "osmosis/superfluid/superfluid.proto";
import "osmosis/superfluid/params.proto";
import "osmosis/lockup/lock.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "cosmos/staking/v1beta1/staking.proto";

option go_package = "github.com/osmosis-labs/osmosis/v7/x/superfluid/types";

Expand Down Expand Up @@ -112,6 +113,12 @@ service Query {
// option (google.api.http).get =
// "/osmosis/superfluid/v1beta1/superfluid_unbondings_by_validator_denom";
// }

nghuyenthevinh2000 marked this conversation as resolved.
Show resolved Hide resolved
// Returns the specified delegations for a specific delegator
rpc TotalDelegationByDelegator (QueryTotalDelegationByDelegatorRequest) returns (QueryTotalDelegationByDelegatorResponse) {
option (google.api.http).get = "/osmosis/superfluid/v1beta1/"
"total_delegation_by_delegator/{delegator_address}";
}
}

message QueryParamsRequest {}
Expand Down Expand Up @@ -256,4 +263,25 @@ message EstimateSuperfluidDelegatedAmountByValidatorDenomResponse {
// (gogoproto.nullable) = false,
// (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
// ];
// }
// }

message QueryTotalDelegationByDelegatorRequest {
string delegator_address = 1;
}

message QueryTotalDelegationByDelegatorResponse {
repeated SuperfluidDelegationRecord superfluid_delegation_records = 1
[ (gogoproto.nullable) = false ];

repeated cosmos.staking.v1beta1.DelegationResponse delegation_response = 2 [
(gogoproto.nullable) = false
];
repeated cosmos.base.v1beta1.Coin total_delegated_coins = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
cosmos.base.v1beta1.Coin total_equivalent_staked_amount = 4 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
];
}
Empty file modified scripts/multinode-local-testnet.sh
100644 → 100755
Empty file.
30 changes: 30 additions & 0 deletions x/superfluid/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func GetQueryCmd() *cobra.Command {
GetCmdSuperfluidDelegationsByDelegator(),
GetCmdSuperfluidUndelegationsByDelegator(),
GetCmdTotalSuperfluidDelegations(),
GetCmdTotalDelegationByDelegator(),
)

return cmd
Expand Down Expand Up @@ -349,3 +350,32 @@ func GetCmdTotalSuperfluidDelegations() *cobra.Command {

return cmd
}

func GetCmdTotalDelegationByDelegator() *cobra.Command {
cmd := &cobra.Command{
Use: "total-delegation-by-delegator [delegator_address]",
Short: "Query both superfluid delegation and normal delegation",
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.TotalDelegationByDelegator(cmd.Context(), &types.QueryTotalDelegationByDelegatorRequest{
DelegatorAddress: args[0],
})

if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
88 changes: 88 additions & 0 deletions x/superfluid/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,91 @@ func (q Querier) TotalSuperfluidDelegations(goCtx context.Context, _ *types.Tota
TotalDelegations: totalSuperfluidDelegated,
}, nil
}

func (q Querier) TotalDelegationByDelegator(goCtx context.Context, req *types.QueryTotalDelegationByDelegatorRequest) (*types.QueryTotalDelegationByDelegatorResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if len(req.DelegatorAddress) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty delegator address")
}

ctx := sdk.UnwrapSDKContext(goCtx)

delAddr, err := sdk.AccAddressFromBech32(req.DelegatorAddress)
if err != nil {
return nil, err
}

res := types.QueryTotalDelegationByDelegatorResponse{
SuperfluidDelegationRecords: []types.SuperfluidDelegationRecord{},
DelegationResponse: []stakingtypes.DelegationResponse{},
TotalDelegatedCoins: sdk.NewCoins(),
TotalEquivalentStakedAmount: sdk.NewCoin(appparams.BaseCoinUnit, sdk.ZeroInt()),
}

syntheticLocks := q.Keeper.lk.GetAllSyntheticLockupsByAddr(ctx, delAddr)

for _, syntheticLock := range syntheticLocks {
// don't include unbonding delegations
if strings.Contains(syntheticLock.SynthDenom, "superunbonding") {
continue
}

periodLock, err := q.Keeper.lk.GetLockByID(ctx, syntheticLock.UnderlyingLockId)
if err != nil {
return nil, err
}

baseDenom := periodLock.Coins.GetDenomByIndex(0)
lockedCoins := sdk.NewCoin(baseDenom, periodLock.GetCoins().AmountOf(baseDenom))
valAddr, err := ValidatorAddressFromSyntheticDenom(syntheticLock.SynthDenom)

// Find how many osmo tokens this delegation is worth at superfluids current risk adjustment
// and twap of the denom.
equivalentAmount := q.Keeper.GetSuperfluidOSMOTokens(ctx, baseDenom, lockedCoins.Amount)
coin := sdk.NewCoin(appparams.BaseCoinUnit, equivalentAmount)

if err != nil {
return nil, err
}
res.SuperfluidDelegationRecords = append(res.SuperfluidDelegationRecords,
types.SuperfluidDelegationRecord{
DelegatorAddress: req.DelegatorAddress,
ValidatorAddress: valAddr,
DelegationAmount: lockedCoins,
EquivalentStakedAmount: &coin,
},
)
res.TotalDelegatedCoins = res.TotalDelegatedCoins.Add(lockedCoins)
res.TotalEquivalentStakedAmount = res.TotalEquivalentStakedAmount.Add(coin)
}

//this is for getting normal staking
q.sk.IterateDelegations(ctx, delAddr, func(_ int64, del stakingtypes.DelegationI) bool {
val, found := q.sk.GetValidator(ctx, del.GetValidatorAddr())
if !found {
return true
}

lockedCoins := sdk.NewCoin(appparams.BaseCoinUnit, val.TokensFromShares(del.GetShares()).TruncateInt())

res.DelegationResponse = append(res.DelegationResponse,
stakingtypes.DelegationResponse{
Delegation: stakingtypes.Delegation{
DelegatorAddress: del.GetDelegatorAddr().String(),
ValidatorAddress: del.GetValidatorAddr().String(),
Shares: del.GetShares(),
},
Balance: lockedCoins,
},
)

res.TotalDelegatedCoins = res.TotalDelegatedCoins.Add(lockedCoins)
res.TotalEquivalentStakedAmount = res.TotalEquivalentStakedAmount.Add(lockedCoins)

return false
})

return &res, nil
}
66 changes: 66 additions & 0 deletions x/superfluid/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package keeper_test

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

Expand Down Expand Up @@ -200,3 +202,67 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
suite.Require().NoError(err)
suite.Require().Equal(totalSuperfluidDelegationsRes.TotalDelegations, sdk.NewInt(30000000))
}

func (suite *KeeperTestSuite) TestGRPCQueryTotalDelegationByDelegator() {
suite.SetupTest()

// Generate delegator addresses
delAddrs := CreateRandomAccounts(2)

// setup 2 validators
valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})

denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms
superfluidDelegations := []superfluidDelegation{
{0, 0, 0, 1000000},
{0, 1, 1, 1000000},
{1, 0, 1, 1000000},
{1, 1, 0, 1000000},
}

// setup superfluid delegations
suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)

// setup normal delegations
bond0to0 := stakingtypes.NewDelegation(delAddrs[0], valAddrs[0], sdk.NewDec(9000000))
bond0to1 := stakingtypes.NewDelegation(delAddrs[0], valAddrs[1], sdk.NewDec(9000000))
bond1to0 := stakingtypes.NewDelegation(delAddrs[1], valAddrs[0], sdk.NewDec(9000000))
bond1to1 := stakingtypes.NewDelegation(delAddrs[1], valAddrs[1], sdk.NewDec(9000000))

suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond0to0)
suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond0to1)
suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond1to0)
suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond1to1)

multiplier0 := suite.querier.Keeper.GetOsmoEquivalentMultiplier(suite.Ctx, denoms[0])
multiplier1 := suite.querier.Keeper.GetOsmoEquivalentMultiplier(suite.Ctx, denoms[1])
minRiskFactor := suite.querier.Keeper.GetParams(suite.Ctx).MinimumRiskFactor

expectAmount0 := multiplier0.Mul(sdk.NewDec(1000000)).Sub(multiplier0.Mul(sdk.NewDec(1000000)).Mul(minRiskFactor))
expectAmount1 := multiplier1.Mul(sdk.NewDec(1000000)).Sub(multiplier1.Mul(sdk.NewDec(1000000)).Mul(minRiskFactor))

// for each delegator, query all their superfluid delegations and normal delegations. Making sure they have 4 delegations
// Making sure TotalEquivalentStakedAmount is equal to converted amount + normal delegations
for _, delegator := range delAddrs {
res, err := suite.queryClient.TotalDelegationByDelegator(sdk.WrapSDKContext(suite.Ctx), &types.QueryTotalDelegationByDelegatorRequest{
DelegatorAddress: delegator.String(),
})

fmt.Printf("res = %v \n", res)

suite.Require().NoError(err)
suite.Require().Len(res.SuperfluidDelegationRecords, 2)
suite.Require().Len(res.DelegationResponse, 2)
suite.Require().True(res.TotalDelegatedCoins.IsEqual(sdk.NewCoins(
sdk.NewInt64Coin(denoms[0], 1000000),
sdk.NewInt64Coin(denoms[1], 1000000),
sdk.NewInt64Coin("uosmo", 18000000),
)))

total_osmo_equivalent := sdk.NewCoin("uosmo", expectAmount0.RoundInt().Add(expectAmount1.RoundInt()).Add(sdk.NewInt(18000000)))

suite.Require().True(res.TotalEquivalentStakedAmount.IsEqual(total_osmo_equivalent))
}
}
3 changes: 2 additions & 1 deletion x/superfluid/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package keeper
import (
"fmt"

"github.com/osmosis-labs/osmosis/v7/x/superfluid/types"
"github.com/tendermint/tendermint/libs/log"

"github.com/osmosis-labs/osmosis/v7/x/superfluid/types"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
Expand Down
Loading