Skip to content

Commit

Permalink
osmocli: parse Use field's arguments dynamically from a message (back…
Browse files Browse the repository at this point in the history
…port #6005)
  • Loading branch information
p0mvn committed Aug 30, 2023
1 parent cf69b87 commit 2926b97
Show file tree
Hide file tree
Showing 30 changed files with 314 additions and 107 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ Fixes mainnet bugs w/ incorrect accumulation sumtrees, and CL handling for a bal
* [#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
* [#6005](https://github.com/osmosis-labs/osmosis/pull/6005) osmocli: parse Use field's arguments dynamically

* [#6012](https://github.com/osmosis-labs/osmosis/pull/6012) chore: add autocomplete to makefile

### Minor improvements & Bug Fixes
Expand Down
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,7 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230703010110-ed4eb883f2a6 h1:
github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230703010110-ed4eb883f2a6/go.mod h1:9KGhMg+7ZWgZ50Wa/x8w/jN19O0TSqYLlqUj+2wwxLU=
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:YlmchqTmlwdWSmrRmXKR+PcU96ntOd8u10vTaTZdcNY=
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
<<<<<<< HEAD
github.com/osmosis-labs/osmosis/osmomath v0.0.6 h1:WNkVmeeudAqRFk5a4CChWsdxfiY/XLClT1i845L78ss=
github.com/osmosis-labs/osmosis/osmomath v0.0.6/go.mod h1:UlftwozB+QObT3o0YfkuuyL9fsVdgoWt0dm6J7MLYnU=
github.com/osmosis-labs/osmosis/osmoutils v0.0.6 h1:VI4wPzxXpdg5XEUaBugY9lADwxzw3H6lEJ0D+TZc4oE=
Expand All @@ -969,6 +970,18 @@ github.com/osmosis-labs/osmosis/x/epochs v0.0.2 h1:aEeXHGCSJMgMtAvCucsD2RSaWZ8lI
github.com/osmosis-labs/osmosis/x/epochs v0.0.2/go.mod h1:8dvJFHTpu6SIxmOaSaEw0tHnQ/Z9blf5qsF/ZJnMVHo=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.8 h1:BUGowctYQT0vdPgULrvwraEsW+sS6DnbzndTLKLmWVY=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.8/go.mod h1:sR0lpev9mcm9/9RY50T1og3UC3WpZAsINh/OmgrmFlg=
=======
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7 h1:NTR4zfrPMP4pJ5T60zyZumBAnTWmTAQX/JSZLGrM9jI=
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=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230807183608-16c217dedde5/go.mod h1:sR0lpev9mcm9/9RY50T1og3UC3WpZAsINh/OmgrmFlg=
>>>>>>> c9cbb9cb (osmocli: parse `Use` field's arguments dynamically from a message (#6005))
github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg=
github.com/osmosis-labs/wasmd v0.31.0-osmo-v16/go.mod h1:Rf8zW/GgBQyFRRB4s62VQHWA6sTlMFSjoDQQpoq64iI=
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
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"}

// 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/v18/x/concentrated-liquidity/client/queryproto"
cltypes "github.com/osmosis-labs/osmosis/v18/x/concentrated-liquidity/types"
lockuptypes "github.com/osmosis-labs/osmosis/v18/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
Loading

0 comments on commit 2926b97

Please sign in to comment.