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

Move config parsing to use context #1

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions README.md
Expand Up @@ -9,9 +9,6 @@ Intended use cases:

This is the start of ideas around how to implement the cosmos client libraries in a seperate repo

- [ ] `lens keys` to test key integration
- [ ] `lens query` to test query integration
- [ ] `lens tx` to test tx integration
- [ ] Switch `lens` from using `var config *Config` as a global variable to a `lens.Config` struct pulled out `context` in a similar manner to the way the SDK works. This should allow for generic reuse of the `cmd` package to quickly build a new client. with standard functionality.
- [ ] How to instantiate and use the GRPC golang client? This is not not currently obvious.
- [ ] Currently we are depending on the sdk keyring libs. This is fine for now but eventually the goal is to support our own keyring implemenation that is specifically for `lens`
Expand Down
32 changes: 32 additions & 0 deletions client/context.go
@@ -0,0 +1,32 @@
package client

import (
"context"
"errors"
"fmt"
)

type contextKey string

func newContextKey(chainid string) contextKey {
return contextKey(fmt.Sprintf("chain-client-context/%s", chainid))
}

// SetChainClientToContext sets the chain client to the context
func SetChainClientOnContext(ctx context.Context, chainid string, client *ChainClient) error {
v := ctx.Value(newContextKey(chainid))
if v == nil {
return errors.New("chain client not found in context")
}
ptr := v.(*ChainClient)
*ptr = *client
return nil
}

// GetChainClientFromContext returns the chain client from the context
func GetChainClientFromContext(ctx context.Context, chainid string) *ChainClient {
if v, ok := ctx.Value(newContextKey(chainid)).(*ChainClient); ok {
return v
}
return nil
}
3 changes: 3 additions & 0 deletions client/query.go
Expand Up @@ -21,6 +21,7 @@ func (cc *ChainClient) QueryBalanceWithAddress(address sdk.AccAddress) (sdk.Coin
return res.Balances, nil
}

// QueryLatestHeight returns the latest height from the chain
func (cc *ChainClient) QueryLatestHeight() (int64, error) {
stat, err := cc.RPCClient.Status(context.Background())
if err != nil {
Expand All @@ -37,6 +38,7 @@ func (cc *ChainClient) QueryDenomTraces(pageReq *querytypes.PageRequest, height
})
}

// QueryAccount returns the account with address as input
func (cc *ChainClient) QueryAccount(address sdk.AccAddress) (authtypes.AccountI, error) {
addr, err := cc.EncodeBech32AccAddr(address)
if err != nil {
Expand Down Expand Up @@ -98,6 +100,7 @@ func (cc *ChainClient) QueryBalance(address sdk.AccAddress, showDenoms bool) (sd
return out, nil
}

// DefaultPageRequest returns a default page request
func DefaultPageRequest() *querytypes.PageRequest {
return &querytypes.PageRequest{
Key: []byte(""),
Expand Down
14 changes: 14 additions & 0 deletions client/tx.go
Expand Up @@ -19,6 +19,8 @@ import (
"google.golang.org/grpc/status"
)

// TxFactory returns a new transaction factory based on the chain client's configuration
// and the provided message.
func (cc *ChainClient) TxFactory() tx.Factory {
return tx.Factory{}.
WithAccountRetriever(cc).
Expand All @@ -30,6 +32,7 @@ func (cc *ChainClient) TxFactory() tx.Factory {
WithSignMode(cc.Config.SignMode())
}

// SignMode returns the sign mode for the chain client
func (ccc *ChainClientConfig) SignMode() signing.SignMode {
signMode := signing.SignMode_SIGN_MODE_UNSPECIFIED
switch ccc.SignModeStr {
Expand All @@ -41,6 +44,11 @@ func (ccc *ChainClientConfig) SignMode() signing.SignMode {
return signMode
}

// SendMsg wraps the msg in a StdTx, signs and sends it. An error is returned if there
// was an issue sending the transaction. A successfully sent, but failed transaction will
// 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) SendMsg(ctx context.Context, msg sdk.Msg) (*sdk.TxResponse, bool, error) {
return cc.SendMsgs(ctx, []sdk.Msg{msg})
}
Expand Down Expand Up @@ -106,6 +114,8 @@ func (cc *ChainClient) SendMsgs(ctx context.Context, msgs []sdk.Msg) (*sdk.TxRes
return res, true, nil
}

// PrepareFactory returns a new transaction factory based on the chain client's configuration
// and the provided transaction factory.
func (cc *ChainClient) PrepareFactory(txf tx.Factory) (tx.Factory, error) {
from, err := cc.GetKeyAddress()
if err != nil {
Expand Down Expand Up @@ -141,6 +151,7 @@ func (cc *ChainClient) PrepareFactory(txf tx.Factory) (tx.Factory, error) {
return txf, nil
}

// CalculateGas estimates the gas for a transaction based on TxFactory and msgs.
func (cc *ChainClient) CalculateGas(txf tx.Factory, msgs ...sdk.Msg) (txtypes.SimulateResponse, uint64, error) {
txBytes, err := BuildSimTx(txf, msgs...)
if err != nil {
Expand All @@ -165,6 +176,8 @@ func (cc *ChainClient) CalculateGas(txf tx.Factory, msgs ...sdk.Msg) (txtypes.Si
return simRes, uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed)), nil
}

// QueryABCI queries the ABCI server with the provided request. An error is returned
// if the query returns a non-zero code and the ABCI server returns a non-nil error.
func (cc *ChainClient) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) {
opts := rpcclient.ABCIQueryOptions{
Height: req.Height,
Expand All @@ -187,6 +200,7 @@ func (cc *ChainClient) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, err
return result.Response, nil
}

// sdkErrorToGRPCError converts an sdk error to a grpc error.
func sdkErrorToGRPCError(resp abci.ResponseQuery) error {
switch resp.Code {
case sdkerrors.ErrInvalidRequest.ABCICode():
Expand Down
84 changes: 58 additions & 26 deletions cmd/config.go
Expand Up @@ -84,14 +84,23 @@ func configInitCmd() *cobra.Command {

// Config represents the config file for the relayer
type Config struct {
Chain *client.ChainClientConfig
cl *client.ChainClient
DefaultChain string `yaml:"default_chain"`
Chains []*client.ChainClientConfig `yaml:"chains"`
}

// Called to initialize the relayer.Chain types on Config
func validateConfig(c *Config) error {
if err := c.Chain.Validate(); err != nil {
return err
var found bool
for _, chain := range c.Chains {
if err := chain.Validate(); err != nil {
return err
}
if c.DefaultChain == chain.ChainID {
found = true
}
}
if !found {
return fmt.Errorf("default chain %s not found in chains", c.DefaultChain)
}
return nil
}
Expand All @@ -111,22 +120,42 @@ func defaultConfig(keyHome string, debug bool) []byte {
modules = append(modules, v)
}
cfg := Config{
Chain: &client.ChainClientConfig{
Key: "default",
ChainID: "cosmoshub-4",
RPCAddr: "https://cosmoshub-4.technofractal.com:443",
GRPCAddr: "https://gprc.cosmoshub-4.technofractal.com:443",
AccountPrefix: "cosmos",
KeyringBackend: "test",
GasAdjustment: 1.2,
GasPrices: "0.01uatom",
KeyDirectory: keyHome,
Debug: debug,
Timeout: "20s",
OutputFormat: "json",
BroadcastMode: "block",
SignModeStr: "direct",
Modules: modules,
DefaultChain: "cosmoshub-4",
Chains: []*client.ChainClientConfig{
{
Key: "default",
ChainID: "cosmoshub-4",
RPCAddr: "https://cosmoshub-4.technofractal.com:443",
GRPCAddr: "https://gprc.cosmoshub-4.technofractal.com:443",
AccountPrefix: "cosmos",
KeyringBackend: "test",
GasAdjustment: 1.2,
GasPrices: "0.01uatom",
KeyDirectory: keyHome,
Debug: debug,
Timeout: "20s",
OutputFormat: "json",
BroadcastMode: "block",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should avoid using block, this was meant for testing that ended up bleeding into prod.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh interesting

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I should add a mempool query that sees if we have a TX in the mempool before trying to submit another one

SignModeStr: "direct",
Modules: modules,
},
{
Key: "default",
ChainID: "osmosis-1",
RPCAddr: "https://osmosis-1.technofractal.com:443",
GRPCAddr: "https://grpc.osmosis-1.technofractal.com:443",
AccountPrefix: "osmo",
KeyringBackend: "test",
GasAdjustment: 1.2,
GasPrices: "0.01uosmo",
KeyDirectory: keyHome,
Debug: debug,
Timeout: "20s",
OutputFormat: "json",
BroadcastMode: "block",
SignModeStr: "direct",
Modules: modules,
},
},
}
return cfg.MustYAML()
Expand Down Expand Up @@ -170,13 +199,16 @@ func initConfig(cmd *cobra.Command) error {
for _, v := range simapp.ModuleBasics {
modules = append(modules, v)
}
config.Chain.Modules = modules
cl, err := client.NewChainClient(config.Chain, os.Stdin, os.Stdout)
if err != nil {
fmt.Println("Error creating chain client:", err)
os.Exit(1)
ctx := cmd.Context()
for _, chain := range config.Chains {
chain.Modules = modules
cl, err := client.NewChainClient(chain, os.Stdin, os.Stdout)
if err != nil {
fmt.Println("Error creating chain client:", err)
os.Exit(1)
}
client.SetChainClientOnContext(ctx, chain.ChainID, cl)
}
config.cl = cl
}
}
return nil
Expand Down
33 changes: 20 additions & 13 deletions cmd/keys.go
Expand Up @@ -8,6 +8,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/strangelove-ventures/lens/client"
)

const (
Expand Down Expand Up @@ -46,17 +47,18 @@ $ %s keys add ibc-0
$ %s keys add ibc-1 key2
$ %s k a ibc-2 testkey`, appName, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
var keyName string
if len(args) == 0 {
keyName = config.cl.Config.Key
keyName = cl.Config.Key
} else {
keyName = args[0]
}
if config.cl.KeyExists(keyName) {
if cl.KeyExists(keyName) {
return errKeyExists(keyName)
}

ko, err := config.cl.AddKey(keyName)
ko, err := cl.AddKey(keyName)
if err != nil {
return err
}
Expand Down Expand Up @@ -87,12 +89,13 @@ func keysRestoreCmd() *cobra.Command {
$ %s keys restore ibc-0 testkey "[mnemonic-words]"
$ %s k r ibc-1 faucet-key "[mnemonic-words]"`, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
keyName := args[1]
if config.cl.KeyExists(keyName) {
if cl.KeyExists(keyName) {
return errKeyExists(keyName)
}

address, err := config.cl.RestoreKey(keyName, args[2])
address, err := cl.RestoreKey(keyName, args[2])
if err != nil {
return err
}
Expand All @@ -118,8 +121,9 @@ $ %s keys delete ibc-0 -y
$ %s keys delete ibc-1 key2 -y
$ %s k d ibc-2 testkey`, appName, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
keyName := args[1]
if !config.cl.KeyExists(keyName) {
if !cl.KeyExists(keyName) {
return errKeyDoesntExist(keyName)
}

Expand All @@ -130,7 +134,7 @@ $ %s k d ibc-2 testkey`, appName, appName, appName)),
}
}

if err := config.cl.DeleteKey(keyName); err != nil {
if err := cl.DeleteKey(keyName); err != nil {
panic(err)
}

Expand Down Expand Up @@ -172,7 +176,8 @@ func keysListCmd() *cobra.Command {
$ %s keys list ibc-0
$ %s k l ibc-1`, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
info, err := config.cl.ListAddresses()
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
info, err := cl.ListAddresses()
if err != nil {
return err
}
Expand Down Expand Up @@ -203,17 +208,18 @@ $ %s keys show ibc-0
$ %s keys show ibc-1 key2
$ %s k s ibc-2 testkey`, appName, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
var keyName string
if len(args) == 0 {
keyName = config.cl.Config.Key
keyName = cl.Config.Key
} else {
keyName = args[0]
}
if !config.cl.KeyExists(keyName) {
if !cl.KeyExists(keyName) {
return errKeyDoesntExist(keyName)
}

address, err := config.cl.ShowAddress(keyName)
address, err := cl.ShowAddress(keyName)
if err != nil {
return err
}
Expand All @@ -237,12 +243,13 @@ func keysExportCmd() *cobra.Command {
$ %s keys export ibc-0 testkey
$ %s k e ibc-2 testkey`, appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {
cl := client.GetChainClientFromContext(cmd.Context(), config.DefaultChain)
keyName := args[1]
if !config.cl.KeyExists(keyName) {
if !cl.KeyExists(keyName) {
return errKeyDoesntExist(keyName)
}

info, err := config.cl.ExportPrivKeyArmor(keyName)
info, err := cl.ExportPrivKeyArmor(keyName)
if err != nil {
return err
}
Expand Down
41 changes: 41 additions & 0 deletions cmd/modules.go
@@ -0,0 +1,41 @@
package cmd

import (
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
authz "github.com/cosmos/cosmos-sdk/x/authz/module"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/capability"
"github.com/cosmos/cosmos-sdk/x/crisis"
"github.com/cosmos/cosmos-sdk/x/distribution"
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
feegrant "github.com/cosmos/cosmos-sdk/x/feegrant/module"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/upgrade"
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
)

var ModuleBasics = []module.AppModuleBasic{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this for encodings or decoding txs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both

auth.AppModuleBasic{},
authz.AppModuleBasic{},
bank.AppModuleBasic{},
capability.AppModuleBasic{},
// TODO: add osmosis governance proposal types here
// TODO: add other proposal types here
gov.NewAppModuleBasic(
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
),
crisis.AppModuleBasic{},
distribution.AppModuleBasic{},
feegrant.AppModuleBasic{},
mint.AppModuleBasic{},
params.AppModuleBasic{},
slashing.AppModuleBasic{},
staking.AppModuleBasic{},
upgrade.AppModuleBasic{},
}