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

feat: Client implementation #1888

Merged
merged 23 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

### Features

- [1888](https://github.com/umee-network/umee/pull/1888) Created `/sdkclient` and `/client` (umee client) packages to easy the E2E tests and external tools. Essentially, you can import that client and broadcast transactions easily.

## [v4.3.0](https://github.com/umee-network/umee/releases/tag/v4.3.0) - 2023-04-5

### Features
Expand Down
3 changes: 2 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -300,7 +301,7 @@ func New(
skipUpgradeHeights map[int64]bool,
homePath string,
invCheckPeriod uint,
encodingConfig appparams.EncodingConfig,
encodingConfig sdkparams.EncodingConfig,
appOpts servertypes.AppOptions,
wasmEnabledProposals []wasm.ProposalType,
wasmOpts []wasm.Option,
Expand Down
4 changes: 2 additions & 2 deletions app/encoding.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package app

import (
sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/std"

"github.com/umee-network/umee/v4/app/params"
)

// MakeEncodingConfig returns the application's encoding configuration with all
// types and interfaces registered.
func MakeEncodingConfig() params.EncodingConfig {
func MakeEncodingConfig() sdkparams.EncodingConfig {
encodingConfig := params.MakeEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
Expand Down
16 changes: 0 additions & 16 deletions app/params/encoding.go

This file was deleted.

18 changes: 3 additions & 15 deletions app/params/proto.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
package params

import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/cosmos/cosmos-sdk/simapp/params"
)

// MakeEncodingConfig creates an EncodingConfig for Amino-based tests.
func MakeEncodingConfig() EncodingConfig {
amino := codec.NewLegacyAmino()
interfaceRegistry := types.NewInterfaceRegistry()
marshaler := codec.NewProtoCodec(interfaceRegistry)
txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes)

return EncodingConfig{
InterfaceRegistry: interfaceRegistry,
Codec: marshaler,
TxConfig: txCfg,
Amino: amino,
}
func MakeEncodingConfig() params.EncodingConfig {
return params.MakeTestEncodingConfig()
}
41 changes: 41 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package client
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"

sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/umee-network/umee/v4/sdkclient"
)

// Client sdkclient.Client and provides umee chain specific transactions and queries.
type Client struct {
sdkclient.Client
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
}

// NewClient constructs Client object.
func NewClient(
chainID,
tmrpcEndpoint,
grpcEndpoint,
accountName,
accountMnemonic string,
gasAdjustment float64,
encCfg sdkparams.EncodingConfig,
) (Client, error) {
c, err := sdkclient.NewClient(chainID, tmrpcEndpoint, grpcEndpoint,
accountName, accountMnemonic, gasAdjustment, encCfg)
if err != nil {
return Client{}, err
}
return Client{
Client: c,
}, nil
}

func (c *Client) NewQCtx() (context.Context, context.CancelFunc) {
return c.Query.NewCtx()
}

func (c *Client) NewQCtxWithCancel() (context.Context, context.CancelFunc) {
return c.Query.NewCtxWithCancel()
}
43 changes: 43 additions & 0 deletions client/oracle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package client

import (
sdk "github.com/cosmos/cosmos-sdk/types"

oracletypes "github.com/umee-network/umee/v4/x/oracle/types"
)

func (c *Client) OracleQueryClient() oracletypes.QueryClient {
return oracletypes.NewQueryClient(c.Query.GrpcConn)
}

func (c *Client) QueryOracleParams() (oracletypes.Params, error) {
ctx, cancel := c.NewQCtx()
defer cancel()

queryResponse, err := c.OracleQueryClient().Params(ctx, &oracletypes.QueryParams{})
return queryResponse.Params, err

Check warning

Code scanning / CodeQL

Missing error check

[queryResponse](1) may be nil at this dereference because [err](2) may not have been checked.
}

func (c *Client) QueryExchangeRates() ([]sdk.DecCoin, error) {
ctx, cancel := c.NewQCtx()
defer cancel()

queryResponse, err := c.OracleQueryClient().ExchangeRates(ctx, &oracletypes.QueryExchangeRates{})
return queryResponse.ExchangeRates, err

Check warning

Code scanning / CodeQL

Missing error check

[queryResponse](1) may be nil at this dereference because [err](2) may not have been checked.
}

func (c *Client) QueryMedians() ([]oracletypes.Price, error) {
ctx, cancel := c.NewQCtx()
defer cancel()

resp, err := c.OracleQueryClient().Medians(ctx, &oracletypes.QueryMedians{})
return resp.Medians, err

Check warning

Code scanning / CodeQL

Missing error check

[resp](1) may be nil at this dereference because [err](2) may not have been checked.
}

func (c *Client) QueryMedianDeviations() ([]oracletypes.Price, error) {
ctx, cancel := c.NewQCtx()
defer cancel()

queryResponse, err := c.OracleQueryClient().MedianDeviations(ctx, &oracletypes.QueryMedianDeviations{})
return queryResponse.MedianDeviations, err

Check warning

Code scanning / CodeQL

Missing error check

[queryResponse](1) may be nil at this dereference because [err](2) may not have been checked.
}
3 changes: 2 additions & 1 deletion cmd/umeed/cmd/app_creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/snapshots"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/store"
Expand All @@ -29,7 +30,7 @@ import (
)

type appCreator struct {
encCfg appparams.EncodingConfig
encCfg sdkparams.EncodingConfig
moduleManager module.BasicManager
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/umeed/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/server"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
Expand All @@ -29,7 +30,7 @@ import (
)

// NewRootCmd returns the root command handler for the Umee daemon.
func NewRootCmd() (*cobra.Command, appparams.EncodingConfig) {
func NewRootCmd() (*cobra.Command, sdkparams.EncodingConfig) {
encodingConfig := umeeapp.MakeEncodingConfig()
moduleManager := umeeapp.ModuleBasics

Expand Down
33 changes: 16 additions & 17 deletions tests/grpc/chain_height.go → sdkclient/chain_height.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package grpc
package sdkclient

import (
"context"
Expand All @@ -16,11 +16,11 @@ var (
queryEventNewBlockHeader = tmtypes.QueryForEvent(tmtypes.EventNewBlockHeader)
)

// ChainHeight is used to cache the chain height of the
// ChainHeightListener is used to cache the chain height of the
// current node which is being updated each time the
// node sends an event of EventNewBlockHeader.
// It starts a goroutine to subscribe to blockchain new block event and update the cached height.
type ChainHeight struct {
type ChainHeightListener struct {
Logger zerolog.Logger

mtx sync.RWMutex
Expand All @@ -31,11 +31,11 @@ type ChainHeight struct {

// NewChainHeight returns a new ChainHeight struct that
// starts a new goroutine subscribed to EventNewBlockHeader.
func NewChainHeight(
func NewChainHeightListener(
ctx context.Context,
rpcClient tmrpcclient.Client,
logger zerolog.Logger,
) (*ChainHeight, error) {
) (*ChainHeightListener, error) {
if !rpcClient.IsRunning() {
if err := rpcClient.Start(); err != nil {
return nil, err
Expand All @@ -47,19 +47,18 @@ func NewChainHeight(
if err != nil {
return nil, err
}

chainHeight := &ChainHeight{
Logger: logger.With().Str("oracle_client", "chain_height").Logger(),
chainHeight := &ChainHeightListener{
Logger: logger.With().Str("app_client", "chain_height").Logger(),
HeightChanged: make(chan int64),
}
chainHeight.HeightChanged = make(chan int64)

go chainHeight.subscribe(ctx, rpcClient, newBlockHeaderSubscription)

Check notice

Code scanning / CodeQL

Spawning a Go routine

Spawning a Go routine may be a possible source of non-determinism

return chainHeight, nil
}

// updateChainHeight receives the data to be updated thread safe.
func (chainHeight *ChainHeight) updateChainHeight(blockHeight int64, err error) {
// setChainHeight receives the data to be updated thread safe.
func (chainHeight *ChainHeightListener) setChainHeight(blockHeight int64, err error) {
chainHeight.mtx.Lock()
defer chainHeight.mtx.Unlock()

Expand All @@ -75,7 +74,7 @@ func (chainHeight *ChainHeight) updateChainHeight(blockHeight int64, err error)

// subscribe listens to new blocks being made
// and updates the chain height.
func (chainHeight *ChainHeight) subscribe(
func (chainHeight *ChainHeightListener) subscribe(
ctx context.Context,
eventsClient tmrpcclient.EventsClient,
newBlockHeaderSubscription <-chan tmctypes.ResultEvent,
Expand All @@ -86,7 +85,7 @@ func (chainHeight *ChainHeight) subscribe(
err := eventsClient.Unsubscribe(ctx, tmtypes.EventNewBlockHeader, queryEventNewBlockHeader.String())
if err != nil {
chainHeight.Logger.Err(err)
chainHeight.updateChainHeight(chainHeight.lastChainHeight, err)
chainHeight.setChainHeight(chainHeight.lastChainHeight, err)
}
chainHeight.Logger.Info().Msg("closing the ChainHeight subscription")
return
Expand All @@ -95,16 +94,16 @@ func (chainHeight *ChainHeight) subscribe(
eventDataNewBlockHeader, ok := resultEvent.Data.(tmtypes.EventDataNewBlockHeader)
if !ok {
chainHeight.Logger.Err(errParseEventDataNewBlockHeader)
chainHeight.updateChainHeight(chainHeight.lastChainHeight, errParseEventDataNewBlockHeader)
chainHeight.setChainHeight(chainHeight.lastChainHeight, errParseEventDataNewBlockHeader)
continue
}
chainHeight.updateChainHeight(eventDataNewBlockHeader.Header.Height, nil)
chainHeight.setChainHeight(eventDataNewBlockHeader.Header.Height, nil)
}
}
}

// GetChainHeight returns the last chain height available.
func (chainHeight *ChainHeight) GetChainHeight() (int64, error) {
// GetHeight returns the last chain height available.
func (chainHeight *ChainHeightListener) GetHeight() (int64, error) {
chainHeight.mtx.RLock()
defer chainHeight.mtx.RUnlock()

Expand Down
51 changes: 51 additions & 0 deletions sdkclient/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package sdkclient

import (
"context"
"time"

sdkparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/rs/zerolog"
rpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/umee-network/umee/v4/sdkclient/query"
"github.com/umee-network/umee/v4/sdkclient/tx"
)

// Client provides basic capabilities to connect to a Cosmos SDK based chain and execute
// transactions and queries. The object should be extended by another struct to provide
// chain specific transactions and queries. Example:
// https://github.com/umee-network/umee/blob/main/client
type Client struct {
Query *query.Client
Tx *tx.Client
}

func NewClient(
chainID,
tmrpcEndpoint,
grpcEndpoint,
accountName,
accountMnemonic string,
gasAdjustment float64,
encCfg sdkparams.EncodingConfig,
) (uc Client, err error) {
uc = Client{}
uc.Query, err = query.NewClient(grpcEndpoint, 15*time.Second)
if err != nil {
return Client{}, err
}
uc.Tx, err = tx.NewClient(chainID, tmrpcEndpoint, accountName, accountMnemonic, gasAdjustment, encCfg)
return uc, err
}

func (c Client) NewChainHeightListener(ctx context.Context, logger zerolog.Logger) (*ChainHeightListener, error) {
return NewChainHeightListener(ctx, c.Tx.ClientContext.Client, logger)
}

func (c Client) QueryTimeout() time.Duration {
return c.Query.QueryTimeout
}

func (c Client) TmClient() rpcclient.Client {
return c.Tx.ClientContext.Client
}
Loading