github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/grpc_query.go (about) 1 package keeper 2 3 import ( 4 "context" 5 "strings" 6 7 "google.golang.org/grpc/codes" 8 "google.golang.org/grpc/status" 9 10 "cosmossdk.io/store/prefix" 11 storetypes "cosmossdk.io/store/types" 12 13 "github.com/cosmos/cosmos-sdk/runtime" 14 sdk "github.com/cosmos/cosmos-sdk/types" 15 "github.com/cosmos/cosmos-sdk/types/query" 16 "github.com/cosmos/cosmos-sdk/x/staking/types" 17 ) 18 19 // Querier is used as Keeper will have duplicate methods if used directly, and gRPC names take precedence over keeper 20 type Querier struct { 21 *Keeper 22 } 23 24 var _ types.QueryServer = Querier{} 25 26 func NewQuerier(keeper *Keeper) Querier { 27 return Querier{Keeper: keeper} 28 } 29 30 // Validators queries all validators that match the given status 31 func (k Querier) Validators(ctx context.Context, req *types.QueryValidatorsRequest) (*types.QueryValidatorsResponse, error) { 32 if req == nil { 33 return nil, status.Error(codes.InvalidArgument, "empty request") 34 } 35 36 // validate the provided status, return all the validators if the status is empty 37 if req.Status != "" && !(req.Status == types.Bonded.String() || req.Status == types.Unbonded.String() || req.Status == types.Unbonding.String()) { 38 return nil, status.Errorf(codes.InvalidArgument, "invalid validator status %s", req.Status) 39 } 40 41 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 42 valStore := prefix.NewStore(store, types.ValidatorsKey) 43 44 validators, pageRes, err := query.GenericFilteredPaginate(k.cdc, valStore, req.Pagination, func(key []byte, val *types.Validator) (*types.Validator, error) { 45 if req.Status != "" && !strings.EqualFold(val.GetStatus().String(), req.Status) { 46 return nil, nil 47 } 48 49 return val, nil 50 }, func() *types.Validator { 51 return &types.Validator{} 52 }) 53 if err != nil { 54 return nil, status.Error(codes.Internal, err.Error()) 55 } 56 57 vals := types.Validators{} 58 for _, val := range validators { 59 vals.Validators = append(vals.Validators, *val) 60 } 61 62 return &types.QueryValidatorsResponse{Validators: vals.Validators, Pagination: pageRes}, nil 63 } 64 65 // Validator queries validator info for given validator address 66 func (k Querier) Validator(ctx context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) { 67 if req == nil { 68 return nil, status.Error(codes.InvalidArgument, "empty request") 69 } 70 71 if req.ValidatorAddr == "" { 72 return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") 73 } 74 75 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 76 if err != nil { 77 return nil, err 78 } 79 80 validator, err := k.GetValidator(ctx, valAddr) 81 if err != nil { 82 return nil, status.Errorf(codes.NotFound, "validator %s not found", req.ValidatorAddr) 83 } 84 85 return &types.QueryValidatorResponse{Validator: validator}, nil 86 } 87 88 // ValidatorDelegations queries delegate info for given validator 89 func (k Querier) ValidatorDelegations(ctx context.Context, req *types.QueryValidatorDelegationsRequest) (*types.QueryValidatorDelegationsResponse, error) { 90 if req == nil { 91 return nil, status.Error(codes.InvalidArgument, "empty request") 92 } 93 94 if req.ValidatorAddr == "" { 95 return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") 96 } 97 98 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 99 if err != nil { 100 return nil, err 101 } 102 103 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 104 delStore := prefix.NewStore(store, types.GetDelegationsByValPrefixKey(valAddr)) 105 106 var ( 107 dels types.Delegations 108 pageRes *query.PageResponse 109 ) 110 pageRes, err = query.Paginate(delStore, req.Pagination, func(delAddr, value []byte) error { 111 bz := store.Get(types.GetDelegationKey(delAddr, valAddr)) 112 113 var delegation types.Delegation 114 err = k.cdc.Unmarshal(bz, &delegation) 115 if err != nil { 116 return err 117 } 118 119 dels = append(dels, delegation) 120 return nil 121 }) 122 if err != nil { 123 delegations, pageResponse, err := k.getValidatorDelegationsLegacy(ctx, req) 124 if err != nil { 125 return nil, status.Error(codes.Internal, err.Error()) 126 } 127 128 dels = types.Delegations{} 129 for _, d := range delegations { 130 dels = append(dels, *d) 131 } 132 133 pageRes = pageResponse 134 } 135 136 delResponses, err := delegationsToDelegationResponses(ctx, k.Keeper, dels) 137 if err != nil { 138 return nil, status.Error(codes.Internal, err.Error()) 139 } 140 141 return &types.QueryValidatorDelegationsResponse{ 142 DelegationResponses: delResponses, Pagination: pageRes, 143 }, nil 144 } 145 146 func (k Querier) getValidatorDelegationsLegacy(ctx context.Context, req *types.QueryValidatorDelegationsRequest) ([]*types.Delegation, *query.PageResponse, error) { 147 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 148 149 valStore := prefix.NewStore(store, types.DelegationKey) 150 return query.GenericFilteredPaginate(k.cdc, valStore, req.Pagination, func(key []byte, delegation *types.Delegation) (*types.Delegation, error) { 151 _, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 152 if err != nil { 153 return nil, err 154 } 155 156 if !strings.EqualFold(delegation.GetValidatorAddr(), req.ValidatorAddr) { 157 return nil, nil 158 } 159 160 return delegation, nil 161 }, func() *types.Delegation { 162 return &types.Delegation{} 163 }) 164 } 165 166 // ValidatorUnbondingDelegations queries unbonding delegations of a validator 167 func (k Querier) ValidatorUnbondingDelegations(ctx context.Context, req *types.QueryValidatorUnbondingDelegationsRequest) (*types.QueryValidatorUnbondingDelegationsResponse, error) { 168 if req == nil { 169 return nil, status.Error(codes.InvalidArgument, "empty request") 170 } 171 172 if req.ValidatorAddr == "" { 173 return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") 174 } 175 var ubds types.UnbondingDelegations 176 177 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 178 if err != nil { 179 return nil, err 180 } 181 182 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 183 srcValPrefix := types.GetUBDsByValIndexKey(valAddr) 184 ubdStore := prefix.NewStore(store, srcValPrefix) 185 pageRes, err := query.Paginate(ubdStore, req.Pagination, func(key, value []byte) error { 186 storeKey := types.GetUBDKeyFromValIndexKey(append(srcValPrefix, key...)) 187 storeValue := store.Get(storeKey) 188 189 ubd, err := types.UnmarshalUBD(k.cdc, storeValue) 190 if err != nil { 191 return err 192 } 193 ubds = append(ubds, ubd) 194 return nil 195 }) 196 if err != nil { 197 return nil, status.Error(codes.Internal, err.Error()) 198 } 199 200 return &types.QueryValidatorUnbondingDelegationsResponse{ 201 UnbondingResponses: ubds, 202 Pagination: pageRes, 203 }, nil 204 } 205 206 // Delegation queries delegate info for given validator delegator pair 207 func (k Querier) Delegation(ctx context.Context, req *types.QueryDelegationRequest) (*types.QueryDelegationResponse, error) { 208 if req == nil { 209 return nil, status.Error(codes.InvalidArgument, "empty request") 210 } 211 212 if req.DelegatorAddr == "" { 213 return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty") 214 } 215 if req.ValidatorAddr == "" { 216 return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") 217 } 218 219 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 220 if err != nil { 221 return nil, err 222 } 223 224 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 225 if err != nil { 226 return nil, err 227 } 228 229 delegation, err := k.GetDelegation(ctx, delAddr, valAddr) 230 if err != nil { 231 return nil, status.Errorf( 232 codes.NotFound, 233 "delegation with delegator %s not found for validator %s", 234 req.DelegatorAddr, req.ValidatorAddr) 235 } 236 237 delResponse, err := delegationToDelegationResponse(ctx, k.Keeper, delegation) 238 if err != nil { 239 return nil, status.Error(codes.Internal, err.Error()) 240 } 241 242 return &types.QueryDelegationResponse{DelegationResponse: &delResponse}, nil 243 } 244 245 // UnbondingDelegation queries unbonding info for given validator delegator pair 246 func (k Querier) UnbondingDelegation(ctx context.Context, req *types.QueryUnbondingDelegationRequest) (*types.QueryUnbondingDelegationResponse, error) { 247 if req == nil { 248 return nil, status.Errorf(codes.InvalidArgument, "empty request") 249 } 250 251 if req.DelegatorAddr == "" { 252 return nil, status.Errorf(codes.InvalidArgument, "delegator address cannot be empty") 253 } 254 if req.ValidatorAddr == "" { 255 return nil, status.Errorf(codes.InvalidArgument, "validator address cannot be empty") 256 } 257 258 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 259 if err != nil { 260 return nil, err 261 } 262 263 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 264 if err != nil { 265 return nil, err 266 } 267 268 unbond, err := k.GetUnbondingDelegation(ctx, delAddr, valAddr) 269 if err != nil { 270 return nil, status.Errorf( 271 codes.NotFound, 272 "unbonding delegation with delegator %s not found for validator %s", 273 req.DelegatorAddr, req.ValidatorAddr) 274 } 275 276 return &types.QueryUnbondingDelegationResponse{Unbond: unbond}, nil 277 } 278 279 // DelegatorDelegations queries all delegations of a given delegator address 280 func (k Querier) DelegatorDelegations(ctx context.Context, req *types.QueryDelegatorDelegationsRequest) (*types.QueryDelegatorDelegationsResponse, error) { 281 if req == nil { 282 return nil, status.Errorf(codes.InvalidArgument, "empty request") 283 } 284 285 if req.DelegatorAddr == "" { 286 return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty") 287 } 288 var delegations types.Delegations 289 290 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 291 if err != nil { 292 return nil, err 293 } 294 295 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 296 delStore := prefix.NewStore(store, types.GetDelegationsKey(delAddr)) 297 pageRes, err := query.Paginate(delStore, req.Pagination, func(key, value []byte) error { 298 delegation, err := types.UnmarshalDelegation(k.cdc, value) 299 if err != nil { 300 return err 301 } 302 delegations = append(delegations, delegation) 303 return nil 304 }) 305 if err != nil { 306 return nil, status.Error(codes.Internal, err.Error()) 307 } 308 309 delegationResps, err := delegationsToDelegationResponses(ctx, k.Keeper, delegations) 310 if err != nil { 311 return nil, status.Error(codes.Internal, err.Error()) 312 } 313 314 return &types.QueryDelegatorDelegationsResponse{DelegationResponses: delegationResps, Pagination: pageRes}, nil 315 } 316 317 // DelegatorValidator queries validator info for given delegator validator pair 318 func (k Querier) DelegatorValidator(ctx context.Context, req *types.QueryDelegatorValidatorRequest) (*types.QueryDelegatorValidatorResponse, error) { 319 if req == nil { 320 return nil, status.Error(codes.InvalidArgument, "empty request") 321 } 322 323 if req.DelegatorAddr == "" { 324 return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty") 325 } 326 if req.ValidatorAddr == "" { 327 return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") 328 } 329 330 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 331 if err != nil { 332 return nil, err 333 } 334 335 valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr) 336 if err != nil { 337 return nil, err 338 } 339 340 validator, err := k.GetDelegatorValidator(ctx, delAddr, valAddr) 341 if err != nil { 342 return nil, status.Error(codes.Internal, err.Error()) 343 } 344 345 return &types.QueryDelegatorValidatorResponse{Validator: validator}, nil 346 } 347 348 // DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address 349 func (k Querier) DelegatorUnbondingDelegations(ctx context.Context, req *types.QueryDelegatorUnbondingDelegationsRequest) (*types.QueryDelegatorUnbondingDelegationsResponse, error) { 350 if req == nil { 351 return nil, status.Error(codes.InvalidArgument, "empty request") 352 } 353 354 if req.DelegatorAddr == "" { 355 return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty") 356 } 357 var unbondingDelegations types.UnbondingDelegations 358 359 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 360 if err != nil { 361 return nil, err 362 } 363 364 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 365 unbStore := prefix.NewStore(store, types.GetUBDsKey(delAddr)) 366 pageRes, err := query.Paginate(unbStore, req.Pagination, func(key, value []byte) error { 367 unbond, err := types.UnmarshalUBD(k.cdc, value) 368 if err != nil { 369 return err 370 } 371 unbondingDelegations = append(unbondingDelegations, unbond) 372 return nil 373 }) 374 if err != nil { 375 return nil, status.Error(codes.Internal, err.Error()) 376 } 377 378 return &types.QueryDelegatorUnbondingDelegationsResponse{ 379 UnbondingResponses: unbondingDelegations, Pagination: pageRes, 380 }, nil 381 } 382 383 // HistoricalInfo queries the historical info for given height 384 func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) { 385 if req == nil { 386 return nil, status.Error(codes.InvalidArgument, "empty request") 387 } 388 389 if req.Height < 0 { 390 return nil, status.Error(codes.InvalidArgument, "height cannot be negative") 391 } 392 393 hi, err := k.GetHistoricalInfo(ctx, req.Height) 394 if err != nil { 395 return nil, status.Errorf(codes.NotFound, "historical info for height %d not found", req.Height) 396 } 397 398 return &types.QueryHistoricalInfoResponse{Hist: &hi}, nil 399 } 400 401 // Redelegations queries redelegations of given address 402 func (k Querier) Redelegations(ctx context.Context, req *types.QueryRedelegationsRequest) (*types.QueryRedelegationsResponse, error) { 403 if req == nil { 404 return nil, status.Error(codes.InvalidArgument, "empty request") 405 } 406 407 var redels types.Redelegations 408 var pageRes *query.PageResponse 409 var err error 410 411 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 412 switch { 413 case req.DelegatorAddr != "" && req.SrcValidatorAddr != "" && req.DstValidatorAddr != "": 414 redels, err = queryRedelegation(ctx, k, req) 415 case req.DelegatorAddr == "" && req.SrcValidatorAddr != "" && req.DstValidatorAddr == "": 416 redels, pageRes, err = queryRedelegationsFromSrcValidator(store, k, req) 417 default: 418 redels, pageRes, err = queryAllRedelegations(store, k, req) 419 } 420 if err != nil { 421 return nil, status.Error(codes.Internal, err.Error()) 422 } 423 redelResponses, err := redelegationsToRedelegationResponses(ctx, k.Keeper, redels) 424 if err != nil { 425 return nil, status.Error(codes.Internal, err.Error()) 426 } 427 428 return &types.QueryRedelegationsResponse{RedelegationResponses: redelResponses, Pagination: pageRes}, nil 429 } 430 431 // DelegatorValidators queries all validators info for given delegator address 432 func (k Querier) DelegatorValidators(ctx context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) { 433 if req == nil { 434 return nil, status.Error(codes.InvalidArgument, "empty request") 435 } 436 437 if req.DelegatorAddr == "" { 438 return nil, status.Error(codes.InvalidArgument, "delegator address cannot be empty") 439 } 440 var validators types.Validators 441 442 store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) 443 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 444 if err != nil { 445 return nil, err 446 } 447 448 delStore := prefix.NewStore(store, types.GetDelegationsKey(delAddr)) 449 pageRes, err := query.Paginate(delStore, req.Pagination, func(key, value []byte) error { 450 delegation, err := types.UnmarshalDelegation(k.cdc, value) 451 if err != nil { 452 return err 453 } 454 455 valAddr, err := k.validatorAddressCodec.StringToBytes(delegation.GetValidatorAddr()) 456 if err != nil { 457 return err 458 } 459 460 validator, err := k.GetValidator(ctx, valAddr) 461 if err != nil { 462 return err 463 } 464 465 validators.Validators = append(validators.Validators, validator) 466 return nil 467 }) 468 if err != nil { 469 return nil, status.Error(codes.Internal, err.Error()) 470 } 471 472 return &types.QueryDelegatorValidatorsResponse{Validators: validators.Validators, Pagination: pageRes}, nil 473 } 474 475 // Pool queries the pool info 476 func (k Querier) Pool(ctx context.Context, _ *types.QueryPoolRequest) (*types.QueryPoolResponse, error) { 477 bondDenom, err := k.BondDenom(ctx) 478 if err != nil { 479 return nil, err 480 } 481 bondedPool := k.GetBondedPool(ctx) 482 notBondedPool := k.GetNotBondedPool(ctx) 483 484 pool := types.NewPool( 485 k.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount, 486 k.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, 487 ) 488 489 return &types.QueryPoolResponse{Pool: pool}, nil 490 } 491 492 // Params queries the staking parameters 493 func (k Querier) Params(ctx context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 494 params, err := k.GetParams(ctx) 495 if err != nil { 496 return nil, err 497 } 498 return &types.QueryParamsResponse{Params: params}, nil 499 } 500 501 func queryRedelegation(ctx context.Context, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, err error) { 502 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 503 if err != nil { 504 return nil, err 505 } 506 507 srcValAddr, err := k.validatorAddressCodec.StringToBytes(req.SrcValidatorAddr) 508 if err != nil { 509 return nil, err 510 } 511 512 dstValAddr, err := k.validatorAddressCodec.StringToBytes(req.DstValidatorAddr) 513 if err != nil { 514 return nil, err 515 } 516 517 redel, err := k.GetRedelegation(ctx, delAddr, srcValAddr, dstValAddr) 518 if err != nil { 519 return nil, status.Errorf( 520 codes.NotFound, 521 "redelegation not found for delegator address %s from validator address %s", 522 req.DelegatorAddr, req.SrcValidatorAddr) 523 } 524 redels = []types.Redelegation{redel} 525 526 return redels, nil 527 } 528 529 func queryRedelegationsFromSrcValidator(store storetypes.KVStore, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, res *query.PageResponse, err error) { 530 valAddr, err := k.validatorAddressCodec.StringToBytes(req.SrcValidatorAddr) 531 if err != nil { 532 return nil, nil, err 533 } 534 535 srcValPrefix := types.GetREDsFromValSrcIndexKey(valAddr) 536 redStore := prefix.NewStore(store, srcValPrefix) 537 res, err = query.Paginate(redStore, req.Pagination, func(key, value []byte) error { 538 storeKey := types.GetREDKeyFromValSrcIndexKey(append(srcValPrefix, key...)) 539 storeValue := store.Get(storeKey) 540 red, err := types.UnmarshalRED(k.cdc, storeValue) 541 if err != nil { 542 return err 543 } 544 redels = append(redels, red) 545 return nil 546 }) 547 548 return redels, res, err 549 } 550 551 func queryAllRedelegations(store storetypes.KVStore, k Querier, req *types.QueryRedelegationsRequest) (redels types.Redelegations, res *query.PageResponse, err error) { 552 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(req.DelegatorAddr) 553 if err != nil { 554 return nil, nil, err 555 } 556 557 redStore := prefix.NewStore(store, types.GetREDsKey(delAddr)) 558 res, err = query.Paginate(redStore, req.Pagination, func(key, value []byte) error { 559 redelegation, err := types.UnmarshalRED(k.cdc, value) 560 if err != nil { 561 return err 562 } 563 redels = append(redels, redelegation) 564 return nil 565 }) 566 567 return redels, res, err 568 } 569 570 // util 571 572 func delegationToDelegationResponse(ctx context.Context, k *Keeper, del types.Delegation) (types.DelegationResponse, error) { 573 valAddr, err := k.validatorAddressCodec.StringToBytes(del.GetValidatorAddr()) 574 if err != nil { 575 return types.DelegationResponse{}, err 576 } 577 578 val, err := k.GetValidator(ctx, valAddr) 579 if err != nil { 580 return types.DelegationResponse{}, err 581 } 582 583 _, err = k.authKeeper.AddressCodec().StringToBytes(del.DelegatorAddress) 584 if err != nil { 585 return types.DelegationResponse{}, err 586 } 587 588 bondDenom, err := k.BondDenom(ctx) 589 if err != nil { 590 return types.DelegationResponse{}, err 591 } 592 593 return types.NewDelegationResp( 594 del.DelegatorAddress, 595 del.GetValidatorAddr(), 596 del.Shares, 597 sdk.NewCoin(bondDenom, val.TokensFromShares(del.Shares).TruncateInt()), 598 ), nil 599 } 600 601 func delegationsToDelegationResponses(ctx context.Context, k *Keeper, delegations types.Delegations) (types.DelegationResponses, error) { 602 resp := make(types.DelegationResponses, len(delegations)) 603 604 for i, del := range delegations { 605 delResp, err := delegationToDelegationResponse(ctx, k, del) 606 if err != nil { 607 return nil, err 608 } 609 610 resp[i] = delResp 611 } 612 613 return resp, nil 614 } 615 616 func redelegationsToRedelegationResponses(ctx context.Context, k *Keeper, redels types.Redelegations) (types.RedelegationResponses, error) { 617 resp := make(types.RedelegationResponses, len(redels)) 618 619 for i, redel := range redels { 620 _, err := k.validatorAddressCodec.StringToBytes(redel.ValidatorSrcAddress) 621 if err != nil { 622 return nil, err 623 } 624 valDstAddr, err := k.validatorAddressCodec.StringToBytes(redel.ValidatorDstAddress) 625 if err != nil { 626 return nil, err 627 } 628 629 _, err = k.authKeeper.AddressCodec().StringToBytes(redel.DelegatorAddress) 630 if err != nil { 631 return nil, err 632 } 633 634 val, err := k.GetValidator(ctx, valDstAddr) 635 if err != nil { 636 return nil, err 637 } 638 639 entryResponses := make([]types.RedelegationEntryResponse, len(redel.Entries)) 640 for j, entry := range redel.Entries { 641 entryResponses[j] = types.NewRedelegationEntryResponse( 642 entry.CreationHeight, 643 entry.CompletionTime, 644 entry.SharesDst, 645 entry.InitialBalance, 646 val.TokensFromShares(entry.SharesDst).TruncateInt(), 647 entry.UnbondingId, 648 ) 649 } 650 651 resp[i] = types.NewRedelegationResponse( 652 redel.DelegatorAddress, 653 redel.ValidatorSrcAddress, 654 redel.ValidatorDstAddress, 655 entryResponses, 656 ) 657 } 658 659 return resp, nil 660 }