225 lines
7.5 KiB
Go
225 lines
7.5 KiB
Go
package rest
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/context"
|
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/wire"
|
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
|
"github.com/cosmos/cosmos-sdk/x/stake/tags"
|
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
|
"github.com/pkg/errors"
|
|
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
|
)
|
|
|
|
// contains checks if the a given query contains one of the tx types
|
|
func contains(stringSlice []string, txType string) bool {
|
|
for _, word := range stringSlice {
|
|
if word == txType {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAccAddr sdk.AccAddress) (
|
|
validator types.BechValidator, httpStatusCode int, errMsg string, err error) {
|
|
|
|
keyDel := stake.GetDelegationKey(delegatorAddr, validatorAccAddr)
|
|
|
|
res, err := cliCtx.QueryStore(keyDel, storeName)
|
|
if err != nil {
|
|
return types.BechValidator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
|
|
}
|
|
|
|
if len(res) == 0 {
|
|
return types.BechValidator{}, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
|
|
if err != nil {
|
|
return types.BechValidator{}, http.StatusInternalServerError, "Error: ", err
|
|
}
|
|
if len(kvs) == 0 {
|
|
return types.BechValidator{}, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
validator, errVal := getValidatorFromAccAdrr(validatorAccAddr, kvs, cdc)
|
|
if errVal != nil {
|
|
return types.BechValidator{}, http.StatusInternalServerError, "Couldn't get info from validator. Error: ", errVal
|
|
}
|
|
return validator, http.StatusOK, "", nil
|
|
}
|
|
|
|
func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
|
|
outputDelegation DelegationWithoutRat, httpStatusCode int, errMsg string, err error) {
|
|
delegationKey := stake.GetDelegationKey(delegatorAddr, validatorAddr)
|
|
marshalledDelegation, err := cliCtx.QueryStore(delegationKey, storeName)
|
|
if err != nil {
|
|
return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
|
|
}
|
|
|
|
if len(marshalledDelegation) == 0 {
|
|
return DelegationWithoutRat{}, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
delegation, err := types.UnmarshalDelegation(cdc, delegationKey, marshalledDelegation)
|
|
if err != nil {
|
|
return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't unmarshall delegation. Error: ", err
|
|
}
|
|
|
|
outputDelegation = DelegationWithoutRat{
|
|
DelegatorAddr: delegation.DelegatorAddr,
|
|
ValidatorAddr: delegation.ValidatorAddr,
|
|
Height: delegation.Height,
|
|
Shares: delegation.Shares.FloatString(),
|
|
}
|
|
|
|
return outputDelegation, http.StatusOK, "", nil
|
|
}
|
|
|
|
func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
|
|
unbonds types.UnbondingDelegation, httpStatusCode int, errMsg string, err error) {
|
|
undelegationKey := stake.GetUBDKey(delegatorAddr, validatorAddr)
|
|
marshalledUnbondingDelegation, err := cliCtx.QueryStore(undelegationKey, storeName)
|
|
if err != nil {
|
|
return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't query unbonding-delegation. Error: ", err
|
|
}
|
|
|
|
if len(marshalledUnbondingDelegation) == 0 {
|
|
return types.UnbondingDelegation{}, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
unbondingDelegation, err := types.UnmarshalUBD(cdc, undelegationKey, marshalledUnbondingDelegation)
|
|
if err != nil {
|
|
return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't unmarshall unbonding-delegation. Error: ", err
|
|
}
|
|
return unbondingDelegation, http.StatusOK, "", nil
|
|
}
|
|
|
|
func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
|
|
regelegations types.Redelegation, httpStatusCode int, errMsg string, err error) {
|
|
|
|
keyRedelegateTo := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr)
|
|
marshalledRedelegations, err := cliCtx.QueryStore(keyRedelegateTo, storeName)
|
|
if err != nil {
|
|
return types.Redelegation{}, http.StatusInternalServerError, "couldn't query redelegation. Error: ", err
|
|
}
|
|
|
|
if len(marshalledRedelegations) == 0 {
|
|
return types.Redelegation{}, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
redelegations, err := types.UnmarshalRED(cdc, keyRedelegateTo, marshalledRedelegations)
|
|
if err != nil {
|
|
return types.Redelegation{}, http.StatusInternalServerError, "couldn't unmarshall redelegations. Error: ", err
|
|
}
|
|
|
|
return redelegations, http.StatusOK, "", nil
|
|
}
|
|
|
|
// queries staking txs
|
|
func queryTxs(node rpcclient.Client, cdc *wire.Codec, tag string, delegatorAddr string) ([]tx.Info, error) {
|
|
page := 0
|
|
perPage := 100
|
|
prove := false
|
|
query := fmt.Sprintf("%s='%s' AND %s='%s'", tags.Action, tag, tags.Delegator, delegatorAddr)
|
|
res, err := node.TxSearch(query, prove, page, perPage)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return tx.FormatTxResults(cdc, res.Txs)
|
|
}
|
|
|
|
// gets all validators
|
|
func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechValidator, error) {
|
|
validators := make([]types.BechValidator, len(validatorKVs))
|
|
for i, kv := range validatorKVs {
|
|
|
|
addr := kv.Key[1:]
|
|
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bech32Validator, err := validator.Bech32Validator()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
validators[i] = bech32Validator
|
|
}
|
|
return validators, nil
|
|
}
|
|
|
|
// gets a validator given a ValAddress
|
|
func getValidator(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) {
|
|
// parse out the validators
|
|
for _, kv := range validatorKVs {
|
|
addr := kv.Key[1:]
|
|
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
|
|
if err != nil {
|
|
return stake.BechValidator{}, err
|
|
}
|
|
|
|
ownerAddress := validator.PubKey.Address()
|
|
if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) {
|
|
bech32Validator, err := validator.Bech32Validator()
|
|
if err != nil {
|
|
return stake.BechValidator{}, err
|
|
}
|
|
|
|
return bech32Validator, nil
|
|
}
|
|
}
|
|
return stake.BechValidator{}, errors.Errorf("Couldn't find validator")
|
|
}
|
|
|
|
// gets a validator given an AccAddress
|
|
func getValidatorFromAccAdrr(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) {
|
|
// parse out the validators
|
|
for _, kv := range validatorKVs {
|
|
addr := kv.Key[1:]
|
|
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
|
|
if err != nil {
|
|
return stake.BechValidator{}, err
|
|
}
|
|
|
|
ownerAddress := validator.PubKey.Address()
|
|
if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) {
|
|
bech32Validator, err := validator.Bech32Validator()
|
|
if err != nil {
|
|
return stake.BechValidator{}, err
|
|
}
|
|
|
|
return bech32Validator, nil
|
|
}
|
|
}
|
|
return stake.BechValidator{}, errors.Errorf("Couldn't find validator")
|
|
}
|
|
|
|
// gets all Bech32 validators from a key
|
|
func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *wire.Codec) (
|
|
validators []types.BechValidator, httpStatusCode int, errMsg string, err error) {
|
|
// Get all validators using key
|
|
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
|
|
if err != nil {
|
|
return nil, http.StatusInternalServerError, "couldn't query validators. Error: ", err
|
|
}
|
|
|
|
// the query will return empty if there are no validators
|
|
if len(kvs) == 0 {
|
|
return nil, http.StatusNoContent, "", nil
|
|
}
|
|
|
|
validators, err = getValidators(kvs, cdc)
|
|
if err != nil {
|
|
return nil, http.StatusInternalServerError, "Error: ", err
|
|
}
|
|
return validators, http.StatusOK, "", nil
|
|
}
|