Skip to content

Commit

Permalink
rpc(delegation): Query stakers for operator (#272)
Browse files Browse the repository at this point in the history
* introduces a command to query the delegated stakers and refine the RPC

* refine the QueryDelegatedStakersByOperator http endpoint
Remove the printing of the staker number and add the staker count to the response.
  • Loading branch information
TimmyExogenous authored Dec 30, 2024
1 parent 3b0b393 commit a928315
Show file tree
Hide file tree
Showing 36 changed files with 1,714 additions and 710 deletions.
2 changes: 1 addition & 1 deletion app/ethtest_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState,
associations := []delegationtypes.StakerToOperator{
{
Operator: operator.String(),
StakerID: stakerID,
StakerId: stakerID,
},
}
stakersByOperator := []delegationtypes.StakersByOperator{
Expand Down
2 changes: 1 addition & 1 deletion app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ func GenesisStateWithValSet(app *ExocoreApp, genesisState simapp.GenesisState,
associations := []delegationtypes.StakerToOperator{
{
Operator: operator.String(),
StakerID: stakerID,
StakerId: stakerID,
},
}
stakersByOperator := []delegationtypes.StakersByOperator{
Expand Down
2 changes: 1 addition & 1 deletion cmd/exocored/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func getTestExocoreGenesis(
)
associations = append(associations, delegationtypes.StakerToOperator{
Operator: operator.String(),
StakerID: stakerID,
StakerId: stakerID,
})
stakersByOperator = append(stakersByOperator, delegationtypes.StakersByOperator{
Key: string(assetstypes.GetJoinedStoreKey(operator.String(), assetID)),
Expand Down
28 changes: 14 additions & 14 deletions proto/exocore/assets/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ message QueryAllClientChainInfoResponse {
// QueryStakingAssetInfo is the query for getting the staking asset info.
message QueryStakingAssetInfo {
// asset_id is the asset for which the query is made.
string asset_id = 1 [(gogoproto.customname) = "AssetID"];
string asset_id = 1 ;
}

// QueryAllStakingAssetsInfo is the query for getting all staking assets info.
Expand All @@ -51,7 +51,7 @@ message QueryAllStakingAssetsInfoResponse {
// QueryStakerAssetInfo is the query for getting the staker asset info.
message QueryStakerAssetInfo {
// stake_id is the staker id for which the query is made.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1 ;
}

// QueryAssetInfoResponse is the response for the staker asset info.
Expand All @@ -63,9 +63,9 @@ message QueryAssetInfoResponse {
// QuerySpecifiedAssetAmountReq is the query for getting the staker specified asset amount.
message QuerySpecifiedAssetAmountReq {
// staker_id is the staker id for which the query is made.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1 ;
// asset_id is the asset for which the query is made.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
string asset_id = 2 ;
}

// QueryOperatorAssetInfos is the query for getting the operator asset info.
Expand All @@ -86,7 +86,7 @@ message QueryOperatorSpecifiedAssetAmountReq {
// operator_addr is the operator address for which the query is made.
string operator_addr = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// asset_id is the asset for which the query is made.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
string asset_id = 2;
}

// QueryStakerExCoreAddr is the query for getting the staker exocore address.
Expand Down Expand Up @@ -119,47 +119,47 @@ message QueryParamsResponse {
service Query {
// Params retrieves the assets module params
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/exocore/assets/v1/Params";
option (google.api.http).get = "/exocore/assets/v1/params";
}

// ClientChainInfoByIndex queries the client chain info by index.
rpc QueClientChainInfoByIndex(QueryClientChainInfo) returns (ClientChainInfo) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueClientChainInfoByIndex";
option (google.api.http).get = "/exocore/assets/v1/client_chain/{chain_index}";
}
// AllClientChainInfo queries all client chain info.
rpc QueAllClientChainInfo(QueryAllClientChainInfo) returns (QueryAllClientChainInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueAllClientChainInfo";
option (google.api.http).get = "/exocore/assets/v1/all_client_chains";
}
// StakingAssetInfo queries the staking asset info.
rpc QueStakingAssetInfo(QueryStakingAssetInfo) returns (StakingAssetInfo) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueStakingAssetInfo";
option (google.api.http).get = "/exocore/assets/v1/asset/{asset_id}";
}
// AllStakingAssetsInfo queries all staking assets info.
rpc QueAllStakingAssetsInfo(QueryAllStakingAssetsInfo) returns (QueryAllStakingAssetsInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueAllStakingAssetsInfo";
option (google.api.http).get = "/exocore/assets/v1/all_assets";
}
// StakerAssetInfos queries the staker asset info.
rpc QueStakerAssetInfos(QueryStakerAssetInfo) returns (QueryAssetInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueStakerAssetInfos";
option (google.api.http).get = "/exocore/assets/v1/staker_assets/{staker_id}";
}
// StakerSpecifiedAssetAmount queries the staker specified asset amount.
rpc QueStakerSpecifiedAssetAmount(QuerySpecifiedAssetAmountReq) returns (StakerAssetInfo) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueStakerSpecifiedAssetAmount";
option (google.api.http).get = "/exocore/assets/v1/staker_asset/{staker_id}/{asset_id}";
}
// OperatorAssetInfos queries the operator asset info.
rpc QueOperatorAssetInfos(QueryOperatorAssetInfos) returns (QueryOperatorAssetInfosResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueOperatorAssetInfos";
option (google.api.http).get = "/exocore/assets/v1/operator_assets/{operator_addr}";
}
// OperatorSpecifiedAssetAmount queries the operator specified asset amount.
rpc QueOperatorSpecifiedAssetAmount(QueryOperatorSpecifiedAssetAmountReq) returns (OperatorAssetInfo) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/assets/v1/QueStakerSpecifiedAssetAmount";
option (google.api.http).get = "/exocore/assets/v1/operator_asset/{operator_addr}/{asset_id}";
}
}
4 changes: 2 additions & 2 deletions proto/exocore/delegation/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ message StakersByOperator {
// DelegationsByStaker is a list of delegations for a single staker.
message DelegationsByStaker {
// staker_id is the staker's account address + _ + l0 chain id (hex).``
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// delegations is the list of delegations for the staker, indexed by the
// asset_id.
repeated DelegatedSingleAssetInfo delegations = 2 [(gogoproto.nullable) = false];
Expand All @@ -55,7 +55,7 @@ message DelegationsByStaker {
// StakerToOperator is the association between a staker and an operator.
message StakerToOperator {
// staker_id is the staker's account address + _ + l0 chain id (hex).
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// operator is the bech32 address of the operator.
string operator = 2;
}
50 changes: 36 additions & 14 deletions proto/exocore/delegation/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ option go_package = "github.com/ExocoreNetwork/exocore/x/delegation/types";
// by staker id and asset id.
message DelegationInfoReq {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// asset_id is the asset id.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
string asset_id = 2;
}

// StakerList is a list to save a batch of stakers
Expand Down Expand Up @@ -61,11 +61,11 @@ message QueryDelegationInfoResponse {
// SingleDelegationInfoReq is the request to obtain the single delegation information.
message SingleDelegationInfoReq {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// operator_addr is the operator address.
string operator_addr = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// asset_id is the asset id.
string asset_id = 3 [(gogoproto.customname) = "AssetID"];
string asset_id = 3;
}

// UndelegationHoldCountReq is the request to obtain the undelegation hold count.
Expand All @@ -84,9 +84,9 @@ message UndelegationHoldCountResponse {
// by staker id and asset id.
message UndelegationsReq {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// asset_id is the asset id.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
string asset_id = 2;
}

// UndelegationsByHeightReq is the request to obtain all undelegations waiting to be completed
Expand All @@ -105,7 +105,7 @@ message UndelegationRecordList {
// QueryAssociatedOperatorByStakerReq is the request to obtain the associated operator of the specified staker
message QueryAssociatedOperatorByStakerReq {
// stake_id is the staker id for which the query is made.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
}

// QueryAssociatedOperatorByStakerResponse is the response to QueryAssociatedOperatorByStakerReq
Expand All @@ -126,49 +126,71 @@ message QueryAssociatedStakersByOperatorResponse {
repeated string stakers = 1;
}

// QueryDelegatedStakersByOperatorReq is the request to obtain the delegated stakers of the specified operator
message QueryDelegatedStakersByOperatorReq {
// operator is the operator address for which the query is made.
string operator = 1;
// asset_id is the asset id.
string asset_id = 2;
}

// QueryDelegatedStakersByOperatorResponse is the response to QueryDelegatedStakersByOperatorReq
message QueryDelegatedStakersByOperatorResponse {
// count is the number of stakers
uint64 count = 1;
// stakers is the returned stakers associated to the specified operator
repeated string stakers = 2;
}

// Query is the service API for the delegation module.
service Query {
// DelegationInfo queries the delegation information for {stakerID, assetID}.
rpc QueryDelegationInfo(DelegationInfoReq) returns (QueryDelegationInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/GetDelegationInfo";
option (google.api.http).get = "/exocore/delegation/v1/delegations/{staker_id}/{asset_id}";
}
// SingleDelegationInfo queries the single delegation information for
// {chain, staker, asset, operator}.
rpc QuerySingleDelegationInfo(SingleDelegationInfoReq) returns (DelegationAmounts) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QuerySingleDelegationInfo";
option (google.api.http).get = "/exocore/delegation/v1/single_delegation/{staker_id}/{operator_addr}/{asset_id}";
}

// QueryUndelegationHoldCount queries the undelegation hold count.
rpc QueryUndelegationHoldCount(UndelegationHoldCountReq) returns (UndelegationHoldCountResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegationHoldCount/{record_key}";
option (google.api.http).get = "/exocore/delegation/v1/undelegation_hold_count/{record_key}";
}

// QueryUndelegations queries all undelegations for
// {staker, asset}.
rpc QueryUndelegations(UndelegationsReq) returns (UndelegationRecordList) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegations";
option (google.api.http).get = "/exocore/delegation/v1/undelegations/{staker_id}/{asset_id}";
}

// QueryUndelegationsByHeight queries all undelegations waiting to be completed by
// {height}.
rpc QueryUndelegationsByHeight(UndelegationsByHeightReq) returns (UndelegationRecordList) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegationsByHeight";
option (google.api.http).get = "/exocore/delegation/v1/pending_undelegations/{block_height}";
}

// QueryAssociatedOperatorByStaker queries the associated operator for the specified staker
rpc QueryAssociatedOperatorByStaker(QueryAssociatedOperatorByStakerReq) returns (QueryAssociatedOperatorByStakerResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryAssociatedOperatorByStaker";
option (google.api.http).get = "/exocore/delegation/v1/associated_operator/{staker_id}";
}

// QueryAssociatedStakersByOperator queries the associated stakers for the specified operator
rpc QueryAssociatedStakersByOperator(QueryAssociatedStakersByOperatorReq) returns (QueryAssociatedStakersByOperatorResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryAssociatedStakersByOperator/{operator}";
option (google.api.http).get = "/exocore/delegation/v1/associated_stakers/{operator}";
}

// QueryDelegatedStakersByOperator queries the delegated stakers for the specified operator
rpc QueryDelegatedStakersByOperator(QueryDelegatedStakersByOperatorReq) returns (QueryDelegatedStakersByOperatorResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/delegated_stakers/{operator}/{asset_id}";
}
}
10 changes: 5 additions & 5 deletions proto/exocore/delegation/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ message ValueField {
// DelegatedSingleAssetInfo is a single asset info that is delegated by a staker.
message DelegatedSingleAssetInfo {
// asset_id is the asset id.
string asset_id = 1 [(gogoproto.customname) = "AssetID"];
string asset_id = 1;
// since Cosmos uses an IAVL+ tree where the order of insertion affects the state root (even
// if the items are unrelated), and deserializing a protobuf map into Golang does not
// guarantee order, we cannot use a map here. Instead, we use a repeated field of key-value
Expand Down Expand Up @@ -55,17 +55,17 @@ message DelegationIncOrDecInfo {
// MsgDelegation is the delegation Msg.
message MsgDelegation {
// asset_id is the asset id.
string asset_id = 1 [(gogoproto.customname) = "AssetID"];
string asset_id = 1;
// base_info is the delegation increase or decrease request container.
DelegationIncOrDecInfo base_info = 2;
}

// UndelegationRecord is the undelegation record, keyed by a RecordKey.
message UndelegationRecord {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
string staker_id = 1;
// asset_id is the asset id.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
string asset_id = 2;
// operator_addr is the operator address.
string operator_addr = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// tx_hash is the transaction hash on the client chain.
Expand Down Expand Up @@ -106,7 +106,7 @@ message DelegationResponse {}
// MsgUndelegation is the undelegation Msg.
message MsgUndelegation {
// asset_id is the identity of the asset.
string asset_id = 1 [(gogoproto.customname) = "AssetID"];
string asset_id = 1;
// base_info is the delegation increase or decrease request container.
DelegationIncOrDecInfo base_info = 2;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/oracle/create_price.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (s *E2ETestSuite) testCreatePriceNST() {
s.moveNAndCheck(1)
ctx := context.Background()
// check stakerAssetInfo
res, err := s.network.QueryAssets().QueStakerSpecifiedAssetAmount(ctx, &assetstypes.QuerySpecifiedAssetAmountReq{StakerID: stakerID, AssetID: network.NativeAssetID})
res, err := s.network.QueryAssets().QueStakerSpecifiedAssetAmount(ctx, &assetstypes.QuerySpecifiedAssetAmountReq{StakerId: stakerID, AssetId: network.NativeAssetID})
s.Require().NoError(err)
s.Require().Equal(assetstypes.StakerAssetInfo{
TotalDepositAmount: sdkmath.NewInt(32),
Expand Down
2 changes: 1 addition & 1 deletion testutil/batch/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (m *Manager) AssetsCheck(opFuncIfCheckFail func(assetID string, asset *Asse
_, assetID := assetstypes.GetStakerIDAndAssetIDFromStr(
uint64(asset.ClientChainID), "", asset.Address.String())
req := &assetstypes.QueryStakingAssetInfo{
AssetID: assetID, // already lowercase
AssetId: assetID, // already lowercase
}
_, err := queryClient.QueStakingAssetInfo(m.ctx, req)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions testutil/batch/tx_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ func (m *Manager) QueryStakerAssetInfo(clientChainLzID uint64, stakerAddr, asset
queryClient := assettypes.NewQueryClient(m.NodeClientCtx[DefaultNodeIndex])
stakerID, assetID := assettypes.GetStakerIDAndAssetIDFromStr(clientChainLzID, stakerAddr, assetAddr)
req := &assettypes.QuerySpecifiedAssetAmountReq{
StakerID: stakerID, // already lowercase
AssetID: assetID, // already lowercase
StakerId: stakerID, // already lowercase
AssetId: assetID, // already lowercase
}
return queryClient.QueStakerSpecifiedAssetAmount(m.ctx, req)
}
Expand All @@ -48,8 +48,8 @@ func (m *Manager) QueryDelegatedAmount(clientChainLzID uint64, stakerAddr, asset
queryDelegationClient := delegationtype.NewQueryClient(m.NodeClientCtx[DefaultNodeIndex])
stakerID, assetID := assettypes.GetStakerIDAndAssetIDFromStr(clientChainLzID, stakerAddr, assetAddr)
req := &delegationtype.SingleDelegationInfoReq{
StakerID: stakerID, // already lowercase
AssetID: assetID, // already lowercase
StakerId: stakerID, // already lowercase
AssetId: assetID, // already lowercase
OperatorAddr: operatorAddr, // already lowercase
}
delegationInfo, err := queryDelegationClient.QuerySingleDelegationInfo(m.ctx, req)
Expand All @@ -58,7 +58,7 @@ func (m *Manager) QueryDelegatedAmount(clientChainLzID uint64, stakerAddr, asset
}
operatorAssetReq := &assettypes.QueryOperatorSpecifiedAssetAmountReq{
OperatorAddr: operatorAddr, // already lowercase
AssetID: assetID, // already lowercase
AssetId: assetID, // already lowercase
}
queryAssetsClient := assettypes.NewQueryClient(m.NodeClientCtx[DefaultNodeIndex])
operatorAssetInfo, err := queryAssetsClient.QueOperatorSpecifiedAssetAmount(m.ctx, operatorAssetReq)
Expand Down
2 changes: 1 addition & 1 deletion testutil/network/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ func NewGenStateDelegation(operatorAccAddresses []sdk.AccAddress, stakingAmount
stakerID, assetID := assetstypes.GetStakerIDAndAssetIDFromStr(asset.AssetBasicInfo.LayerZeroChainID, hexutil.Encode(operator), asset.AssetBasicInfo.Address)
if !stakerIDsLinked[stakerID] {
DefaultGenStateDelegation.Associations = append(DefaultGenStateDelegation.Associations, delegationtypes.StakerToOperator{
StakerID: stakerID,
StakerId: stakerID,
Operator: operator.String(),
})
stakerIDsLinked[stakerID] = true
Expand Down
4 changes: 2 additions & 2 deletions testutil/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,11 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc
associations := []delegationtypes.StakerToOperator{
{
Operator: operator1.String(),
StakerID: stakerID1,
StakerId: stakerID1,
},
{
Operator: operator2.String(),
StakerID: stakerID2,
StakerId: stakerID2,
},
}
stakersByOperator := []delegationtypes.StakersByOperator{
Expand Down
Loading

0 comments on commit a928315

Please sign in to comment.