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(cmd/network): add --mainnet and --total-supply flags to the publish command #2122

Merged
merged 13 commits into from
Mar 10, 2022
Merged
2 changes: 1 addition & 1 deletion starport/cmd/network_campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ func NewNetworkCampaign() *cobra.Command {
Use: "campaign",
Short: "Handle campaigns",
}

c.AddCommand(
NewNetworkCampaignPublish(),
NewNetworkCampaignList(),
NewNetworkCampaignShow(),
NewNetworkCampaignUpdate(),
Expand Down
58 changes: 58 additions & 0 deletions starport/cmd/network_campaign_publish.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package starportcmd

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"

"github.com/tendermint/starport/starport/pkg/clispinner"
)

const (
flagMetadata = "metadata"
)

// NewNetworkCampaignPublish returns a new command to publish a new campaigns on Starport Network.
func NewNetworkCampaignPublish() *cobra.Command {
c := &cobra.Command{
Use: "create [name] [total-supply]",
Short: "Create a campaign",
Args: cobra.ExactArgs(2),
RunE: networkCampaignPublishHandler,
}
c.Flags().String(flagMetadata, "", "Add a metada to the chain")
c.Flags().AddFlagSet(flagNetworkFrom())
c.Flags().AddFlagSet(flagSetKeyringBackend())
c.Flags().AddFlagSet(flagSetHome())
return c
}

func networkCampaignPublishHandler(cmd *cobra.Command, args []string) error {
nb, err := newNetworkBuilder(cmd)
if err != nil {
return err
}
defer nb.Cleanup()

// parse launch ID
totalSupply, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}

n, err := nb.Network()
if err != nil {
return err
}

metadata, _ := cmd.Flags().GetString(flagMetadata)
campaignID, err := n.CreateCampaign(args[0], metadata, totalSupply)
if err != nil {
return err
}

nb.Spinner.Stop()
fmt.Printf("%s Campaign ID: %d \n", clispinner.Bullet, campaignID)
return nil
}
32 changes: 31 additions & 1 deletion starport/cmd/network_chain_publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
flagCampaign = "campaign"
flagNoCheck = "no-check"
flagChainID = "chain-id"
flagMainnet = "mainnet"
)

// NewNetworkChainPublish returns a new command to publish a new chain to start a new network.
Expand All @@ -45,6 +46,7 @@ func NewNetworkChainPublish() *cobra.Command {
c.Flags().String(flagCampaignMetadata, "", "Add a campaign metadata")
c.Flags().String(flagCampaignTotalShares, "", "Add a shares supply for the campaign")
c.Flags().String(flagCampaignTotalSupply, "", "Add a total of the mainnet of a campaign")
c.Flags().Bool(flagMainnet, false, "Initialize a mainnet campaign")
c.Flags().AddFlagSet(flagNetworkFrom())
c.Flags().AddFlagSet(flagSetKeyringBackend())
c.Flags().AddFlagSet(flagSetHome())
Expand All @@ -66,8 +68,21 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error {
campaignMetadata, _ = cmd.Flags().GetString(flagCampaignMetadata)
campaignTotalSharesStr, _ = cmd.Flags().GetString(flagCampaignTotalShares)
campaignTotalSupplyStr, _ = cmd.Flags().GetString(flagCampaignTotalSupply)
isMainnet, _ = cmd.Flags().GetBool(flagMainnet)
)

if campaign != 0 && campaignTotalSupplyStr != "" {
return fmt.Errorf("%s and %s flags cannot be set together", flagCampaign, flagCampaignTotalSupply)
}
if isMainnet && campaign == 0 && campaignTotalSupplyStr == "" {
return fmt.Errorf(
"%s flag requires one of the %s or %s flags to be set",
flagMainnet,
flagCampaign,
flagCampaignTotalSupply,
)
}

totalShares, err := campaigntypes.NewShares(campaignTotalSharesStr)
if err != nil {
return err
Expand Down Expand Up @@ -128,13 +143,25 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error {

if campaign != 0 {
publishOptions = append(publishOptions, network.WithCampaign(campaign))
} else if campaignTotalSupplyStr != "" {
totalSupply, err := sdk.ParseCoinsNormalized(campaignTotalSupplyStr)
if err != nil {
return err
}
if !totalSupply.Empty() {
publishOptions = append(publishOptions, network.WithTotalSupply(totalSupply))
}
}

// use custom chain id if given.
if chainID != "" {
publishOptions = append(publishOptions, network.WithChainID(chainID))
}

if isMainnet {
publishOptions = append(publishOptions, network.Mainnet())
}

if !totalSupply.Empty() {
publishOptions = append(publishOptions, network.WithTotalSupply(totalSupply))
}
Expand All @@ -154,7 +181,7 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error {
return err
}

launchID, campaignID, err := n.Publish(cmd.Context(), c, publishOptions...)
launchID, campaignID, mainnetID, err := n.Publish(cmd.Context(), c, publishOptions...)
if err != nil {
return err
}
Expand All @@ -164,6 +191,9 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error {
fmt.Printf("%s Network published \n", clispinner.OK)
fmt.Printf("%s Launch ID: %d \n", clispinner.Bullet, launchID)
fmt.Printf("%s Campaign ID: %d \n", clispinner.Bullet, campaignID)
if isMainnet {
fmt.Printf("%s Mainnet ID: %d \n", clispinner.Bullet, mainnetID)
}

return nil
}
57 changes: 56 additions & 1 deletion starport/services/network/campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ func (n Network) Campaigns(ctx context.Context) ([]networktypes.Campaign, error)
var campaigns []networktypes.Campaign

n.ev.Send(events.New(events.StatusOngoing, "Fetching campaigns information"))
res, err := campaigntypes.NewQueryClient(n.cosmos.Context).CampaignAll(ctx, &campaigntypes.QueryAllCampaignRequest{})
res, err := campaigntypes.NewQueryClient(n.cosmos.Context).
CampaignAll(ctx, &campaigntypes.QueryAllCampaignRequest{})
if err != nil {
return campaigns, err
}
Expand All @@ -82,6 +83,60 @@ func (n Network) Campaigns(ctx context.Context) ([]networktypes.Campaign, error)
return campaigns, nil
}

// CreateCampaign creates a campaign in Starport Network
func (n Network) CreateCampaign(name, metadata string, totalSupply sdk.Coins) (uint64, error) {
n.ev.Send(events.New(events.StatusOngoing, fmt.Sprintf("Creating campaign %s", name)))

msgCreateCampaign := campaigntypes.NewMsgCreateCampaign(
n.account.Address(networktypes.SPN),
name,
totalSupply,
[]byte(metadata),
)
res, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateCampaign)
if err != nil {
return 0, err
}

var createCampaignRes campaigntypes.MsgCreateCampaignResponse
if err := res.Decode(&createCampaignRes); err != nil {
return 0, err
}

return createCampaignRes.CampaignID, nil
}

// InitializeMainnet Initialize the mainnet of the campaign.
func (n Network) InitializeMainnet(
campaignID uint64,
sourceURL,
sourceHash string,
mainnetChainID string,
) (uint64, error) {
n.ev.Send(events.New(events.StatusOngoing, "Initializing the mainnet campaign"))
msg := campaigntypes.NewMsgInitializeMainnet(
n.account.Address(networktypes.SPN),
campaignID,
sourceURL,
sourceHash,
mainnetChainID,
)

res, err := n.cosmos.BroadcastTx(n.account.Name, msg)
if err != nil {
return 0, err
}

var initMainnetRes campaigntypes.MsgInitializeMainnetResponse
if err := res.Decode(&initMainnetRes); err != nil {
return 0, err
}

n.ev.Send(events.New(events.StatusDone, fmt.Sprintf("Campaign %d initialized on mainnet", campaignID)))

return initMainnetRes.MainnetID, nil
}

// UpdateCampaign updates the campaign name or metadata
func (n Network) UpdateCampaign(
id uint64,
Expand Down
55 changes: 28 additions & 27 deletions starport/services/network/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

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

campaigntypes "github.com/tendermint/spn/x/campaign/types"
launchtypes "github.com/tendermint/spn/x/launch/types"
profiletypes "github.com/tendermint/spn/x/profile/types"
Expand All @@ -21,9 +20,10 @@ type publishOptions struct {
chainID string
campaignID uint64
noCheck bool
metadata []byte
metadata string
totalShares campaigntypes.Shares
totalSupply sdk.Coins
mainnet bool
}

// PublishOption configures chain creation.
Expand Down Expand Up @@ -67,7 +67,7 @@ func WithTotalShares(totalShares campaigntypes.Shares) PublishOption {
// WithMetadata provides a meta data proposal to update the campaign.
func WithMetadata(metadata string) PublishOption {
return func(c *publishOptions) {
c.metadata = []byte(metadata)
c.metadata = metadata
}
}

Expand All @@ -78,8 +78,15 @@ func WithTotalSupply(totalSupply sdk.Coins) PublishOption {
}
}

// Mainnet initialize a published chain into the mainnet
func Mainnet() PublishOption {
return func(o *publishOptions) {
o.mainnet = true
}
}

// Publish submits Genesis to SPN to announce a new network.
func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption) (launchID, campaignID uint64, err error) {
func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption) (launchID, campaignID, mainnetID uint64, err error) {
o := publishOptions{}
for _, apply := range options {
apply(&o)
Expand All @@ -90,15 +97,15 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption)
// if the initial genesis is a genesis URL and no check are performed, we simply fetch it and get its hash.
if o.noCheck && o.genesisURL != "" {
if _, genesisHash, err = cosmosutil.GenesisAndHashFromURL(ctx, o.genesisURL); err != nil {
return 0, 0, err
return 0, 0, 0, err
}
}

chainID := o.chainID
if chainID == "" {
chainID, err = c.ID()
if err != nil {
return 0, 0, err
return 0, 0, 0, err
}
}

Expand All @@ -120,10 +127,10 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption)
"",
)
if _, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateCoordinator); err != nil {
return 0, 0, err
return 0, 0, 0, err
}
} else if err != nil {
return 0, 0, err
return 0, 0, 0, err
}

if campaignID != 0 {
Expand All @@ -133,25 +140,13 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption)
CampaignID: o.campaignID,
})
if err != nil {
return 0, 0, err
return 0, 0, 0, err
}
} else {
msgCreateCampaign := campaigntypes.NewMsgCreateCampaign(
coordinatorAddress,
c.Name(),
o.totalSupply,
o.metadata,
)
res, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateCampaign)
campaignID, err = n.CreateCampaign(c.Name(), o.metadata, o.totalSupply)
if err != nil {
return 0, 0, err
}

var createCampaignRes campaigntypes.MsgCreateCampaignResponse
if err := res.Decode(&createCampaignRes); err != nil {
return 0, 0, err
return 0, 0, 0, err
}
campaignID = createCampaignRes.CampaignID
}

msgCreateChain := launchtypes.NewMsgCreateChain(
Expand All @@ -167,19 +162,25 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption)
)
res, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateChain)
if err != nil {
return 0, 0, err
return 0, 0, 0, err
}

var createChainRes launchtypes.MsgCreateChainResponse
if err := res.Decode(&createChainRes); err != nil {
return 0, 0, err
return 0, 0, 0, err
}

if !o.totalShares.Empty() {
if err := n.UpdateCampaign(campaignID, WithCampaignTotalShares(o.totalShares)); err != nil {
return createChainRes.LaunchID, campaignID, err
return 0, 0, 0, err
}
}

return createChainRes.LaunchID, campaignID, nil
if o.mainnet {
mainnetID, err = n.InitializeMainnet(campaignID, c.SourceURL(), c.SourceHash(), chainID)
if err != nil {
return 0, 0, 0, err
}
}
return createChainRes.LaunchID, campaignID, mainnetID, nil
}