Skip to content

Commit

Permalink
feat(cmd): Add non-interactive mode network add-local, paratime add
Browse files Browse the repository at this point in the history
  • Loading branch information
amela committed Sep 10, 2024
1 parent eacb0ef commit 271db45
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 121 deletions.
144 changes: 90 additions & 54 deletions cmd/network/add_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,103 @@ import (
"fmt"

"github.com/spf13/cobra"
flag "github.com/spf13/pflag"

"github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"

"github.com/oasisprotocol/cli/cmd/common"
cliConfig "github.com/oasisprotocol/cli/config"
)

var addLocalCmd = &cobra.Command{
Use: "add-local <name> <rpc-endpoint>",
Short: "Add a new local network",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
cfg := cliConfig.Global()
name, rpc := args[0], args[1]

net := config.Network{
RPC: rpc,
}
// Validate initial network configuration early.
cobra.CheckErr(config.ValidateIdentifier(name))
if !net.IsLocalRPC() {
cobra.CheckErr(fmt.Errorf("rpc-endpoint '%s' is not local", rpc))
}

// Connect to the network and query the chain context.
ctx := context.Background()
conn, err := connection.ConnectNoVerify(ctx, &net)
cobra.CheckErr(err)

chainContext, err := conn.Consensus().GetChainContext(ctx)
cobra.CheckErr(err)
net.ChainContext = chainContext
cobra.CheckErr(net.Validate())

// With a very high probability, the user is going to be
// adding a local endpoint for an existing network, so try
// to clone config details from any of the hardcoded
// defaults.
var clonedDefault bool
for _, defaultNet := range config.DefaultNetworks.All {
if defaultNet.ChainContext != chainContext {
continue
var (
symbol string
numDecimals uint
description string

addLocalCmd = &cobra.Command{
Use: "add-local <name> <rpc-endpoint>",
Short: "Add a new local network",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
cfg := cliConfig.Global()
name, rpc := args[0], args[1]

net := config.Network{
RPC: rpc,
}
// Validate initial network configuration early.
cobra.CheckErr(config.ValidateIdentifier(name))
if !net.IsLocalRPC() {
cobra.CheckErr(fmt.Errorf("rpc-endpoint '%s' is not local", rpc))
}

// Connect to the network and query the chain context.
ctx := context.Background()
conn, err := connection.ConnectNoVerify(ctx, &net)
cobra.CheckErr(err)

chainContext, err := conn.Consensus().GetChainContext(ctx)
cobra.CheckErr(err)
net.ChainContext = chainContext
cobra.CheckErr(net.Validate())

// With a very high probability, the user is going to be
// adding a local endpoint for an existing network, so try
// to clone config details from any of the hardcoded
// defaults.
var clonedDefault bool
for _, defaultNet := range config.DefaultNetworks.All {
if defaultNet.ChainContext != chainContext {
continue
}

// Yep.
net.Denomination = defaultNet.Denomination
net.ParaTimes = defaultNet.ParaTimes
clonedDefault = true
break
}

if symbol != "" {
net.Denomination.Symbol = symbol
}

if numDecimals != 0 {
net.Denomination.Decimals = uint8(numDecimals)
}

if description != "" {
net.Description = description
}

// Yep.
net.Denomination = defaultNet.Denomination
net.ParaTimes = defaultNet.ParaTimes
clonedDefault = true
break
}

// If we failed to crib details from a hardcoded config,
// ask the user.
if !clonedDefault {
networkDetailsFromSurvey(&net)
}

err = cfg.Networks.Add(name, &net)
cobra.CheckErr(err)

err = cfg.Save()
cobra.CheckErr(err)
},
// If we failed to crib details from a hardcoded config,
// and user did not set -y flag ask the user.
if !clonedDefault && !common.GetAnswerYes() {
networkDetailsFromSurvey(&net)
}

err = cfg.Networks.Add(name, &net)
cobra.CheckErr(err)

err = cfg.Save()
cobra.CheckErr(err)
},
}
)

func init() {
addLocalCmd.Flags().AddFlagSet(common.AnswerYesFlag)

symbolFlag := flag.NewFlagSet("", flag.ContinueOnError)
symbolFlag.StringVar(&symbol, "symbol", "", "network's symbol")
addLocalCmd.Flags().AddFlagSet(symbolFlag)

numDecimalsFlag := flag.NewFlagSet("", flag.ContinueOnError)
numDecimalsFlag.UintVar(&numDecimals, "num-decimals", 0, "network's number of decimals")
addLocalCmd.Flags().AddFlagSet(numDecimalsFlag)

descriptionFlag := flag.NewFlagSet("", flag.ContinueOnError)
descriptionFlag.StringVar(&description, "description", "", "network's description")
addLocalCmd.Flags().AddFlagSet(descriptionFlag)
}
174 changes: 110 additions & 64 deletions cmd/paratime/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,121 @@ import (

"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"

"github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"

"github.com/oasisprotocol/cli/cmd/common"
cliConfig "github.com/oasisprotocol/cli/config"
)

var addCmd = &cobra.Command{
Use: "add <network> <name> <id>",
Short: "Add a new ParaTime",
Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) {
cfg := cliConfig.Global()
network, name, id := args[0], args[1], args[2]

net, exists := cfg.Networks.All[network]
if !exists {
cobra.CheckErr(fmt.Errorf("network '%s' does not exist", network))
}

pt := config.ParaTime{
ID: id,
}
// Validate initial paratime configuration early.
cobra.CheckErr(config.ValidateIdentifier(name))
cobra.CheckErr(pt.Validate())

// Ask user for some additional parameters.
questions := []*survey.Question{
{
Name: "description",
Prompt: &survey.Input{Message: "Description:"},
},
{
Name: "symbol",
Prompt: &survey.Input{
Message: "Denomination symbol:",
Default: net.Denomination.Symbol,
},
},
{
Name: "decimals",
Prompt: &survey.Input{
Message: "Denomination decimal places:",
Default: fmt.Sprintf("%d", net.Denomination.Decimals),
var (
symbol string
numDecimals uint
description string

addCmd = &cobra.Command{
Use: "add <network> <name> <id>",
Short: "Add a new ParaTime",
Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) {
cfg := cliConfig.Global()
network, name, id := args[0], args[1], args[2]

net, exists := cfg.Networks.All[network]
if !exists {
cobra.CheckErr(fmt.Errorf("network '%s' does not exist", network))
}

pt := config.ParaTime{
ID: id,
}
// Validate initial paratime configuration early.
cobra.CheckErr(config.ValidateIdentifier(name))
cobra.CheckErr(pt.Validate())

paratimeInfo := struct {
Description string
Symbol string
Decimals uint8
}{
Symbol: net.Denomination.Symbol,
Decimals: net.Denomination.Decimals,
}

if symbol != "" {
paratimeInfo.Symbol = symbol
}

if numDecimals != 0 {
paratimeInfo.Decimals = uint8(numDecimals)
}

if description != "" {
paratimeInfo.Description = description
}

if !common.GetAnswerYes() {
// Ask user for some additional parameters.
questions := []*survey.Question{
{
Name: "description",
Prompt: &survey.Input{
Message: "Description:",
Default: paratimeInfo.Description,
},
},
{
Name: "symbol",
Prompt: &survey.Input{
Message: "Denomination symbol:",
Default: paratimeInfo.Symbol,
},
},
{
Name: "decimals",
Prompt: &survey.Input{
Message: "Denomination decimal places:",
Default: fmt.Sprintf("%d", paratimeInfo.Decimals),
},
Validate: survey.Required,
},
}

err := survey.Ask(questions, &paratimeInfo)
cobra.CheckErr(err)
}

pt.Description = paratimeInfo.Description
pt.Denominations = map[string]*config.DenominationInfo{
config.NativeDenominationKey: {
Symbol: paratimeInfo.Symbol,
Decimals: paratimeInfo.Decimals,
},
Validate: survey.Required,
},
}
answers := struct {
Description string
Symbol string
Decimals uint8
}{}
err := survey.Ask(questions, &answers)
cobra.CheckErr(err)

pt.Description = answers.Description
pt.Denominations = map[string]*config.DenominationInfo{
config.NativeDenominationKey: {
Symbol: answers.Symbol,
Decimals: answers.Decimals,
},
}
pt.ConsensusDenomination = config.NativeDenominationKey // TODO: Make this configurable.

err = net.ParaTimes.Add(name, &pt)
cobra.CheckErr(err)

err = cfg.Save()
cobra.CheckErr(err)
},
}
pt.ConsensusDenomination = config.NativeDenominationKey // TODO: Make this configurable.

err := net.ParaTimes.Add(name, &pt)
cobra.CheckErr(err)

err = cfg.Save()
cobra.CheckErr(err)
},
}
)

func init() {
addCmd.Flags().AddFlagSet(common.AnswerYesFlag)

symbolFlag := flag.NewFlagSet("", flag.ContinueOnError)
symbolFlag.StringVar(&symbol, "symbol", "", "paratime's symbol")
addCmd.Flags().AddFlagSet(symbolFlag)

numDecimalsFlag := flag.NewFlagSet("", flag.ContinueOnError)
numDecimalsFlag.UintVar(&numDecimals, "num-decimals", 0, "paratime's number of decimals")
addCmd.Flags().AddFlagSet(numDecimalsFlag)

descriptionFlag := flag.NewFlagSet("", flag.ContinueOnError)
descriptionFlag.StringVar(&description, "description", "", "paratime's description")
addCmd.Flags().AddFlagSet(descriptionFlag)
}
16 changes: 13 additions & 3 deletions docs/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,23 @@ For Unix sockets, use:

`network add-local <name> <rpc-endpoint>` command can be used if you are
running `oasis-node` on your local machine. In this case, Oasis CLI will
autodetect the native token symbol and decimal places, the chain domain
separation context and registered ParaTimes.
autodetect the chain domain separation context. For the Oasis Mainnet and
Testnet chains, the native token symbol, the number of decimal places and
registered ParaTimes will automatically be predefined. Otherwise, the Oasis CLI
will ask you to enter them.

```
```shell
oasis network add-local testnet_local unix:/node_testnet/data/internal.sock
```

To override the defaults, you can pass `--num-decimals`, `--symbol` and
`--description` parameters. This is especially useful, if you are running the
command in a [non-interactive mode](account.md#y):

```shell
oasis network add-local testnet_local unix:/node_testnet/data/internal.sock --num-decimals 9 --symbol TEST --description "Work machine - Localnet" -y
```

## List Networks {#list}

Invoke `network list` to list all configured networks.
Expand Down
7 changes: 7 additions & 0 deletions docs/paratime.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ oasis paratime add testnet sapphire2 0000000000000000000000000000000000000000000
? Denomination decimal places: 18
```

You can also enable [non-interactive mode](account.md#y) and pass
`--num-decimals`, `--symbol` and `--description` parameters directly:

```shell
oasis paratime add testnet sapphire2 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6d --num-decimals 18 --symbol TEST --description "Testnet Sapphire 2" -y
```

:::danger Decimal places of the native and ParaTime token may differ!

Emerald and Sapphire use **18 decimals** for compatibility with
Expand Down

0 comments on commit 271db45

Please sign in to comment.