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

osmocli: parse Use field's arguments dynamically from a message #6005

Merged
merged 24 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#5890](https://github.com/osmosis-labs/osmosis/pull/5890) feat: CreateCLPool & LinkCFMMtoCL pool into one gov-prop
* [#5959](https://github.com/osmosis-labs/osmosis/pull/5959) allow testing with different chain-id's in E2E testing
* [#5964](https://github.com/osmosis-labs/osmosis/pull/5964) fix e2e test concurrency bugs
* [#5948] (https://github.com/osmosis-labs/osmosis/pull/5948) Parameterizing Pool Type Information in Protorev
* [#6001](https://github.com/osmosis-labs/osmosis/pull/6001) feat: improve set-env CLI cmd\
* [#5948](https://github.com/osmosis-labs/osmosis/pull/5948) Parameterizing Pool Type Information in Protorev
* [#6001](https://github.com/osmosis-labs/osmosis/pull/6001) feat: improve set-env CLI cmd
* [#6005](https://github.com/osmosis-labs/osmosis/pull/6005) osmocli: parse Use field's arguments dynamically
* [#5953] (https://github.com/osmosis-labs/osmosis/pull/5953) Supporting two pool routes in ProtoRev
* [#6012](https://github.com/osmosis-labs/osmosis/pull/6012) chore: add autocomplete to makefile

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
github.com/ory/dockertest/v3 v3.10.0
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230807183608-16c217dedde5
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230819081851-a85e510a6965
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230807183608-16c217dedde5
github.com/pkg/errors v0.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,8 @@ github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7/go.mod h1:UlftwozB+QObT3o0YfkuuyL9fsVdgoWt0dm6J7MLYnU=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230807183608-16c217dedde5 h1:j4ifxomFROGROHalqWwX7VPDgxOPotMB1GiAWdb03i4=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230807183608-16c217dedde5/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230819081851-a85e510a6965 h1:K6tR6qLhz3bRUKBCsfpDu3JT0jyUELWZrhX3DBaqnjk=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230819081851-a85e510a6965/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM=
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo=
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304/go.mod h1:yPWoJTj5RKrXKUChAicp+G/4Ni/uVEpp27mi/FF/L9c=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230807183608-16c217dedde5 h1:clEegVniz0zTTBXKfg2oymKa63IYUxcrVXM+LtsvCpA=
Expand Down
48 changes: 48 additions & 0 deletions osmoutils/osmocli/dynamic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package osmocli

import (
"fmt"
"reflect"
"regexp"
"strings"

"github.com/gogo/protobuf/proto"

"github.com/osmosis-labs/osmosis/osmoutils"
)

type Descriptor interface {
GetCustomFlagOverrides() map[string]string
AttachToUse(str string)
}

// fields that are not provided as arguments
var nonAttachableFields []string = []string{"sender", "pagination", "owner", "admin"}
Copy link
Member Author

Choose a reason for hiding this comment

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

to reviewers: are there some other fields which should not be passed as arguments of cli commands?


// attachFieldsToUse extracts fields from reqP proto message and dynamically appends them into Use field
func attachFieldsToUse[reqP proto.Message](desc Descriptor) {
req := osmoutils.MakeNew[reqP]()
v := reflect.ValueOf(req).Type().Elem() // get underlying non-pointer struct
var useField string
for i := 0; i < v.NumField(); i++ {
fn := pascalToKebab(v.Field(i).Name)

// if a field is parsed from a flag, skip it
if desc.GetCustomFlagOverrides()[fn] != "" || osmoutils.Contains(nonAttachableFields, fn) {
continue
}

useField += fmt.Sprintf(" [%s]", fn)
}

desc.AttachToUse(useField)
}

// pascalToKebab converts PascalCase string to kebab-case string
func pascalToKebab(s string) string {
reg := regexp.MustCompile(`([a-z0-9])([A-Z])`)
s = reg.ReplaceAllString(s, `${1}-${2}`)

// Convert everything to lowercase
return strings.ToLower(s)
}
116 changes: 116 additions & 0 deletions osmoutils/osmocli/dynamic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package osmocli

import (
"testing"

"github.com/stretchr/testify/require"

clqueryproto "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/client/queryproto"
cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types"
lockuptypes "github.com/osmosis-labs/osmosis/v17/x/lockup/types"
)

// test-specific helper descriptor
type TestDescriptor interface {
Descriptor
GetUse() string
}

type TestQueryDescriptor struct {
*QueryDescriptor
}

func (tqd *TestQueryDescriptor) GetUse() string {
return tqd.Use
}

type TestTxCliDescriptor struct {
*TxCliDesc
}

func (ttxcd *TestTxCliDescriptor) GetUse() string {
return ttxcd.Use
}

func TestAttachFieldsToUse(t *testing.T) {
tests := map[string]struct {
desc TestDescriptor
attachFunc func(Descriptor)
expectedUse string
}{
"basic/TxCliDesc/attaches_2_args": {
desc: &TestTxCliDescriptor{
&TxCliDesc{
Use: "set-reward-receiver-address",
Short: "sets reward receiver address for the designated lock id",
Long: "sets reward receiver address for the designated lock id",
},
},
attachFunc: attachFieldsToUse[*lockuptypes.MsgSetRewardReceiverAddress],
expectedUse: "set-reward-receiver-address [lock-id] [reward-receiver]",
},
"basic/QueryDescriptor/attaches_1_arg": {
desc: &TestQueryDescriptor{
&QueryDescriptor{
Use: "pool-accumulator-rewards",
Short: "Query pool accumulator rewards",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} pool-accumulator-rewards 1`,
},
},
attachFunc: attachFieldsToUse[*clqueryproto.PoolAccumulatorRewardsRequest],
expectedUse: "pool-accumulator-rewards [pool-id]",
},
"ignore_pagination/QueryDescriptor/no_args": {
desc: &TestQueryDescriptor{
&QueryDescriptor{
Use: "pools",
Short: "Query pools",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} pools`,
},
},
attachFunc: attachFieldsToUse[*clqueryproto.PoolsRequest],
expectedUse: "pools",
},
"ignore_owner/TxCliDesc/attach_2_args": {
desc: &TestTxCliDescriptor{
&TxCliDesc{
Use: "lock-tokens",
Short: "lock tokens into lockup pool from user account",
},
},
attachFunc: attachFieldsToUse[*lockuptypes.MsgLockTokens],
expectedUse: "lock-tokens [duration] [coins]", // in osmosis, this command takes duration from a flag, but here it is just for testing purposes
},
"ignore_sender/TxCliDesc/attach_5_args": { // also tests that args are shown in kebab-case
desc: &TestTxCliDescriptor{
&TxCliDesc{
Use: "add-to-position",
Short: "add to an existing concentrated liquidity position",
Example: "osmosisd tx concentratedliquidity add-to-position 10 1000000000uosmo 10000000uion --from val --chain-id localosmosis -b block --keyring-backend test --fees 1000000uosmo",
},
},
attachFunc: attachFieldsToUse[*cltypes.MsgAddToPosition],
expectedUse: "add-to-position [position-id] [amount0] [amount1] [token-min-amount0] [token-min-amount1]",
},
"ignore_custom_flag_overrides/TxCliDesc/": {
desc: &TestTxCliDescriptor{
&TxCliDesc{
Use: "lock-tokens",
Short: "lock tokens into lockup pool from user account",
CustomFlagOverrides: map[string]string{
"duration": "duration",
},
},
},
attachFunc: attachFieldsToUse[*lockuptypes.MsgLockTokens],
expectedUse: "lock-tokens [coins]",
},
}

for _, tt := range tests {
tt.attachFunc(tt.desc)
require.Equal(t, tt.desc.GetUse(), tt.expectedUse)
}
}
13 changes: 13 additions & 0 deletions osmoutils/osmocli/query_cmd_wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ type QueryDescriptor struct {
numArgs int
}

var _ Descriptor = &QueryDescriptor{}

// Implement Descriptor interface
func (desc QueryDescriptor) GetCustomFlagOverrides() map[string]string {
return desc.CustomFlagOverrides
}

// Implement Descriptor interface
func (desc *QueryDescriptor) AttachToUse(str string) {
desc.Use += str
}

func QueryIndexCmd(moduleName string) *cobra.Command {
cmd := IndexCmd(moduleName)
cmd.Short = fmt.Sprintf("Querying commands for the %s module", moduleName)
Expand Down Expand Up @@ -89,6 +101,7 @@ func BuildQueryCli[reqP proto.Message, querier any](desc *QueryDescriptor, newQu
}
}

attachFieldsToUse[reqP](desc)
cmd := &cobra.Command{
Use: desc.Use,
Short: desc.Short,
Expand Down
14 changes: 14 additions & 0 deletions osmoutils/osmocli/tx_cmd_wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ type TxCliDesc struct {
CustomFieldParsers map[string]CustomFieldParserFn
}

var _ Descriptor = &TxCliDesc{}

// Implement Descriptor interface
func (desc TxCliDesc) GetCustomFlagOverrides() map[string]string {
return desc.CustomFlagOverrides
}

// Implement Descriptor interface
func (desc *TxCliDesc) AttachToUse(str string) {
desc.Use += str
}

func AddTxCmd[M sdk.Msg](cmd *cobra.Command, f func() (*TxCliDesc, M)) {
desc, _ := f()
subCmd := BuildTxCli[M](desc)
Expand All @@ -60,6 +72,8 @@ func BuildTxCli[M sdk.Msg](desc *TxCliDesc) *cobra.Command {
return ParseFieldsFromFlagsAndArgs[M](flagAdvice, flags, args)
}
}

attachFieldsToUse[M](desc)
return desc.BuildCommandCustomFn()
}

Expand Down
18 changes: 9 additions & 9 deletions x/concentrated-liquidity/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func GetQueryCmd() *cobra.Command {

func GetUserPositions() (*osmocli.QueryDescriptor, *queryproto.UserPositionsRequest) {
return &osmocli.QueryDescriptor{
Use: "user-positions [address]",
Use: "user-positions",
Short: "Query user's positions",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} user-positions osmo12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj`,
Expand All @@ -43,7 +43,7 @@ func GetUserPositions() (*osmocli.QueryDescriptor, *queryproto.UserPositionsRequ

func GetPositionById() (*osmocli.QueryDescriptor, *queryproto.PositionByIdRequest) {
return &osmocli.QueryDescriptor{
Use: "position-by-id [positionID]",
Use: "position-by-id",
Short: "Query position by ID",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} position-by-id 53`,
Expand All @@ -62,7 +62,7 @@ func GetCmdPools() (*osmocli.QueryDescriptor, *queryproto.PoolsRequest) {

func GetClaimableSpreadRewards() (*osmocli.QueryDescriptor, *queryproto.ClaimableSpreadRewardsRequest) {
return &osmocli.QueryDescriptor{
Use: "claimable-spread-rewards [positionID]",
Use: "claimable-spread-rewards",
Short: "Query claimable spread rewards",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} claimable-spread-rewards 53`,
Expand All @@ -71,7 +71,7 @@ func GetClaimableSpreadRewards() (*osmocli.QueryDescriptor, *queryproto.Claimabl

func GetClaimableIncentives() (*osmocli.QueryDescriptor, *queryproto.ClaimableIncentivesRequest) {
return &osmocli.QueryDescriptor{
Use: "claimable-incentives [positionID]",
Use: "claimable-incentives",
Short: "Query claimable incentives",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} claimable-incentives 53`,
Expand All @@ -80,7 +80,7 @@ func GetClaimableIncentives() (*osmocli.QueryDescriptor, *queryproto.ClaimableIn

func GetIncentiveRecords() (*osmocli.QueryDescriptor, *queryproto.IncentiveRecordsRequest) {
return &osmocli.QueryDescriptor{
Use: "incentive-records [poolId]",
Use: "incentive-records",
Short: "Query incentive records for a given pool",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} incentive-records 1`,
Expand All @@ -89,7 +89,7 @@ func GetIncentiveRecords() (*osmocli.QueryDescriptor, *queryproto.IncentiveRecor

func GetCFMMPoolIdLinkFromConcentratedPoolId() (*osmocli.QueryDescriptor, *queryproto.CFMMPoolIdLinkFromConcentratedPoolIdRequest) {
return &osmocli.QueryDescriptor{
Use: "cfmm-pool-link-from-cl [poolId]",
Use: "cfmm-pool-link-from-cl",
Short: "Query cfmm pool id link from concentrated pool id",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} cfmm-pool-link-from-cl 1`,
Expand All @@ -107,7 +107,7 @@ func GetTotalLiquidity() (*osmocli.QueryDescriptor, *queryproto.GetTotalLiquidit

func GetTickLiquidityNetInDirection() (*osmocli.QueryDescriptor, *queryproto.LiquidityNetInDirectionRequest) {
return &osmocli.QueryDescriptor{
Use: "liquidity-net-in-direction [pool-id] [token-in-denom] [start-tick] [use-current-tick] [bound-tick] [use-no-bound]",
Use: "liquidity-net-in-direction",
Short: "Query liquidity net in direction",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} 4 uosmo "[-18000000]" true "[-9000000]" true`,
Expand All @@ -116,7 +116,7 @@ func GetTickLiquidityNetInDirection() (*osmocli.QueryDescriptor, *queryproto.Liq

func GetPoolAccumulatorRewards() (*osmocli.QueryDescriptor, *queryproto.PoolAccumulatorRewardsRequest) {
return &osmocli.QueryDescriptor{
Use: "pool-accumulator-rewards [pool-id]",
Use: "pool-accumulator-rewards",
Short: "Query pool accumulator rewards",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} pool-accumulator-rewards 1`,
Expand All @@ -125,7 +125,7 @@ func GetPoolAccumulatorRewards() (*osmocli.QueryDescriptor, *queryproto.PoolAccu

func GetTickAccumulatorTrackers() (*osmocli.QueryDescriptor, *queryproto.TickAccumulatorTrackersRequest) {
return &osmocli.QueryDescriptor{
Use: "tick-accumulator-trackers [pool-id] [tick-index]",
Use: "tick-accumulator-trackers",
Short: "Query tick accumulator trackers",
Long: `{{.Short}}{{.ExampleHeader}}
{{.CommandPrefix}} tick-accumulator-trackers 1 "[-18000000]"`,
Expand Down
14 changes: 7 additions & 7 deletions x/concentrated-liquidity/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var poolIdFlagOverride = map[string]string{

func NewCreateConcentratedPoolCmd() (*osmocli.TxCliDesc, *clmodel.MsgCreateConcentratedPool) {
return &osmocli.TxCliDesc{
Use: "create-pool [denom-0] [denom-1] [tick-spacing] [spread-factor]",
Use: "create-pool",
Short: "create a concentrated liquidity pool with the given denom pair, tick spacing, and spread factor",
Long: "denom-1 (the quote denom), tick spacing, and spread factors must all be authorized by the concentrated liquidity module",
Example: "osmosisd tx concentratedliquidity create-pool uion uosmo 100 0.01 --from val --chain-id osmosis-1 -b block --keyring-backend test --fees 1000uosmo",
Expand All @@ -47,47 +47,47 @@ func NewCreateConcentratedPoolCmd() (*osmocli.TxCliDesc, *clmodel.MsgCreateConce

func NewCreatePositionCmd() (*osmocli.TxCliDesc, *types.MsgCreatePosition) {
return &osmocli.TxCliDesc{
Use: "create-position [pool-id] [lower-tick] [upper-tick] [tokensProvided] [token-0-min-amount] [token-1-min-amount]",
Use: "create-position",
Short: "create or add to existing concentrated liquidity position",
Example: "osmosisd tx concentratedliquidity create-position 1 \"[-69082]\" 69082 10000uosmo,10000uion 0 0 --from val --chain-id osmosis-1 -b block --keyring-backend test --fees 1000uosmo",
}, &types.MsgCreatePosition{}
}

func NewAddToPositionCmd() (*osmocli.TxCliDesc, *types.MsgAddToPosition) {
return &osmocli.TxCliDesc{
Use: "add-to-position [position-id] [token-0] [token-1]",
Use: "add-to-position",
Short: "add to an existing concentrated liquidity position",
Example: "osmosisd tx concentratedliquidity add-to-position 10 1000000000uosmo 10000000uion --from val --chain-id localosmosis -b block --keyring-backend test --fees 1000000uosmo",
}, &types.MsgAddToPosition{}
}

func NewWithdrawPositionCmd() (*osmocli.TxCliDesc, *types.MsgWithdrawPosition) {
return &osmocli.TxCliDesc{
Use: "withdraw-position [position-id] [liquidity]",
Use: "withdraw-position",
Short: "withdraw from an existing concentrated liquidity position",
Example: "osmosisd tx concentratedliquidity withdraw-position 1 1000 --from val --chain-id localosmosis --keyring-backend=test --fees=1000uosmo",
}, &types.MsgWithdrawPosition{}
}

func NewCollectSpreadRewardsCmd() (*osmocli.TxCliDesc, *types.MsgCollectSpreadRewards) {
return &osmocli.TxCliDesc{
Use: "collect-spread-rewards [position-ids]",
Use: "collect-spread-rewards",
Short: "collect spread rewards from liquidity position(s)",
Example: "osmosisd tx concentratedliquidity collect-spread-rewards 998 --from val --chain-id localosmosis -b block --keyring-backend test --fees 1000000uosmo",
}, &types.MsgCollectSpreadRewards{}
}

func NewCollectIncentivesCmd() (*osmocli.TxCliDesc, *types.MsgCollectIncentives) {
return &osmocli.TxCliDesc{
Use: "collect-incentives [position-ids]",
Use: "collect-incentives",
Short: "collect incentives from liquidity position(s)",
Example: "osmosisd tx concentratedliquidity collect-incentives 1 --from val --chain-id localosmosis -b block --keyring-backend test --fees 10000uosmo",
}, &types.MsgCollectIncentives{}
}

func NewFungifyChargedPositionsCmd() (*osmocli.TxCliDesc, *types.MsgFungifyChargedPositions) {
return &osmocli.TxCliDesc{
Use: "fungify-positions [position-ids]",
Use: "fungify-positions",
Short: "Combine fully charged positions within the same range into a new single fully charged position",
Example: "osmosisd tx concentratedliquidity fungify-positions 1,2 --from val --keyring-backend test -b=block --chain-id=localosmosis --gas=1000000 --fees 20000uosmo",
}, &types.MsgFungifyChargedPositions{}
Expand Down
Loading