Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Merge PR #29: Standard Tx and Query Commands
Browse files Browse the repository at this point in the history
* WIP all the commands

* Continue cleanup and standardization

* Merge PR #30: add an output flag 

Co-authored-by: Jack Zampolin <[email protected]>

* Address issue #9

* Merge PR #31: show balances across configured chains

* add a minimal and naive way to show balances across active chains that have been added + validation

* Update cmd/chains.go

Co-authored-by: Jack Zampolin <[email protected]>

* address comments

* crosschainbank -> crosschain with aliases
* add command structure similar to other subcommands with bank >
  balances
* add spacing between print output
* default shows the denom: balance, can be overridden with `--combined`
  for a global balance view

Co-authored-by: Jack Zampolin <[email protected]>

* Resolve registry related TODOs (#36)

* refactor registry code

Co-authored-by: Jack Zampolin <[email protected]>

* commit work

* Add context to queries and standardize, wrap up bank queries

* Fix build

Co-authored-by: Logan Henderson <[email protected]>
Co-authored-by: Prasanna Gautam <[email protected]>
  • Loading branch information
3 people authored Jan 5, 2022
1 parent 3bf9edf commit 2b13131
Show file tree
Hide file tree
Showing 25 changed files with 1,264 additions and 584 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
lens.exe
.idea/
vendor/
build/
18 changes: 16 additions & 2 deletions client/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,26 @@ import (
func (cc *ChainClient) EncodeBech32AccAddr(addr sdk.AccAddress) (string, error) {
return sdk.Bech32ifyAddressBytes(cc.Config.AccountPrefix, addr)
}
func (cc *ChainClient) MustEncodeAccAddr(addr sdk.AccAddress) string {
enc, err := cc.EncodeBech32AccAddr(addr)
if err != nil {
panic(err)
}
return enc
}
func (cc *ChainClient) EncodeBech32AccPub(addr sdk.AccAddress) (string, error) {
return sdk.Bech32ifyAddressBytes(fmt.Sprintf("%s%s", cc.Config.AccountPrefix, "pub"), addr)
}
func (cc *ChainClient) EncodeBech32ValAddr(addr sdk.AccAddress) (string, error) {
func (cc *ChainClient) EncodeBech32ValAddr(addr sdk.ValAddress) (string, error) {
return sdk.Bech32ifyAddressBytes(fmt.Sprintf("%s%s", cc.Config.AccountPrefix, "valoper"), addr)
}
func (cc *ChainClient) MustEncodeValAddr(addr sdk.ValAddress) string {
enc, err := cc.EncodeBech32ValAddr(addr)
if err != nil {
panic(err)
}
return enc
}
func (cc *ChainClient) EncodeBech32ValPub(addr sdk.AccAddress) (string, error) {
return sdk.Bech32ifyAddressBytes(fmt.Sprintf("%s%s", cc.Config.AccountPrefix, "valoperpub"), addr)
}
Expand All @@ -31,7 +45,7 @@ func (cc *ChainClient) DecodeBech32AccAddr(addr string) (sdk.AccAddress, error)
func (cc *ChainClient) DecodeBech32AccPub(addr string) (sdk.AccAddress, error) {
return sdk.GetFromBech32(addr, fmt.Sprintf("%s%s", cc.Config.AccountPrefix, "pub"))
}
func (cc *ChainClient) DecodeBech32ValAddr(addr string) (sdk.AccAddress, error) {
func (cc *ChainClient) DecodeBech32ValAddr(addr string) (sdk.ValAddress, error) {
return sdk.GetFromBech32(addr, fmt.Sprintf("%s%s", cc.Config.AccountPrefix, "valoper"))
}
func (cc *ChainClient) DecodeBech32ValPub(addr string) (sdk.AccAddress, error) {
Expand Down
27 changes: 26 additions & 1 deletion client/chain_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ func (cc *ChainClient) PrintTxResponse(res *sdk.TxResponse) error {
return cc.PrintObject(res)
}

func (cc *ChainClient) HandleAndPrintMsgSend(res *sdk.TxResponse, err error) error {
if err != nil {
if res != nil {
return fmt.Errorf("failed to withdraw rewards: code(%d) msg(%s)", res.Code, res.Logs)
}
return fmt.Errorf("failed to withdraw rewards: err(%w)", err)
}
return cc.PrintTxResponse(res)
}

func (cc *ChainClient) PrintObject(res interface{}) error {
var (
bz []byte
Expand All @@ -91,7 +101,7 @@ func (cc *ChainClient) PrintObject(res interface{}) error {
if err != nil {
return err
}
case "json-indent":
case "indent":
if m, ok := res.(proto.Message); ok {
bz, err = cc.MarshalProto(m)
if err != nil {
Expand Down Expand Up @@ -144,3 +154,18 @@ func NewRPCClient(addr string, timeout time.Duration) (*rpchttp.HTTP, error) {
}
return rpcClient, nil
}

// AccountFromKeyOrAddress returns an account from either a key or an address
// if empty string is passed in this returns the default key's address
func (cc *ChainClient) AccountFromKeyOrAddress(keyOrAddress string) (out sdk.AccAddress, err error) {
switch {
case keyOrAddress == "":
out, err = cc.GetKeyAddress()
case cc.KeyExists(keyOrAddress):
cc.Config.Key = keyOrAddress
out, err = cc.GetKeyAddress()
default:
out, err = cc.DecodeBech32AccAddr(keyOrAddress)
}
return
}
107 changes: 60 additions & 47 deletions client/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (
)

// QueryBalanceWithAddress returns the amount of coins in the relayer account with address as input
func (cc *ChainClient) QueryBalanceWithAddress(address sdk.AccAddress, pageReq *query.PageRequest) (sdk.Coins, error) {
func (cc *ChainClient) QueryBalanceWithAddress(ctx context.Context, address sdk.AccAddress, pageReq *query.PageRequest) (sdk.Coins, error) {
addr, err := cc.EncodeBech32AccAddr(address)
if err != nil {
return nil, err
}
params := &bankTypes.QueryAllBalancesRequest{Address: addr, Pagination: pageReq}
res, err := bankTypes.NewQueryClient(cc).AllBalances(context.Background(), params)
res, err := bankTypes.NewQueryClient(cc).AllBalances(ctx, params)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -59,23 +59,23 @@ func (cc *ChainClient) QueryAccount(address sdk.AccAddress) (authtypes.AccountI,
return acc, nil
}

// QueryBalance is a helper function for query balance
func (cc *ChainClient) QueryBalance(address sdk.AccAddress, showDenoms bool) (sdk.Coins, error) {
coins, err := cc.QueryBalanceWithAddress(address, DefaultPageRequest())
// QueryBalanceWithDenomTraces is a helper function for query balance
func (cc *ChainClient) QueryBalanceWithDenomTraces(ctx context.Context, address sdk.AccAddress, pageReq *query.PageRequest) (sdk.Coins, error) {
coins, err := cc.QueryBalanceWithAddress(ctx, address, pageReq)
if err != nil {
return nil, err
}

if showDenoms {
return coins, nil
}

h, err := cc.QueryLatestHeight()
if err != nil {
return nil, err
}

dts, err := cc.QueryDenomTraces(DefaultPageRequest(), h)
// TODO: figure out how to handle this
// we don't want to expose user to this
// so maybe we need a QueryAllDenomTraces function
// that will paginate the responses automatically
dts, err := cc.QueryDenomTraces(pageReq, h)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -104,92 +104,105 @@ func (cc *ChainClient) QueryBalance(address sdk.AccAddress, showDenoms bool) (sd
return out, nil
}

func (cc *ChainClient) QueryDelegatorValidators(address sdk.AccAddress) ([]string, error) {
res, err := distTypes.NewQueryClient(cc).DelegatorValidators(context.Background(), &distTypes.QueryDelegatorValidatorsRequest{
DelegatorAddress: address.String(),
func (cc *ChainClient) QueryDelegatorValidators(ctx context.Context, address sdk.AccAddress) ([]string, error) {
res, err := distTypes.NewQueryClient(cc).DelegatorValidators(ctx, &distTypes.QueryDelegatorValidatorsRequest{
DelegatorAddress: cc.MustEncodeAccAddr(address),
})
if err != nil {
return nil, err
}
return res.Validators, nil
}

func (cc *ChainClient) QueryDistributionCommission(address string) (*distTypes.ValidatorAccumulatedCommission, error) {
func (cc *ChainClient) QueryDistributionCommission(ctx context.Context, address sdk.ValAddress) (sdk.DecCoins, error) {
valAddr, err := cc.EncodeBech32ValAddr(address)
if err != nil {
return nil, err
}
request := distTypes.QueryValidatorCommissionRequest{
ValidatorAddress: address,
ValidatorAddress: valAddr,
}
res, err := distTypes.NewQueryClient(cc).ValidatorCommission(context.Background(), &request)

res, err := distTypes.NewQueryClient(cc).ValidatorCommission(ctx, &request)
if err != nil {
return nil, err
}

return &res.Commission, nil
return res.Commission.Commission, nil
}

func (cc *ChainClient) QueryDistributionCommunityPool() (sdk.DecCoins, error) {
request := distTypes.QueryCommunityPoolRequest{}

res, err := distTypes.NewQueryClient(cc).CommunityPool(context.Background(), &request)

func (cc *ChainClient) QueryDistributionCommunityPool(ctx context.Context) (sdk.DecCoins, error) {
res, err := distTypes.NewQueryClient(cc).CommunityPool(ctx, &distTypes.QueryCommunityPoolRequest{})
if err != nil {
return nil, err
}

return res.Pool, err
}

func (cc *ChainClient) QueryDistributionParams() (*distTypes.Params, error) {
res, err := distTypes.NewQueryClient(cc).Params(context.Background(), &distTypes.QueryParamsRequest{})
func (cc *ChainClient) QueryDistributionParams(ctx context.Context) (*distTypes.Params, error) {
res, err := distTypes.NewQueryClient(cc).Params(ctx, &distTypes.QueryParamsRequest{})
if err != nil {
return nil, err
}

return &res.Params, nil
}

func (cc *ChainClient) QueryDistributionRewards(delegatorAddress string, validatorAddress string) (sdk.DecCoins, error) {
func (cc *ChainClient) QueryDistributionRewards(ctx context.Context, delegatorAddress sdk.AccAddress, validatorAddress sdk.ValAddress) (sdk.DecCoins, error) {
delAddr, err := cc.EncodeBech32AccAddr(delegatorAddress)
if err != nil {
return nil, err
}
valAddr, err := cc.EncodeBech32ValAddr(validatorAddress)
if err != nil {
return nil, err
}
request := distTypes.QueryDelegationRewardsRequest{
DelegatorAddress: delegatorAddress,
ValidatorAddress: validatorAddress,
DelegatorAddress: delAddr,
ValidatorAddress: valAddr,
}
res, err := distTypes.NewQueryClient(cc).DelegationRewards(context.Background(), &request)

res, err := distTypes.NewQueryClient(cc).DelegationRewards(ctx, &request)
if err != nil {
return nil, err
}

return res.Rewards, nil
}

func (cc *ChainClient) QueryDistributionSlashes(validatorAddress string, startHeight, endHeight uint64, pageReq *querytypes.PageRequest) ([]distTypes.ValidatorSlashEvent, error) {
// QueryDistributionSlashes returns all slashes of a validator, optionally pass the start and end height
func (cc *ChainClient) QueryDistributionSlashes(ctx context.Context, validatorAddress sdk.ValAddress, startHeight, endHeight uint64, pageReq *querytypes.PageRequest) (*distTypes.QueryValidatorSlashesResponse, error) {
valAddr, err := cc.EncodeBech32ValAddr(validatorAddress)
if err != nil {
return nil, err
}
request := distTypes.QueryValidatorSlashesRequest{
ValidatorAddress: validatorAddress,
ValidatorAddress: valAddr,
StartingHeight: startHeight,
EndingHeight: endHeight,
Pagination: pageReq,
}
return distTypes.NewQueryClient(cc).ValidatorSlashes(ctx, &request)
}

res, err := distTypes.NewQueryClient(cc).ValidatorSlashes(context.Background(), &request)
// QueryDistributionValidatorRewards returns all the validator distribution rewards from a given height
func (cc *ChainClient) QueryDistributionValidatorRewards(ctx context.Context, validatorAddress sdk.ValAddress) (sdk.DecCoins, error) {
valAddr, err := cc.EncodeBech32ValAddr(validatorAddress)
if err != nil {
return nil, err
}

return res.Slashes, nil
}

func (cc *ChainClient) QueryDistributionValidatorRewards(validatorAddress string) (*distTypes.ValidatorOutstandingRewards, error) {
request := distTypes.QueryValidatorOutstandingRewardsRequest{
ValidatorAddress: validatorAddress,
ValidatorAddress: valAddr,
}

res, err := distTypes.NewQueryClient(cc).ValidatorOutstandingRewards(context.Background(), &request)

res, err := distTypes.NewQueryClient(cc).ValidatorOutstandingRewards(ctx, &request)
if err != nil {
return nil, err
}
return res.Rewards.Rewards, nil
}

// QueryTotalSupply returns the total supply of coins on a chain
func (cc *ChainClient) QueryTotalSupply(ctx context.Context, pageReq *query.PageRequest) (*bankTypes.QueryTotalSupplyResponse, error) {
return bankTypes.NewQueryClient(cc).TotalSupply(ctx, &bankTypes.QueryTotalSupplyRequest{Pagination: pageReq})
}

return &res.Rewards, nil
func (cc *ChainClient) QueryDenomsMetadata(ctx context.Context, pageReq *query.PageRequest) (*bankTypes.QueryDenomsMetadataResponse, error) {
return bankTypes.NewQueryClient(cc).DenomsMetadata(ctx, &bankTypes.QueryDenomsMetadataRequest{Pagination: pageReq})
}

func DefaultPageRequest() *querytypes.PageRequest {
Expand Down
20 changes: 10 additions & 10 deletions client/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (ccc *ChainClientConfig) SignMode() signing.SignMode {
return signMode
}

func (cc *ChainClient) SendMsg(ctx context.Context, msg sdk.Msg) (*sdk.TxResponse, bool, error) {
func (cc *ChainClient) SendMsg(ctx context.Context, msg sdk.Msg) (*sdk.TxResponse, error) {
return cc.SendMsgs(ctx, []sdk.Msg{msg})
}

Expand All @@ -50,18 +50,18 @@ func (cc *ChainClient) SendMsg(ctx context.Context, msg sdk.Msg) (*sdk.TxRespons
// not return an error. If a transaction is successfully sent, the result of the execution
// of that transaction will be logged. A boolean indicating if a transaction was successfully
// sent and executed successfully is returned.
func (cc *ChainClient) SendMsgs(ctx context.Context, msgs []sdk.Msg) (*sdk.TxResponse, bool, error) {
func (cc *ChainClient) SendMsgs(ctx context.Context, msgs []sdk.Msg) (*sdk.TxResponse, error) {
txf, err := cc.PrepareFactory(cc.TxFactory())
if err != nil {
return nil, false, err
return nil, err
}

// TODO: Make this work with new CalculateGas method
// TODO: This is related to GRPC client stuff?
// https://github.com/cosmos/cosmos-sdk/blob/5725659684fc93790a63981c653feee33ecf3225/client/tx/tx.go#L297
_, adjusted, err := cc.CalculateGas(txf, msgs...)
if err != nil {
return nil, false, err
return nil, err
}

// Set the gas amount on the transaction factory
Expand All @@ -70,7 +70,7 @@ func (cc *ChainClient) SendMsgs(ctx context.Context, msgs []sdk.Msg) (*sdk.TxRes
// Build the transaction builder
txb, err := tx.BuildUnsignedTx(txf, msgs...)
if err != nil {
return nil, false, err
return nil, err
}

// Attach the signature to the transaction
Expand All @@ -82,30 +82,30 @@ func (cc *ChainClient) SendMsgs(ctx context.Context, msgs []sdk.Msg) (*sdk.TxRes

done := cc.SetSDKContext()
if err = tx.Sign(txf, cc.Config.Key, txb, false); err != nil {
return nil, false, err
return nil, err
}
done()

// Generate the transaction bytes
txBytes, err := cc.Codec.TxConfig.TxEncoder()(txb.GetTx())
if err != nil {
return nil, false, err
return nil, err
}

// Broadcast those bytes
res, err := cc.BroadcastTx(ctx, txBytes)
if err != nil {
return nil, false, err
return nil, err
}

// transaction was executed, log the success or failure using the tx response code
// NOTE: error is nil, logic should use the returned error to determine if the
// transaction was successfully executed.
if res.Code != 0 {
return res, false, nil
return res, fmt.Errorf("transaction failed with code: %d", res.Code)
}

return res, true, nil
return res, nil
}

func (cc *ChainClient) PrepareFactory(txf tx.Factory) (tx.Factory, error) {
Expand Down
Loading

0 comments on commit 2b13131

Please sign in to comment.